From 2d3cd80303d7141bbdf8369f55a700232e9ae9c9 Mon Sep 17 00:00:00 2001 From: Mirko Vogt Date: Tue, 18 Aug 2009 18:02:38 +0200 Subject: [PATCH] drop out all mtd-related changes made by ingenic --- .../drivers/mtd/nand/jz4740_nand.c | 1038 --------- .../drivers/mtd/nand/jz4750_nand.c | 1785 ---------------- .../patches-2.6.27/001-ingenic-patchset.patch | 1887 ----------------- 3 files changed, 4710 deletions(-) delete mode 100755 target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4740_nand.c delete mode 100755 target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4750_nand.c diff --git a/target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4740_nand.c b/target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4740_nand.c deleted file mode 100755 index 04db59d4c..000000000 --- a/target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4740_nand.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * linux/drivers/mtd/nand/jz4740_nand.c - * - * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. - * - * Ingenic JZ4740 NAND driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define NAND_DATA_PORT1 0xB8000000 /* read-write area in static bank 1 */ -#define NAND_DATA_PORT2 0xB4000000 /* read-write area in static bank 2 */ -#define NAND_DATA_PORT3 0xAC000000 /* read-write area in static bank 3 */ -#define NAND_DATA_PORT4 0xA8000000 /* read-write area in static bank 4 */ - -#define PAR_SIZE 9 - -#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) -#define __nand_disable() (REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1) - -#define __nand_ecc_enable() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST ) -#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE) - -#define __nand_select_hm_ecc() (REG_EMC_NFECR &= ~EMC_NFECR_RS ) -#define __nand_select_rs_ecc() (REG_EMC_NFECR |= EMC_NFECR_RS) - -#define __nand_read_hm_ecc() (REG_EMC_NFECC & 0x00ffffff) - -#define __nand_rs_ecc_encoding() (REG_EMC_NFECR |= EMC_NFECR_RS_ENCODING) -#define __nand_rs_ecc_decoding() (REG_EMC_NFECR &= ~EMC_NFECR_RS_ENCODING) -#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF)) -#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF)) - -/* - * MTD structure for JzSOC board - */ -static struct mtd_info *jz_mtd = NULL; -extern struct mtd_info *jz_mtd1; -extern char all_use_planes; -extern int global_page; /* for two-plane operations */ - -/* - * Define partitions for flash devices - */ -#ifdef CONFIG_JZ4740_PAVO -static struct mtd_partition partition_info[] = { - { name: "NAND BOOT partition", - offset: 0 * 0x100000, - size: 4 * 0x100000, - use_planes: 0 }, - { name: "NAND KERNEL partition", - offset: 4 * 0x100000, - size: 4 * 0x100000, - use_planes: 0 }, - { name: "NAND ROOTFS partition", - offset: 8 * 0x100000, - size: 120 * 0x100000, - use_planes: 0 }, - { name: "NAND DATA1 partition", - offset: 128 * 0x100000, - size: 128 * 0x100000, - use_planes: 1 }, - { name: "NAND DATA2 partition", - offset: 256 * 0x100000, - size: 256 * 0x100000, - use_planes: 1 }, - { name: "NAND VFAT partition", - offset: 512 * 0x100000, - size: 512 * 0x100000, - use_planes: 1 }, -}; - - -/* Define max reserved bad blocks for each partition. - * This is used by the mtdblock-jz.c NAND FTL driver only. - * - * The NAND FTL driver reserves some good blocks which can't be - * seen by the upper layer. When the bad block number of a partition - * exceeds the max reserved blocks, then there is no more reserved - * good blocks to be used by the NAND FTL driver when another bad - * block generated. - */ -static int partition_reserved_badblocks[] = { - 2, /* reserved blocks of mtd0 */ - 2, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10, /* reserved blocks of mtd3 */ - 20, /* reserved blocks of mtd4 */ - 20}; /* reserved blocks of mtd5 */ -#endif /* CONFIG_JZ4740_PAVO */ - -#ifdef CONFIG_JZ4740_LEO -static struct mtd_partition partition_info[] = { - { name: "NAND BOOT partition", - offset: 0 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND KERNEL partition", - offset: 4 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND ROOTFS partition", - offset: 8 * 0x100000, - size: 56 * 0x100000 }, - { name: "NAND VFAT partition", - offset: 64 * 0x100000, - size: 64 * 0x100000 }, -}; -static int partition_reserved_badblocks[] = { - 2, /* reserved blocks of mtd0 */ - 2, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10}; /* reserved blocks of mtd3 */ -#endif /* CONFIG_JZ4740_LEO */ - -#ifdef CONFIG_JZ4740_LYRA -static struct mtd_partition partition_info[] = { - { name: "NAND BOOT partition", - offset: 0 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND KERNEL partition", - offset: 4 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND ROOTFS partition", - offset: 8 * 0x100000, - size: 120 * 0x100000 }, - { name: "NAND DATA1 partition", - offset: 128 * 0x100000, - size: 128 * 0x100000 }, - { name: "NAND DATA2 partition", - offset: 256 * 0x100000, - size: 256 * 0x100000 }, - { name: "NAND VFAT partition", - offset: 512 * 0x100000, - size: 512 * 0x100000 }, -}; - -/* Define max reserved bad blocks for each partition. - * This is used by the mtdblock-jz.c NAND FTL driver only. - * - * The NAND FTL driver reserves some good blocks which can't be - * seen by the upper layer. When the bad block number of a partition - * exceeds the max reserved blocks, then there is no more reserved - * good blocks to be used by the NAND FTL driver when another bad - * block generated. - */ -static int partition_reserved_badblocks[] = { - 2, /* reserved blocks of mtd0 */ - 2, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10, /* reserved blocks of mtd3 */ - 20, /* reserved blocks of mtd4 */ - 20}; /* reserved blocks of mtd5 */ -#endif /* CONFIG_JZ4740_LYRA */ - -#ifdef CONFIG_JZ4725_DIPPER -static struct mtd_partition partition_info[] = { - { name: "NAND BOOT partition", - offset: 0 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND KERNEL partition", - offset: 4 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND ROOTFS partition", - offset: 8 * 0x100000, - size: 56 * 0x100000 }, - { name: "NAND VFAT partition", - offset: 64 * 0x100000, - size: 64 * 0x100000 }, -}; - -/* Define max reserved bad blocks for each partition. - * This is used by the mtdblock-jz.c NAND FTL driver only. - * - * The NAND FTL driver reserves some good blocks which can't be - * seen by the upper layer. When the bad block number of a partition - * exceeds the max reserved blocks, then there is no more reserved - * good blocks to be used by the NAND FTL driver when another bad - * block generated. - */ -static int partition_reserved_badblocks[] = { - 2, /* reserved blocks of mtd0 */ - 2, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10}; /* reserved blocks of mtd3 */ -#endif /* CONFIG_JZ4740_DIPPER */ - -#ifdef CONFIG_JZ4720_VIRGO -static struct mtd_partition partition_info[] = { - { name: "NAND BOOT partition", - offset: 0 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND KERNEL partition", - offset: 4 * 0x100000, - size: 4 * 0x100000 }, - { name: "NAND ROOTFS partition", - offset: 8 * 0x100000, - size: 120 * 0x100000 }, - { name: "NAND DATA1 partition", - offset: 128 * 0x100000, - size: 128 * 0x100000 }, - { name: "NAND DATA2 partition", - offset: 256 * 0x100000, - size: 256 * 0x100000 }, - { name: "NAND VFAT partition", - offset: 512 * 0x100000, - size: 512 * 0x100000 }, -}; - - -/* Define max reserved bad blocks for each partition. - * This is used by the mtdblock-jz.c NAND FTL driver only. - * - * The NAND FTL driver reserves some good blocks which can't be - * seen by the upper layer. When the bad block number of a partition - * exceeds the max reserved blocks, then there is no more reserved - * good blocks to be used by the NAND FTL driver when another bad - * block generated. - */ -static int partition_reserved_badblocks[] = { - 2, /* reserved blocks of mtd0 */ - 2, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10, /* reserved blocks of mtd3 */ - 20, /* reserved blocks of mtd4 */ - 20}; /* reserved blocks of mtd5 */ -#endif /* CONFIG_JZ4720_VIRGO */ -/*------------------------------------------------------------------------- - * Following three functions are exported and used by the mtdblock-jz.c - * NAND FTL driver only. - */ - -unsigned short get_mtdblock_write_verify_enable(void) -{ -#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE - return 1; -#endif - return 0; -} -EXPORT_SYMBOL(get_mtdblock_write_verify_enable); - -unsigned short get_mtdblock_oob_copies(void) -{ - return CONFIG_MTD_OOB_COPIES; -} -EXPORT_SYMBOL(get_mtdblock_oob_copies); - -int *get_jz_badblock_table(void) -{ - return partition_reserved_badblocks; -} -EXPORT_SYMBOL(get_jz_badblock_table); - -/*-------------------------------------------------------------------------*/ - -static void jz_hwcontrol(struct mtd_info *mtd, int dat, - unsigned int ctrl) -{ - struct nand_chip *this = (struct nand_chip *)(mtd->priv); - unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; - extern u8 nand_nce; /* in nand_base.c, indicates which chip select is used for current nand chip */ - - if (ctrl & NAND_CTRL_CHANGE) { - if (ctrl & NAND_NCE) { - switch (nand_nce) { - case NAND_NCE1: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; - break; - case NAND_NCE2: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE2; - break; - case NAND_NCE3: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE3; - break; - case NAND_NCE4: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT4; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE4; - break; - default: - printk("error: no nand_nce 0x%x\n",nand_nce); - break; - } - } else { - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - } - - if ( ctrl & NAND_ALE ) - nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) | 0x00010000); - else - nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) & ~0x00010000); - - if ( ctrl & NAND_CLE ) - nandaddr = nandaddr | 0x00008000; - else - nandaddr = nandaddr & ~0x00008000; - } - - this->IO_ADDR_W = (void __iomem *)nandaddr; - if (dat != NAND_CMD_NONE) - writeb(dat, this->IO_ADDR_W); -} - -static int jz_device_ready(struct mtd_info *mtd) -{ - int ready, wait = 10; - while (wait--); - ready = __gpio_get_pin(94); - return ready; -} - -/* - * EMC setup - */ -static void jz_device_setup(void) -{ -// PORT 0: -// ... -// PORT 1: -// PIN/BIT N FUNC0 FUNC1 -// 25 CS1# - -// 26 CS2# - -// 27 CS3# - -// 28 CS4# - -#define GPIO_CS2_N (32+26) -#define GPIO_CS3_N (32+27) -#define GPIO_CS4_N (32+28) -#define SMCR_VAL 0x0d221200 - - /* Set NFE bit */ - REG_EMC_NFCSR |= EMC_NFCSR_NFE1; - /* Read/Write timings */ - REG_EMC_SMCR1 = SMCR_VAL; - -#if defined(CONFIG_MTD_NAND_CS2) - /* Set CS2# pin as function 0 */ - __gpio_as_func0(GPIO_CS2_N); - REG_EMC_NFCSR |= EMC_NFCSR_NFE2; - REG_EMC_SMCR2 = SMCR_VAL; -#endif - -#if defined(CONFIG_MTD_NAND_CS3) - __gpio_as_func0(GPIO_CS3_N); - REG_EMC_NFCSR |= EMC_NFCSR_NFE3; - REG_EMC_SMCR3 = SMCR_VAL; -#endif - -#if defined(CONFIG_MTD_NAND_CS4) - __gpio_as_func0(GPIO_CS4_N); - REG_EMC_NFCSR |= EMC_NFCSR_NFE4; - REG_EMC_SMCR4 = SMCR_VAL; -#endif -} - -#ifdef CONFIG_MTD_HW_HM_ECC - -static int jzsoc_nand_calculate_hm_ecc(struct mtd_info* mtd, - const u_char* dat, u_char* ecc_code) -{ - unsigned int calc_ecc; - unsigned char *tmp; - - __nand_ecc_disable(); - - calc_ecc = ~(__nand_read_hm_ecc()) | 0x00030000; - - tmp = (unsigned char *)&calc_ecc; - //adjust eccbytes order for compatible with software ecc - ecc_code[0] = tmp[1]; - ecc_code[1] = tmp[0]; - ecc_code[2] = tmp[2]; - - return 0; -} - -static void jzsoc_nand_enable_hm_hwecc(struct mtd_info* mtd, int mode) -{ - __nand_ecc_enable(); - __nand_select_hm_ecc(); -} - -static int jzsoc_nand_hm_correct_data(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc) -{ - u_char a, b, c, d1, d2, d3, add, bit, i; - - /* Do error detection */ - d1 = calc_ecc[0] ^ read_ecc[0]; - d2 = calc_ecc[1] ^ read_ecc[1]; - d3 = calc_ecc[2] ^ read_ecc[2]; - - if ((d1 | d2 | d3) == 0) { - /* No errors */ - return 0; - } - else { - a = (d1 ^ (d1 >> 1)) & 0x55; - b = (d2 ^ (d2 >> 1)) & 0x55; - c = (d3 ^ (d3 >> 1)) & 0x54; - - /* Found and will correct single bit error in the data */ - if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { - c = 0x80; - add = 0; - a = 0x80; - for (i=0; i<4; i++) { - if (d1 & c) - add |= a; - c >>= 2; - a >>= 1; - } - c = 0x80; - for (i=0; i<4; i++) { - if (d2 & c) - add |= a; - c >>= 2; - a >>= 1; - } - bit = 0; - b = 0x04; - c = 0x80; - for (i=0; i<3; i++) { - if (d3 & c) - bit |= b; - c >>= 2; - b >>= 1; - } - b = 0x01; - a = dat[add]; - a ^= (b << bit); - dat[add] = a; - return 0; - } - else { - i = 0; - while (d1) { - if (d1 & 0x01) - ++i; - d1 >>= 1; - } - while (d2) { - if (d2 & 0x01) - ++i; - d2 >>= 1; - } - while (d3) { - if (d3 & 0x01) - ++i; - d3 >>= 1; - } - if (i == 1) { - /* ECC Code Error Correction */ - read_ecc[0] = calc_ecc[0]; - read_ecc[1] = calc_ecc[1]; - read_ecc[2] = calc_ecc[2]; - return 0; - } - else { - /* Uncorrectable Error */ - printk("NAND: uncorrectable ECC error\n"); - return -1; - } - } - } - - /* Should never happen */ - return -1; -} - -#endif /* CONFIG_MTD_HW_HM_ECC */ - -#ifdef CONFIG_MTD_HW_RS_ECC - -static void jzsoc_nand_enable_rs_hwecc(struct mtd_info* mtd, int mode) -{ - REG_EMC_NFINTS = 0x0; - __nand_ecc_enable(); - __nand_select_rs_ecc(); - - if (mode == NAND_ECC_READ) - __nand_rs_ecc_decoding(); - - if (mode == NAND_ECC_WRITE) - __nand_rs_ecc_encoding(); -} - -static void jzsoc_rs_correct(unsigned char *dat, int idx, int mask) -{ - int i; - - idx--; - - i = idx + (idx >> 3); - if (i >= 512) - return; - - mask <<= (idx & 0x7); - - dat[i] ^= mask & 0xff; - if (i < 511) - dat[i+1] ^= (mask >> 8) & 0xff; -} - -/* - * calc_ecc points to oob_buf for us - */ -static int jzsoc_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc) -{ - volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0; - short k; - u32 stat; - - /* Set PAR values */ - for (k = 0; k < PAR_SIZE; k++) { - *paraddr++ = read_ecc[k]; - } - - /* Set PRDY */ - REG_EMC_NFECR |= EMC_NFECR_PRDY; - - /* Wait for completion */ - __nand_ecc_decode_sync(); - __nand_ecc_disable(); - - /* Check decoding */ - stat = REG_EMC_NFINTS; - - if (stat & EMC_NFINTS_ERR) { - /* Error occurred */ - if (stat & EMC_NFINTS_UNCOR) { - printk("NAND: Uncorrectable ECC error\n"); - return -1; - } else { - u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT; - switch (errcnt) { - case 4: - jzsoc_rs_correct(dat, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); - /* FALL-THROUGH */ - case 3: - jzsoc_rs_correct(dat, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); - /* FALL-THROUGH */ - case 2: - jzsoc_rs_correct(dat, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); - /* FALL-THROUGH */ - case 1: - jzsoc_rs_correct(dat, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); - return 0; - default: - break; - } - } - } - - return 0; -} - -static int jzsoc_nand_calculate_rs_ecc(struct mtd_info* mtd, const u_char* dat, - u_char* ecc_code) -{ - volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0; - short i; - - __nand_ecc_encode_sync(); - __nand_ecc_disable(); - - for(i = 0; i < PAR_SIZE; i++) { - ecc_code[i] = *paraddr++; - } - - return 0; -} - -#endif /* CONFIG_MTD_HW_RS_ECC */ - -/* Nand optimized functions */ -static int dma_chan; -static unsigned int dma_src_phys_addr, dma_dst_phys_addr; -extern int jz_request_dma(int dev_id, const char *dev_str, - irqreturn_t (*irqhandler)(int, void *), - unsigned long irqflags, void *irq_dev_id); - -static void dma_setup(void) -{ - /* Request DMA channel and setup irq handler */ - dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", NULL, IRQF_DISABLED, NULL); - if (dma_chan < 0) { - printk("Setup irq for nand failed!\n"); - return; - } else - printk("Nand DMA request channel %d.\n",dma_chan); -} - -static void jz4740_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) -{ - int i; - struct nand_chip *chip = mtd->priv; - - if ((len <= 32) || (len & 0xf) || ((u32)buf >= (u32)high_memory)) - { - for (i = 0; i < len; i++) - buf[i] = readb(chip->IO_ADDR_R); - } else { - REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; - dma_src_phys_addr = CPHYSADDR(chip->IO_ADDR_R); - dma_dst_phys_addr = CPHYSADDR(buf); - dma_cache_inv((u32)buf, len); - REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; - REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; - REG_DMAC_DTCR(dma_chan) = len / 16; - REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_DAI | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE; - REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; - REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ - - while(!(REG_DMAC_DCCSR(dma_chan) & DMAC_DCCSR_TT)); - REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ - __dmac_channel_clear_transmit_end(dma_chan); - } -} - -static void jz4740_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) -{ - int i; - struct nand_chip *chip = mtd->priv; - - if ((len <= 32) || (len & 0xf) || ((u32)buf >= (u32)high_memory)) - { - for (i = 0; i < len; i++) - writeb(buf[i], chip->IO_ADDR_W); - } else { - REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; - dma_dst_phys_addr = CPHYSADDR(chip->IO_ADDR_R); - dma_src_phys_addr = CPHYSADDR(buf); - dma_cache_wback((unsigned long)buf, len); - REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; - REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; - REG_DMAC_DTCR(dma_chan) = len / 16; - REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_16BYTE ; - REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; - REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ - - while(!(REG_DMAC_DCCSR(dma_chan) & DMAC_DCCSR_TT)); - REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ - __dmac_channel_clear_transmit_end(dma_chan); - } -} - -static int nand_read_page_hwecc_rs_planes(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf) -{ - int i, eccsize = chip->ecc.size; - int eccbytes = chip->ecc.bytes; - int eccsteps = chip->ecc.steps >> 1; - uint8_t *p; - uint8_t *ecc_calc = chip->buffers->ecccalc; - uint8_t *ecc_code = chip->buffers->ecccode; - uint32_t *eccpos = chip->ecc.layout->eccpos; - uint32_t page; - uint8_t flag = 0; - int oobsize = mtd->oobsize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - int ecctotal = chip->ecc.total >> 1; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* Read first page */ - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - chip->read_buf(mtd, chip->oob_poi, oobsize); - for (i = 0; i < ecctotal; i++) { - ecc_code[i] = chip->oob_poi[eccpos[i]]; - if (ecc_code[i] != 0xff) flag = 1; - } - - p = buf; - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); - for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - if (flag) { - chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) - mtd->ecc_stats.failed++; - else - mtd->ecc_stats.corrected += stat; - } - else { - chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); - } - } - /* Read second page */ - page += ppb; - flag = 0; - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - chip->read_buf(mtd, chip->oob_poi + oobsize, oobsize); - for (i = 0; i < ecctotal; i++) { - ecc_code[i] = chip->oob_poi[oobsize + eccpos[i]]; - if (ecc_code[i] != 0xff) flag = 1; - } - - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); - eccsteps = chip->ecc.steps >> 1; - for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - if (flag) { - chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) - mtd->ecc_stats.failed++; - else - mtd->ecc_stats.corrected += stat; - } - else { - chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); - } - } - - return 0; -} - -static int nand_read_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, - int global_page, int sndcmd) -{ - int page; - int oobsize = mtd->oobsize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* Read first page OOB */ - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - } - chip->read_buf(mtd, chip->oob_poi, oobsize); - /* Read second page OOB */ - page += ppb; - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - sndcmd = 0; - } - chip->read_buf(mtd, chip->oob_poi+oobsize, oobsize); - return 0; -} - -static int nand_write_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, - int global_page) -{ - int status = 0,page; - int pagesize = mtd->writesize >> 1; - int oobsize = mtd->oobsize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - const uint8_t *buf = chip->oob_poi; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x80, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x80, pagesize, 0x00); - else - chip->cmdfunc(mtd, 0x80, pagesize, page & (1 << (chip->chip_shift - chip->page_shift))); - - chip->write_buf(mtd, buf, oobsize); - /* Send first command to program the OOB data */ - chip->cmdfunc(mtd, 0x11, -1, -1); - ndelay(100); - status = chip->waitfunc(mtd, chip); - - page += ppb; - buf += oobsize; - chip->cmdfunc(mtd, 0x81, pagesize, page); - chip->write_buf(mtd, buf, oobsize); - /* Send command to program the OOB data */ - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); - /* Wait long R/B */ - ndelay(100); - status = chip->waitfunc(mtd, chip); - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -static void nand_write_page_hwecc_planes(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) -{ - int i, eccsize = chip->ecc.size; - int eccbytes = chip->ecc.bytes; - int eccsteps = chip->ecc.steps >> 1; - uint8_t *ecc_calc = chip->buffers->ecccalc; - uint8_t *p = (uint8_t *)buf; - uint32_t *eccpos = chip->ecc.layout->eccpos; - int oobsize = mtd->oobsize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - int ecctotal = chip->ecc.total >> 1; - int page; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x80, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x80, 0x00, 0x00); - else - chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); - chip->write_buf(mtd, p, eccsize); - chip->ecc.calculate(mtd, p, &ecc_calc[i]); - } - for (i = 0; i < ecctotal; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; - - chip->write_buf(mtd, chip->oob_poi, oobsize); - - chip->cmdfunc(mtd, 0x11, -1, -1); /* send cmd 0x11 */ - ndelay(100); - while(!chip->dev_ready(mtd)); - - page += ppb; - chip->cmdfunc(mtd, 0x81, 0x00, page); /* send cmd 0x81 */ - eccsteps = chip->ecc.steps >> 1; - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); - chip->write_buf(mtd, p, eccsize); - chip->ecc.calculate(mtd, p, &ecc_calc[i]); - } - - for (i = 0; i < ecctotal; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; - - chip->write_buf(mtd, chip->oob_poi, oobsize); -} - -static void single_erase_cmd_planes(struct mtd_info *mtd, int global_page) -{ - struct nand_chip *chip = mtd->priv; - - /* Send commands to erase a block */ - int page; - int ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x60, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x60, -1, 0x00); - else - chip->cmdfunc(mtd, 0x60, -1, page & (1 << (chip->chip_shift - chip->page_shift))); - - page += ppb; - chip->cmdfunc(mtd, 0x60, -1, page & (~(ppb-1))); /* send cmd 0x60 */ - - chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); /* send cmd 0xd0 */ - /* Do not need wait R/B or check status */ -} - -/* - * Main initialization routine - */ -int __init jznand_init(void) -{ - struct nand_chip *this; - int nr_partitions, ret, i; - - /* Allocate memory for MTD device structure and private data */ - jz_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), - GFP_KERNEL); - if (!jz_mtd) { - printk ("Unable to allocate JzSOC NAND MTD device structure.\n"); - return -ENOMEM; - } - - jz_mtd1 = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), - GFP_KERNEL); - if (!jz_mtd1) { - printk ("Unable to allocate JzSOC NAND MTD device structure 1.\n"); - kfree(jz_mtd); - return -ENOMEM; - } - - /* Get pointer to private data */ - this = (struct nand_chip *) (&jz_mtd[1]); - - /* Initialize structures */ - memset((char *) jz_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); - - /* Link the private data with the MTD structure */ - jz_mtd->priv = this; - - /* Set & initialize NAND Flash controller */ - jz_device_setup(); - - /* Set address of NAND IO lines */ - this->IO_ADDR_R = (void __iomem *) NAND_DATA_PORT1; - this->IO_ADDR_W = (void __iomem *) NAND_DATA_PORT1; - this->cmd_ctrl = jz_hwcontrol; - this->dev_ready = jz_device_ready; - -#ifdef CONFIG_MTD_HW_HM_ECC - this->ecc.calculate = jzsoc_nand_calculate_hm_ecc; - this->ecc.correct = jzsoc_nand_hm_correct_data; - this->ecc.hwctl = jzsoc_nand_enable_hm_hwecc; - this->ecc.mode = NAND_ECC_HW; - this->ecc.size = 256; - this->ecc.bytes = 3; - -#endif - -#ifdef CONFIG_MTD_HW_RS_ECC - this->ecc.calculate = jzsoc_nand_calculate_rs_ecc; - this->ecc.correct = jzsoc_nand_rs_correct_data; - this->ecc.hwctl = jzsoc_nand_enable_rs_hwecc; - this->ecc.mode = NAND_ECC_HW; - this->ecc.size = 512; - this->ecc.bytes = 9; -#endif - -#ifdef CONFIG_MTD_SW_HM_ECC - this->ecc.mode = NAND_ECC_SOFT; -#endif - /* 20 us command delay time */ - this->chip_delay = 20; - -#ifdef CONFIG_MTD_NAND_DMA - dma_setup(); -#endif - /* Scan to find existance of the device */ - ret = nand_scan_ident(jz_mtd, NAND_MAX_CHIPS); - if (!ret) { - if (this->planenum == 2) { - /* reset nand functions */ - this->erase_cmd = single_erase_cmd_planes; - this->ecc.read_page = nand_read_page_hwecc_rs_planes; //Muti planes read - this->ecc.write_page = nand_write_page_hwecc_planes; - this->ecc.read_oob = nand_read_oob_std_planes; - this->ecc.write_oob = nand_write_oob_std_planes; -#ifdef CONFIG_MTD_NAND_DMA - this->write_buf = jz4740_nand_write_buf; - this->read_buf = jz4740_nand_read_buf; -#endif - printk(KERN_INFO "Nand using two-plane mode, " - "and resized to writesize:%d oobsize:%d blocksize:0x%x \n", - jz_mtd->writesize, jz_mtd->oobsize, jz_mtd->erasesize); - } - } - - /* Determine whether all the partitions will use multiple planes if supported */ - nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); - all_use_planes = 1; - for (i = 0; i < nr_partitions; i++) { - all_use_planes &= partition_info[i].use_planes; - } - - if (!ret) - ret = nand_scan_tail(jz_mtd); - - if (ret){ - kfree (jz_mtd1); - kfree (jz_mtd); - return -ENXIO; - } - - /* Register the partitions */ - printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); - - if ((this->planenum == 2) && !all_use_planes) { - for (i = 0; i < nr_partitions; i++) { - if (partition_info[i].use_planes) - add_mtd_partitions(jz_mtd, &partition_info[i], 1); - else - add_mtd_partitions(jz_mtd1, &partition_info[i], 1); - } - } else { - kfree(jz_mtd1); - add_mtd_partitions(jz_mtd, partition_info, nr_partitions); - } - return 0; -} -module_init(jznand_init); - -/* - * Clean up routine - */ -#ifdef MODULE -static void __exit jznand_cleanup(void) -{ - struct nand_chip *this = (struct nand_chip *) &jz_mtd[1]; - - /* Unregister partitions */ - del_mtd_partitions(jz_mtd); - - /* Unregister the device */ - del_mtd_device (jz_mtd); - - /* Free internal data buffers */ - kfree (this->data_buf); - - /* Free the MTD device structure */ - if ((this->planenum == 2) && !all_use_planes) - kfree (jz_mtd1); - kfree (jz_mtd); -} -module_exit(jznand_cleanup); -#endif diff --git a/target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4750_nand.c b/target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4750_nand.c deleted file mode 100755 index 65de9184d..000000000 --- a/target/linux/xburst/files-2.6.27/drivers/mtd/nand/jz4750_nand.c +++ /dev/null @@ -1,1785 +0,0 @@ -/* - * linux/drivers/mtd/nand/jz4750_nand.c - * - * JZ4750 NAND driver - * - * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. - * Author: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -/* 32bit instead of 16byte burst is used by DMA to read or - write NAND and BCH avoiding grabbing bus for too long */ -#define DMAC_DCMD_DS_NAND DMAC_DCMD_DS_32BIT -#define DIV_DS_NAND 4 - -#define DMAC_DCMD_DS_BCH DMAC_DCMD_DS_32BIT -#define DIV_DS_BCH 4 - -#define DEBUG1 0 -#if DEBUG1 -#define dprintk(n,x...) printk(n,##x) -#else -#define dprintk(n,x...) -#endif - -#if defined(CONFIG_MTD_HW_BCH_8BIT) -#define __ECC_ENCODING __ecc_encoding_8bit -#define __ECC_DECODING __ecc_decoding_8bit -#define ERRS_SIZE 5 /* 5 words */ -#else -#define __ECC_ENCODING __ecc_encoding_4bit -#define __ECC_DECODING __ecc_decoding_4bit -#define ERRS_SIZE 3 /* 3 words */ -#endif - -#define NAND_DATA_PORT1 0xB8000000 /* read-write area in static bank 1 */ -#define NAND_DATA_PORT2 0xB4000000 /* read-write area in static bank 2 */ -#define NAND_DATA_PORT3 0xAC000000 /* read-write area in static bank 3 */ -#define NAND_DATA_PORT4 0xA8000000 /* read-write area in static bank 4 */ - -#define NAND_ADDR_OFFSET0 0x00010000 /* address port offset for share mode */ -#define NAND_CMD_OFFSET0 0x00008000 /* command port offset for share mode */ -#define NAND_ADDR_OFFSET1 0x00000010 /* address port offset for unshare mode */ -#define NAND_CMD_OFFSET1 0x00000008 /* command port offset for unshare mode */ - -#if defined(CONFIG_MTD_NAND_DMA) -#define USE_IRQ 1 -enum { - NAND_NONE, - NAND_PROG, - NAND_READ -}; -static volatile u8 nand_status; -static volatile int dma_ack = 0; -static volatile int dma_ack1 = 0; -static char nand_dma_chan; /* automatically select a free channel */ -static char bch_dma_chan = 0; /* fixed to channel 0 */ -static u32 *errs; -static jz_dma_desc_8word *dma_desc_enc, *dma_desc_enc1, *dma_desc_dec, *dma_desc_dec1, *dma_desc_dec2, - *dma_desc_nand_prog, *dma_desc_nand_read; -static u32 *pval_nand_ddr; -static u8 *pval_nand_cmd_pgprog; /* for sending 0x11 or 0x10 when programing*/ -#if defined(CONFIG_MTD_NAND_DMABUF) -u8 *prog_buf, *read_buf; -#endif -DECLARE_WAIT_QUEUE_HEAD(nand_prog_wait_queue); -DECLARE_WAIT_QUEUE_HEAD(nand_read_wait_queue); -#endif - -struct buf_be_corrected { - u8 *data; - u8 *oob; -}; - -static u32 addr_offset; -static u32 cmd_offset; - -extern int global_page; /* for two-plane operations */ - -/* - * MTD structure for JzSOC board - */ -static struct mtd_info *jz_mtd = NULL; -extern struct mtd_info *jz_mtd1; -extern char all_use_planes; - -/* - * Define partitions for flash devices - */ -#if defined(CONFIG_JZ4750_FUWA) || defined(CONFIG_JZ4750D_FUWA1) -static struct mtd_partition partition_info[] = { - {name:"NAND BOOT partition", - offset:0 * 0x100000, - size:4 * 0x100000, - use_planes: 0}, - {name:"NAND KERNEL partition", - offset:4 * 0x100000, - size:4 * 0x100000, - use_planes: 0}, - {name:"NAND ROOTFS partition", - offset:8 * 0x100000, - size:120 * 0x100000, - use_planes: 1}, - {name:"NAND DATA1 partition", - offset:128 * 0x100000, - size:128 * 0x100000, - use_planes: 1}, - {name:"NAND DATA2 partition", - offset:256 * 0x100000, - size:256 * 0x100000, - use_planes: 1}, - {name:"NAND VFAT partition", - offset:512 * 0x100000, - size:512 * 0x100000, - use_planes: 1}, -}; - -/* Define max reserved bad blocks for each partition. - * This is used by the mtdblock-jz.c NAND FTL driver only. - * - * The NAND FTL driver reserves some good blocks which can't be - * seen by the upper layer. When the bad block number of a partition - * exceeds the max reserved blocks, then there is no more reserved - * good blocks to be used by the NAND FTL driver when another bad - * block generated. - */ -static int partition_reserved_badblocks[] = { - 2, /* reserved blocks of mtd0 */ - 2, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10, /* reserved blocks of mtd3 */ - 20, /* reserved blocks of mtd4 */ - 20 -}; /* reserved blocks of mtd5 */ -#endif /* CONFIG_JZ4750_FUWA or CONFIG_JZ4750_APUS */ - -#if defined(CONFIG_JZ4750_APUS) || defined(CONFIG_JZ4750D_CETUS) - -/* Reserve 32MB for bootloader, splash1, splash2 and radiofw */ -#define MISC_OFFSET (32 * 0x100000) - -#define MISC_SIZE ( 1 * 0x100000) -#define RECOVERY_SIZE ( 5 * 0x100000) -#define BOOT_SIZE ( 4 * 0x100000) -#define SYSTEM_SIZE (128 * 0x100000) -#define USERDATA_SIZE (128 * 0x100000) -#define CACHE_SIZE (128 * 0x100000) -#define STORAGE_SIZE (MTDPART_SIZ_FULL) - -static struct mtd_partition partition_info[] = { - - /* Android partitions: - * - * misc@mtd0 : raw - * recovery@mtd1: raw - * boot@mtd2: raw - * system@mtd3: yaffs2 - * userdata@mtd4: yaffs2 - * cache@mtd5: yaffs2 - * storage@mtd6: vfat - */ - {name: "misc", - offset: MISC_OFFSET, - size: MISC_SIZE, - use_planes: 0}, - {name: "recovery", - offset: (MISC_OFFSET+MISC_SIZE), - size: RECOVERY_SIZE, - use_planes: 0}, - {name: "boot", - offset: (MISC_OFFSET+MISC_SIZE+RECOVERY_SIZE), - size: BOOT_SIZE, - use_planes: 0}, - {name: "system", - offset: (MISC_OFFSET+MISC_SIZE+RECOVERY_SIZE+BOOT_SIZE), - size: SYSTEM_SIZE, - use_planes: 0}, - {name: "userdata", - offset: (MISC_OFFSET+MISC_SIZE+RECOVERY_SIZE+BOOT_SIZE+SYSTEM_SIZE), - size: USERDATA_SIZE, - use_planes: 0}, - {name: "cache", - offset: (MISC_OFFSET+MISC_SIZE+RECOVERY_SIZE+BOOT_SIZE+SYSTEM_SIZE+USERDATA_SIZE), - size: CACHE_SIZE, - use_planes: 0}, - {name: "storage", - offset: (MISC_OFFSET+MISC_SIZE+RECOVERY_SIZE+BOOT_SIZE+SYSTEM_SIZE+USERDATA_SIZE+CACHE_SIZE), - size: STORAGE_SIZE, - use_planes: 0} -}; - - -/* Define max reserved bad blocks for each partition. - * This is used by the mtdblock-jz.c NAND FTL driver only. - * - * The NAND FTL driver reserves some good blocks which can't be - * seen by the upper layer. When the bad block number of a partition - * exceeds the max reserved blocks, then there is no more reserved - * good blocks to be used by the NAND FTL driver when another bad - * block generated. - */ -static int partition_reserved_badblocks[] = { - 10, /* reserved blocks of mtd0 */ - 10, /* reserved blocks of mtd1 */ - 10, /* reserved blocks of mtd2 */ - 10, /* reserved blocks of mtd3 */ - 10, /* reserved blocks of mtd4 */ - 10, /* reserved blocks of mtd5 */ - 12 /* reserved blocks of mtd6 */ -}; -#endif /* CONFIG_JZ4750_FUWA or CONFIG_JZ4750_APUS */ - -/*------------------------------------------------------------------------- - * Following three functions are exported and used by the mtdblock-jz.c - * NAND FTL driver only. - */ - -unsigned short get_mtdblock_write_verify_enable(void) -{ -#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE - return 1; -#endif - return 0; -} - -EXPORT_SYMBOL(get_mtdblock_write_verify_enable); - -unsigned short get_mtdblock_oob_copies(void) -{ - return CONFIG_MTD_OOB_COPIES; -} - -EXPORT_SYMBOL(get_mtdblock_oob_copies); - -int *get_jz_badblock_table(void) -{ - return partition_reserved_badblocks; -} - -EXPORT_SYMBOL(get_jz_badblock_table); - -/*-------------------------------------------------------------------------*/ - -static void jz_hwcontrol(struct mtd_info *mtd, int dat, u32 ctrl) -{ - struct nand_chip *this = (struct nand_chip *)(mtd->priv); - u32 nandaddr = (u32)this->IO_ADDR_W; - extern u8 nand_nce; /* defined in nand_base.c, indicates which chip select is used for current nand chip */ - - if (ctrl & NAND_CTRL_CHANGE) { - if (ctrl & NAND_NCE) { - switch (nand_nce) { - case NAND_NCE1: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; - break; - case NAND_NCE2: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE2; - break; - case NAND_NCE3: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE3; - break; - case NAND_NCE4: - this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT4; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR |= EMC_NFCSR_NFCE4; - break; - default: - printk("error: no nand_nce 0x%x\n",nand_nce); - break; - } - } else { - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; - REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; - } - - if (ctrl & NAND_ALE) - nandaddr = (u32)((u32)(this->IO_ADDR_W) | addr_offset); - else - nandaddr = (u32)((u32)(this->IO_ADDR_W) & ~addr_offset); - if (ctrl & NAND_CLE) - nandaddr = (u32)(nandaddr | cmd_offset); - else - nandaddr = (u32)(nandaddr & ~cmd_offset); - } - - this->IO_ADDR_W = (void __iomem *)nandaddr; - if (dat != NAND_CMD_NONE) { - writeb(dat, this->IO_ADDR_W); - /* printk("write cmd:0x%x to 0x%x\n",dat,(u32)this->IO_ADDR_W); */ - } -} - -static int jz_device_ready(struct mtd_info *mtd) -{ - int ready, wait = 10; - while (wait--); - ready = __gpio_get_pin(91); - return ready; -} - -/* - * EMC setup - */ -static void jz_device_setup(void) -{ -// PORT 0: -// PORT 1: -// PORT 2: -// PIN/BIT N FUNC0 FUNC1 -// 21 CS1# - -// 22 CS2# - -// 23 CS3# - -// 24 CS4# - -#define GPIO_CS2_N (32*2+22) -#define GPIO_CS3_N (32*2+23) -#define GPIO_CS4_N (32*2+24) -#define SMCR_VAL 0x0d444400 -//#define SMCR_VAL 0x0d221200 - - __gpio_as_nand_8bit(1); - /* Set NFE bit */ - REG_EMC_NFCSR |= EMC_NFCSR_NFE1; - /* Read/Write timings */ - REG_EMC_SMCR1 = SMCR_VAL; - -#if defined(CONFIG_MTD_NAND_CS2) - __gpio_as_func0(GPIO_CS2_N); - /* Set NFE bit */ - REG_EMC_NFCSR |= EMC_NFCSR_NFE2; - /* Read/Write timings */ - REG_EMC_SMCR2 = SMCR_VAL; -#endif - -#if defined(CONFIG_MTD_NAND_CS3) - __gpio_as_func0(GPIO_CS3_N); - /* Set NFE bit */ - REG_EMC_NFCSR |= EMC_NFCSR_NFE3; - /* Read/Write timings */ - REG_EMC_SMCR3 = SMCR_VAL; -#endif - -#if defined(CONFIG_MTD_NAND_CS4) - __gpio_as_func0(GPIO_CS4_N); - /* Set NFE bit */ - REG_EMC_NFCSR |= EMC_NFCSR_NFE4; - /* Read/Write timings */ - REG_EMC_SMCR4 = SMCR_VAL; -#endif -} - -#ifdef CONFIG_MTD_HW_BCH_ECC - -static void jzsoc_nand_enable_bch_hwecc(struct mtd_info *mtd, int mode) -{ - struct nand_chip *this = (struct nand_chip *)(mtd->priv); - int eccsize = this->ecc.size; - int eccbytes = this->ecc.bytes; - int eccsteps = this->ecc.steps / this->planenum; - int oob_per_eccsize = this->ecc.layout->eccpos[0] / eccsteps; - - REG_BCH_INTS = 0xffffffff; - if (mode == NAND_ECC_READ) { - __ECC_DECODING(); - __ecc_cnt_dec(eccsize + oob_per_eccsize + eccbytes); -#if defined(CONFIG_MTD_NAND_DMA) - __ecc_dma_enable(); -#endif - } - - if (mode == NAND_ECC_WRITE) { - __ECC_ENCODING(); - __ecc_cnt_enc(eccsize + oob_per_eccsize); -#if defined(CONFIG_MTD_NAND_DMA) - __ecc_dma_enable(); -#endif - } -} - -/** - * bch_correct - * @dat: data to be corrected - * @idx: the index of error bit in an eccsize - */ -static void bch_correct(struct mtd_info *mtd, u8 * dat, int idx) -{ - struct nand_chip *this = (struct nand_chip *)(mtd->priv); - int eccsize = this->ecc.size; - int eccsteps = this->ecc.steps / this->planenum; - int ecc_pos = this->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - int i, bit; /* the 'bit' of i byte is error */ - - i = (idx - 1) >> 3; - bit = (idx - 1) & 0x7; - - dprintk("error:i=%d, bit=%d\n",i,bit); - - if (i < eccsize){ - ((struct buf_be_corrected *)dat)->data[i] ^= (1 << bit); - } else if (i < eccsize + oob_per_eccsize) { - ((struct buf_be_corrected *)dat)->oob[i-eccsize] ^= (1 << bit); - } -} - -#if defined(CONFIG_MTD_NAND_DMA) - -/** - * jzsoc_nand_bch_correct_data - * @mtd: mtd info structure - * @dat: data to be corrected - * @errs0: pointer to the dma target buffer of bch decoding which stores BHINTS and - * BHERR0~3(8-bit BCH) or BHERR0~1(4-bit BCH) - * @calc_ecc: no used - */ -static int jzsoc_nand_bch_correct_data(struct mtd_info *mtd, u_char * dat, u_char * errs0, u_char * calc_ecc) -{ - u32 stat; - u32 *errs = (u32 *)errs0; - - if (REG_DMAC_DCCSR(0) & DMAC_DCCSR_BERR) { - stat = errs[0]; - dprintk("stat=%x err0:%x err1:%x \n", stat, errs[1], errs[2]); - - if (stat & BCH_INTS_ERR) { - if (stat & BCH_INTS_UNCOR) { - printk("NAND: Uncorrectable ECC error\n"); - return -1; - } else { - u32 errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT; - switch (errcnt) { -#if defined(CONFIG_MTD_HW_BCH_8BIT) - case 8: - bch_correct(mtd, dat, (errs[4] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - case 7: - bch_correct(mtd, dat, (errs[4] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - case 6: - bch_correct(mtd, dat, (errs[3] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - case 5: - bch_correct(mtd, dat, (errs[3] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -#endif - case 4: - bch_correct(mtd, dat, (errs[2] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - case 3: - bch_correct(mtd, dat, (errs[2] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - case 2: - bch_correct(mtd, dat, (errs[1] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - case 1: - bch_correct(mtd, dat, (errs[1] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - default: - break; - } - } - } - } - - return 0; -} - -#else /* cpu mode */ - -/** - * jzsoc_nand_bch_correct_data - * @mtd: mtd info structure - * @dat: data to be corrected - * @read_ecc: pointer to ecc buffer calculated when nand writing - * @calc_ecc: no used - */ -static int jzsoc_nand_bch_correct_data(struct mtd_info *mtd, u_char * dat, u_char * read_ecc, u_char * calc_ecc) -{ - struct nand_chip *this = (struct nand_chip *)(mtd->priv); - int eccsize = this->ecc.size; - int eccbytes = this->ecc.bytes; - int eccsteps = this->ecc.steps / this->planenum; - int ecc_pos = this->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - short k; - u32 stat; - - /* Write data to REG_BCH_DR */ - for (k = 0; k < eccsize; k++) { - REG_BCH_DR = ((struct buf_be_corrected *)dat)->data[k]; - } - /* Write oob to REG_BCH_DR */ - for (k = 0; k < oob_per_eccsize; k++) { - REG_BCH_DR = ((struct buf_be_corrected *)dat)->oob[k]; - } - /* Write parities to REG_BCH_DR */ - for (k = 0; k < eccbytes; k++) { - REG_BCH_DR = read_ecc[k]; - } - - /* Wait for completion */ - __ecc_decode_sync(); - __ecc_disable(); - - /* Check decoding */ - stat = REG_BCH_INTS; - - if (stat & BCH_INTS_ERR) { - /* Error occurred */ - if (stat & BCH_INTS_UNCOR) { - printk("NAND: Uncorrectable ECC error--\n"); - return -1; - } else { - u32 errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT; - switch (errcnt) { -#if defined(CONFIG_MTD_HW_BCH_8BIT) - case 8: - bch_correct(mtd, dat, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - /* FALL-THROUGH */ - case 7: - bch_correct(mtd, dat, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - /* FALL-THROUGH */ - case 6: - bch_correct(mtd, dat, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - /* FALL-THROUGH */ - case 5: - bch_correct(mtd, dat, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - /* FALL-THROUGH */ -#endif - case 4: - bch_correct(mtd, dat, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - /* FALL-THROUGH */ - case 3: - bch_correct(mtd, dat, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - /* FALL-THROUGH */ - case 2: - bch_correct(mtd, dat, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); - /* FALL-THROUGH */ - case 1: - bch_correct(mtd, dat, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); - return 0; - default: - break; - } - } - } - - return 0; -} -#endif /* CONFIG_MTD_NAND_DMA */ - -static int jzsoc_nand_calculate_bch_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) -{ - struct nand_chip *this = (struct nand_chip *)(mtd->priv); - int eccsize = this->ecc.size; - int eccbytes = this->ecc.bytes; - int eccsteps = this->ecc.steps / this->planenum; - int ecc_pos = this->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - volatile u8 *paraddr = (volatile u8 *)BCH_PAR0; - short i; - - /* Write data to REG_BCH_DR */ - for (i = 0; i < eccsize; i++) { - REG_BCH_DR = ((struct buf_be_corrected *)dat)->data[i]; - } - /* Write oob to REG_BCH_DR */ - for (i = 0; i < oob_per_eccsize; i++) { - REG_BCH_DR = ((struct buf_be_corrected *)dat)->oob[i]; - } - __ecc_encode_sync(); - __ecc_disable(); - - for (i = 0; i < eccbytes; i++) { - ecc_code[i] = *paraddr++; - } - - return 0; -} - -#if defined(CONFIG_MTD_NAND_DMA) - -/** - * nand_write_page_hwecc_bch - [REPLACABLE] hardware ecc based page write function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: data buffer - */ -static void nand_write_page_hwecc_bch0(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, u8 cmd_pgprog) -{ - int eccsize = chip->ecc.size; - int eccsteps = chip->ecc.steps / chip->planenum; - int eccbytes = chip->ecc.bytes; - int ecc_pos = chip->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - int pagesize = mtd->writesize / chip->planenum; - int oobsize = mtd->oobsize / chip->planenum; - int i, err, timeout; - const u8 *databuf; - u8 *oobbuf; - jz_dma_desc_8word *desc; - -#if defined(CONFIG_MTD_NAND_DMABUF) - memcpy(prog_buf, buf, pagesize); - memcpy(prog_buf + pagesize, chip->oob_poi, oobsize); - dma_cache_wback_inv((u32)prog_buf, pagesize + oobsize); -#else - databuf = buf; - oobbuf = chip->oob_poi; - - /* descriptors for encoding data blocks */ - desc = dma_desc_enc; - for (i = 0; i < eccsteps; i++) { - desc->dsadr = CPHYSADDR((u32)databuf) + i * eccsize; /* DMA source address */ - desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ - dprintk("dma_desc_enc:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - /* descriptors for encoding oob blocks */ - desc = dma_desc_enc1; - for (i = 0; i < eccsteps; i++) { - desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address, 28/4 = 7bytes */ - desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ - dprintk("dma_desc_enc1:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - /* descriptor for nand programing data block */ - desc = dma_desc_nand_prog; - desc->dsadr = CPHYSADDR((u32)databuf); /* DMA source address */ - desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_W); /* It will be changed when using multiply chip select */ - dprintk("dma_desc_nand_prog:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - - /* descriptor for nand programing oob block */ - desc++; - desc->dsadr = CPHYSADDR((u32)oobbuf); /* DMA source address */ - desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_W); /* It will be changed when using multiply chip select */ - dprintk("dma_desc_oob_prog:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - - /* descriptor for __nand_cmd(CMD_PGPROG) */ - desc++; - *pval_nand_cmd_pgprog = cmd_pgprog; - desc->dsadr = CPHYSADDR((u32)pval_nand_cmd_pgprog); - desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_R | cmd_offset); /* DMA target address: cmdport */ - if (cmd_pgprog == 0x10) - desc->dcmd |= DMAC_DCMD_LINK; /* __nand_sync() by a DMA descriptor */ - else if (cmd_pgprog == 0x11) - desc->dcmd &= ~DMAC_DCMD_LINK; /* __nand_sync() by polling */ - - dma_cache_wback_inv((u32)dma_desc_enc, (eccsteps * 2 + 2 + 1) * (sizeof(jz_dma_desc_8word))); - dma_cache_wback_inv((u32)databuf, pagesize); - dma_cache_wback_inv((u32)oobbuf, oobsize); - /* 4*6: pval_nand_ddr, pval_nand_dcs, pval_bch_ddr, pval_bch_dcs, dummy, pval_nand_cmd_pgprog */ - dma_cache_wback_inv((u32)pval_nand_ddr, 4 * 8); /* 8 words, a cache line */ -#endif - - REG_DMAC_DCCSR(bch_dma_chan) = 0; - REG_DMAC_DCCSR(nand_dma_chan) = 0; - - /* Setup DMA descriptor address */ - REG_DMAC_DDA(bch_dma_chan) = CPHYSADDR((u32)dma_desc_enc); - REG_DMAC_DDA(nand_dma_chan) = CPHYSADDR((u32)dma_desc_nand_prog); - - /* Setup request source */ - REG_DMAC_DRSR(bch_dma_chan) = DMAC_DRSR_RS_BCH_ENC; - REG_DMAC_DRSR(nand_dma_chan) = DMAC_DRSR_RS_AUTO; - - /* Setup DMA channel control/status register */ - REG_DMAC_DCCSR(bch_dma_chan) = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ - - /* Enable DMA */ - REG_DMAC_DMACR(0) |= DMAC_DMACR_DMAE; - REG_DMAC_DMACR(nand_dma_chan/HALF_DMA_NUM) |= DMAC_DMACR_DMAE; - - /* Enable BCH encoding */ - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); - - dma_ack1 = 0; - nand_status = NAND_PROG; - - /* DMA doorbell set -- start DMA now ... */ - __dmac_channel_set_doorbell(bch_dma_chan); - -#if USE_IRQ - if (cmd_pgprog == 0x10) { - dprintk("nand prog before wake up\n"); - err = wait_event_interruptible_timeout(nand_prog_wait_queue, dma_ack1, 3 * HZ); - nand_status = NAND_NONE; - dprintk("nand prog after wake up\n"); - if (!err) { - printk("*** NAND WRITE, Warning, wait event 3s timeout!\n"); - dump_jz_dma_channel(0); - dump_jz_dma_channel(nand_dma_chan); - printk("REG_BCH_CR=%x REG_BCH_CNT=0x%x REG_BCH_INTS=%x\n", REG_BCH_CR, REG_BCH_CNT, REG_BCH_INTS); - } - dprintk("timeout remain = %d\n", err); - } else if (cmd_pgprog == 0x11) { - timeout = 100000; - while ((!__dmac_channel_transmit_end_detected(nand_dma_chan)) && (timeout--)); - if (timeout <= 0) - printk("two-plane prog 0x11 timeout!\n"); - } -#else - timeout = 100000; - while ((!__dmac_channel_transmit_end_detected(nand_dma_chan)) && (timeout--)); - while(!chip->dev_ready(mtd)); - if (timeout <= 0) - printk("not use irq, prog timeout!\n"); -#endif -} - -static void nand_write_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf) -{ - nand_write_page_hwecc_bch0(mtd, chip, buf, 0x10); -} - -static void nand_write_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf) -{ - int page; - int pagesize = mtd->writesize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x80, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x80, 0x00, 0x00); - else - chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); - - nand_write_page_hwecc_bch0(mtd, chip, buf, 0x11); - chip->cmdfunc(mtd, 0x81, 0x00, page + ppb); - nand_write_page_hwecc_bch0(mtd, chip, buf + pagesize, 0x10); -} - -#else /* nand write in cpu mode */ - -static void nand_write_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) -{ - int i, eccsize = chip->ecc.size; - int eccbytes = chip->ecc.bytes; - int eccsteps = chip->ecc.steps / chip->planenum; - int oob_per_eccsize = chip->ecc.layout->eccpos[0] / eccsteps; - int oobsize = mtd->oobsize / chip->planenum; - int ecctotal = chip->ecc.total / chip->planenum; - uint8_t *p = (uint8_t *)buf; - uint8_t *ecc_calc = chip->buffers->ecccalc; - uint32_t *eccpos = chip->ecc.layout->eccpos; - static struct buf_be_corrected buf_calc0; - struct buf_be_corrected *buf_calc = &buf_calc0; - - for (i = 0; i < eccsteps; i++, p += eccsize) { - buf_calc->data = (u8 *)buf + eccsize * i; - buf_calc->oob = chip->oob_poi + oob_per_eccsize * i; - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); - chip->ecc.calculate(mtd, (u8 *)buf_calc, &ecc_calc[eccbytes*i]); - chip->write_buf(mtd, p, eccsize); - } - - for (i = 0; i < ecctotal; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; - - chip->write_buf(mtd, chip->oob_poi, oobsize); -} - -/* nand write using two-plane mode */ -static void nand_write_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) -{ - int pagesize = mtd->writesize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - int page; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x80, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x80, 0x00, 0x00); - else - chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); - - nand_write_page_hwecc_bch(mtd, chip, buf); - - chip->cmdfunc(mtd, 0x11, -1, -1); /* send cmd 0x11 */ - ndelay(100); - while(!chip->dev_ready(mtd)); - - chip->cmdfunc(mtd, 0x81, 0x00, page + ppb); /* send cmd 0x81 */ - nand_write_page_hwecc_bch(mtd, chip, buf + pagesize); -} -#endif /* CONFIG_MTD_NAND_DMA */ - -/** - * nand_read_page_hwecc_bch - [REPLACABLE] hardware ecc based page read function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * - * Not for syndrome calculating ecc controllers which need a special oob layout - */ -#if defined(CONFIG_MTD_NAND_DMA) -static int nand_read_page_hwecc_bch0(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, u32 page) -{ - int i, eccsize = chip->ecc.size; - int eccsteps = chip->ecc.steps / chip->planenum; - int eccbytes = chip->ecc.bytes; - int ecc_pos = chip->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - int pagesize = mtd->writesize / chip->planenum; - int oobsize = mtd->oobsize / chip->planenum; - u8 *databuf, *oobbuf; - jz_dma_desc_8word *desc; - int err; - u32 addrport, cmdport; - static struct buf_be_corrected buf_correct0; - - addrport = (u32)(chip->IO_ADDR_R) | addr_offset; - cmdport = (u32)(chip->IO_ADDR_R) | cmd_offset; - -#if defined(CONFIG_MTD_NAND_DMABUF) - databuf = read_buf; - oobbuf = read_buf + pagesize; - - dma_cache_inv((u32)read_buf, pagesize + oobsize); // databuf should be invalidated. - memset(errs, 0, eccsteps * ERRS_SIZE * 4); - dma_cache_wback_inv((u32)errs, eccsteps * ERRS_SIZE * 4); -#else - - databuf = buf; - oobbuf = chip->oob_poi; - - /* descriptor for nand reading data block */ - desc = dma_desc_nand_read; - desc->dsadr = CPHYSADDR((u32)chip->IO_ADDR_R); /* It will be changed when using multiply chip select */ - desc->dtadr = CPHYSADDR((u32)databuf); /* DMA target address */ - - dprintk("desc_nand_read:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - - /* descriptor for nand reading oob block */ - desc++; - desc->dsadr = CPHYSADDR((u32)chip->IO_ADDR_R); /* It will be changed when using multiply chip select */ - desc->dtadr = CPHYSADDR((u32)oobbuf); /* DMA target address */ - dprintk("desc_oob_read:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - - /* descriptors for data to be written to bch */ - desc = dma_desc_dec; - for (i = 0; i < eccsteps; i++) { - desc->dsadr = CPHYSADDR((u32)databuf) + i * eccsize; /* DMA source address */ - dprintk("dma_desc_dec:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - /* descriptors for oob to be written to bch */ - desc = dma_desc_dec1; - for (i = 0; i < eccsteps; i++) { - desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address */ - dprintk("dma_desc_dec1:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - /* descriptors for parities to be written to bch */ - desc = dma_desc_dec2; - for (i = 0; i < eccsteps; i++) { - desc->dsadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA source address */ - dprintk("dma_desc_dec2:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - dma_cache_wback_inv((u32)dma_desc_nand_read, (2 + eccsteps * 3) * (sizeof(jz_dma_desc_8word))); - - memset(errs, 0, eccsteps * ERRS_SIZE * 4); - dma_cache_inv((u32)databuf, pagesize); // databuf should be invalidated. - dma_cache_inv((u32)oobbuf, oobsize); // oobbuf should be invalidated too - dma_cache_wback_inv((u32)errs, eccsteps * ERRS_SIZE * 4); -#endif - REG_DMAC_DCCSR(bch_dma_chan) = 0; - REG_DMAC_DCCSR(nand_dma_chan) = 0; - - /* Setup DMA descriptor address */ - REG_DMAC_DDA(nand_dma_chan) = CPHYSADDR((u32)dma_desc_nand_read); - REG_DMAC_DDA(bch_dma_chan) = CPHYSADDR((u32)dma_desc_dec); - - /* Setup request source */ - REG_DMAC_DRSR(nand_dma_chan) = DMAC_DRSR_RS_NAND; - REG_DMAC_DRSR(bch_dma_chan) = DMAC_DRSR_RS_BCH_DEC; - - /* Enable DMA */ - REG_DMAC_DMACR(0) |= DMAC_DMACR_DMAE; - REG_DMAC_DMACR(nand_dma_chan/HALF_DMA_NUM) |= DMAC_DMACR_DMAE; - - /* Enable BCH decoding */ - chip->ecc.hwctl(mtd, NAND_ECC_READ); - - dma_ack = 0; - nand_status = NAND_READ; - /* DMA doorbell set -- start nand DMA now ... */ - __dmac_channel_set_doorbell(nand_dma_chan); - - /* Setup DMA channel control/status register */ - REG_DMAC_DCCSR(nand_dma_chan) = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; - -#define __nand_cmd(n) (REG8(cmdport) = (n)) -#define __nand_addr(n) (REG8(addrport) = (n)) - - __nand_cmd(NAND_CMD_READ0); - - __nand_addr(0); - if (pagesize != 512) - __nand_addr(0); - - __nand_addr(page & 0xff); - __nand_addr((page >> 8) & 0xff); - - /* One more address cycle for the devices whose number of page address bits > 16 */ - if (((chip->chipsize >> chip->page_shift) >> 16) - 1 > 0) - __nand_addr((page >> 16) & 0xff); - - if (pagesize != 512) - __nand_cmd(NAND_CMD_READSTART); - -#if USE_IRQ - do { - err = wait_event_interruptible_timeout(nand_read_wait_queue, dma_ack, 3 * HZ); - }while(err == -ERESTARTSYS); - nand_status = NAND_NONE; - - if (!err) { - printk("*** NAND READ, Warning, wait event 3s timeout!\n"); - dump_jz_dma_channel(0); - dump_jz_dma_channel(nand_dma_chan); - printk("REG_BCH_CR=%x REG_BCH_CNT=0x%x REG_BCH_INTS=%x\n", REG_BCH_CR, REG_BCH_CNT, REG_BCH_INTS); - printk("databuf[0]=%x\n", databuf[0]); - } - dprintk("timeout remain = %d\n", err); -#else - int timeout; - timeout = 100000; - while ((!__dmac_channel_transmit_end_detected(bch_dma_chan)) && (timeout--)); - if (timeout <= 0) { - printk("not use irq, NAND READ timeout!\n"); - } -#endif - - for (i = 0; i < eccsteps; i++) { - int stat; - struct buf_be_corrected *buf_correct = &buf_correct0; - - buf_correct->data = databuf + eccsize * i; - buf_correct->oob = oobbuf + oob_per_eccsize * i; - - stat = chip->ecc.correct(mtd, (u8 *)buf_correct, (u8 *)&errs[i * ERRS_SIZE], NULL); - if (stat < 0) - mtd->ecc_stats.failed++; - else - mtd->ecc_stats.corrected += stat; - } - -#if defined(CONFIG_MTD_NAND_DMABUF) - memcpy(buf, read_buf, pagesize); - memcpy(chip->oob_poi, read_buf + pagesize, oobsize); -#endif - return 0; -} - -static int nand_read_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -{ - u32 page = global_page; - - nand_read_page_hwecc_bch0(mtd, chip, buf, page); - return 0; -} - -static int nand_read_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -{ - u32 page; - int pagesize = mtd->writesize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* read 1st page */ - nand_read_page_hwecc_bch0(mtd, chip, buf, page); - - /* read 2nd page */ - nand_read_page_hwecc_bch0(mtd, chip, buf + pagesize, page + ppb); - return 0; -} - -#else /* nand read in cpu mode */ - -static int nand_read_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -{ - int i, eccsize = chip->ecc.size; - int eccbytes = chip->ecc.bytes; - int eccsteps = chip->ecc.steps / chip->planenum; - int ecc_pos = chip->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - uint8_t *ecc_calc = chip->buffers->ecccalc; - uint8_t *ecc_code = chip->buffers->ecccode; - uint32_t *eccpos = chip->ecc.layout->eccpos; - int pagesize = mtd->writesize / chip->planenum; - int oobsize = mtd->oobsize / chip->planenum; - int ecctotal = chip->ecc.total / chip->planenum; - static struct buf_be_corrected buf_correct0; - - chip->read_buf(mtd, buf, pagesize); - chip->read_buf(mtd, chip->oob_poi, oobsize); - - for (i = 0; i < ecctotal; i++) { - ecc_code[i] = chip->oob_poi[eccpos[i]]; - } - - for (i = 0; i < eccsteps; i++) { - int stat; - struct buf_be_corrected *buf_correct = &buf_correct0; - - buf_correct->data = buf + eccsize * i; - buf_correct->oob = chip->oob_poi + oob_per_eccsize * i; - - chip->ecc.hwctl(mtd, NAND_ECC_READ); - stat = chip->ecc.correct(mtd, (u8 *)buf_correct, &ecc_code[eccbytes*i], &ecc_calc[eccbytes*i]); - if (stat < 0) - mtd->ecc_stats.failed++; - else - mtd->ecc_stats.corrected += stat; - } - - return 0; -} - -static int nand_read_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -{ - int pagesize = mtd->writesize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - uint32_t page; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* Read first page */ - chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); - nand_read_page_hwecc_bch(mtd, chip, buf); - - /* Read 2nd page */ - chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page + ppb); - nand_read_page_hwecc_bch(mtd, chip, buf+pagesize); - return 0; -} -#endif /* CONFIG_MTD_NAND_DMA */ - -#endif /* CONFIG_MTD_HW_BCH_ECC */ - -/* read oob using two-plane mode */ -static int nand_read_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, - int global_page, int sndcmd) -{ - int page; - int oobsize = mtd->oobsize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* Read first page OOB */ - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - } - chip->read_buf(mtd, chip->oob_poi, oobsize); - /* Read second page OOB */ - page += ppb; - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - sndcmd = 0; - } - chip->read_buf(mtd, chip->oob_poi+oobsize, oobsize); - return 0; -} - -/* write oob using two-plane mode */ -static int nand_write_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, - int global_page) -{ - int status = 0, page; - const uint8_t *buf = chip->oob_poi; - int pagesize = mtd->writesize >> 1; - int oobsize = mtd->oobsize >> 1; - int ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x80, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x80, pagesize, 0x00); - else - chip->cmdfunc(mtd, 0x80, pagesize, page & (1 << (chip->chip_shift - chip->page_shift))); - - chip->write_buf(mtd, buf, oobsize); - /* Send first command to program the OOB data */ - chip->cmdfunc(mtd, 0x11, -1, -1); - ndelay(100); - status = chip->waitfunc(mtd, chip); - - page += ppb; - buf += oobsize; - chip->cmdfunc(mtd, 0x81, pagesize, page); - chip->write_buf(mtd, buf, oobsize); - /* Send command to program the OOB data */ - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); - /* Wait long R/B */ - ndelay(100); - status = chip->waitfunc(mtd, chip); - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -/* nand erase using two-plane mode */ -static void single_erase_cmd_planes(struct mtd_info *mtd, int global_page) -{ - struct nand_chip *chip = mtd->priv; - int page, ppb = mtd->erasesize / mtd->writesize; - - page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ - - /* send cmd 0x60, the MSB should be valid if realplane is 4 */ - if (chip->realplanenum == 2) - chip->cmdfunc(mtd, 0x60, -1, 0x00); - else - chip->cmdfunc(mtd, 0x60, -1, page & (1 << (chip->chip_shift - chip->page_shift))); - - page += ppb; - chip->cmdfunc(mtd, 0x60, -1, page & (~(ppb-1))); /* send cmd 0x60 */ - - chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); /* send cmd 0xd0 */ - /* Do not need wait R/B or check status */ -} - -#if defined(CONFIG_MTD_NAND_DMA) - -#if USE_IRQ -static irqreturn_t nand_dma_irq(int irq, void *dev_id) -{ - u8 dma_chan; - volatile int wakeup = 0; - - dma_chan = irq - IRQ_DMA_0; - - dprintk("jz4750_dma_irq %d, channel %d\n", irq, dma_chan); - - if (__dmac_channel_transmit_halt_detected(dma_chan)) { - __dmac_channel_clear_transmit_halt(dma_chan); - wakeup = 1; - printk("DMA HALT\n"); - } - - if (__dmac_channel_address_error_detected(dma_chan)) { - - REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ - __dmac_channel_clear_address_error(dma_chan); - - REG_DMAC_DSAR(dma_chan) = 0; /* reset source address register */ - REG_DMAC_DTAR(dma_chan) = 0; /* reset destination address register */ - - /* clear address error in DMACR */ - REG_DMAC_DMACR((dma_chan / HALF_DMA_NUM)) &= ~(1 << 2); - wakeup = 1; - printk("DMA address error!\n"); - } - - if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { - __dmac_channel_clear_descriptor_invalid(dma_chan); - wakeup = 1; - printk("DMA DESC INVALID\n"); - } -#if 1 - - while (!__dmac_channel_transmit_end_detected(dma_chan)); - - if (__dmac_channel_count_terminated_detected(dma_chan)) { - dprintk("DMA CT\n"); - __dmac_channel_clear_count_terminated(dma_chan); - wakeup = 0; - } -#endif - - if (__dmac_channel_transmit_end_detected(dma_chan)) { - dprintk("DMA TT\n"); - REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ - __dmac_channel_clear_transmit_end(dma_chan); - wakeup = 1; - } - - if (wakeup) { - dprintk("ack %d irq , wake up dma_chan %d nand_status %d\n", dma_ack, dma_chan, nand_status); - /* wakeup wait event */ - if ((dma_chan == nand_dma_chan) && (nand_status == NAND_PROG)) { - dprintk("nand prog dma irq, wake up----\n"); - dma_ack1 = 1; - wake_up_interruptible(&nand_prog_wait_queue); - } - - if ((dma_chan == bch_dma_chan) && (nand_status == NAND_READ)) { - dprintk("nand read irq, wake up----\n"); - dma_ack = 1; - wake_up_interruptible(&nand_read_wait_queue); - } - wakeup = 0; - } - - return IRQ_HANDLED; -} -#endif /* USE_IRQ */ - -static int jz4750_nand_dma_init(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd->priv; - int eccsize = chip->ecc.size; - int eccsteps = chip->ecc.steps / chip->planenum; - int eccbytes = chip->ecc.bytes; - int ecc_pos = chip->ecc.layout->eccpos[0]; - int oob_per_eccsize = ecc_pos / eccsteps; - int pagesize = mtd->writesize / chip->planenum; - int oobsize = mtd->oobsize / chip->planenum; - int i, err; - jz_dma_desc_8word *desc, *dma_desc_bch_ddr, *dma_desc_nand_ddr, *dma_desc_nand_cmd_pgprog; - u32 *pval_nand_dcs, *pval_bch_ddr, *pval_bch_dcs, *dummy; - u32 next; -#if defined(CONFIG_MTD_NAND_DMABUF) - u8 *oobbuf; -#endif - -#if USE_IRQ - if ((nand_dma_chan = jz_request_dma(DMA_ID_NAND, "nand read or write", nand_dma_irq, IRQF_DISABLED, NULL)) < 0) { - printk("can't reqeust DMA nand channel.\n"); - return 0; - } - dprintk("nand dma channel:%d----\n", nand_dma_chan); - - if ((err = request_irq(IRQ_DMA_0 + bch_dma_chan, nand_dma_irq, IRQF_DISABLED, "bch_dma", NULL))) { - printk("bch_dma irq request err\n"); - return 0; - } -#else - if ((nand_dma_chan = jz_request_dma(DMA_ID_NAND, "nand read or write", NULL, IRQF_DISABLED, NULL)) < 0) { - printk("can't reqeust DMA nand channel.\n"); - return 0; - } - dprintk("nand dma channel:%d----\n", nand_dma_chan); -#endif - - __dmac_channel_enable_clk(nand_dma_chan); - __dmac_channel_enable_clk(bch_dma_chan); - -#if defined(CONFIG_MTD_NAND_DMABUF) - if (pagesize < 4096) { - read_buf = prog_buf = (u8 *) __get_free_page(GFP_KERNEL); - } else { - read_buf = prog_buf = (u8 *) __get_free_pages(GFP_KERNEL, 1); - } - if (!read_buf) - return -ENOMEM; -#endif - /* space for the error reports of bch decoding((4 * 5 * eccsteps) bytes), and the space for the value - * of ddr and dcs of channel 0 and channel nand_dma_chan (4 * (2 + 2) bytes) */ - errs = (u32 *)kmalloc(4 * (2 + 2 + 5 * eccsteps), GFP_KERNEL); - if (!errs) - return -ENOMEM; - - pval_nand_ddr = errs + 5 * eccsteps; - pval_nand_dcs = pval_nand_ddr + 1; - pval_bch_ddr = pval_nand_dcs + 1; - pval_bch_dcs = pval_bch_ddr + 1; - /* space for nand prog waiting target, the content is useless */ - dummy = pval_bch_dcs + 1; - /* space to store CMD_PGPROG(0x10) or 0x11 */ - pval_nand_cmd_pgprog = (u8 *)(dummy + 1); - - /* desc can't across 4KB boundary, as desc base address is fixed */ - /* space of descriptors for nand reading data and oob blocks */ - dma_desc_nand_read = (jz_dma_desc_8word *) __get_free_page(GFP_KERNEL); - if (!dma_desc_nand_read) - return -ENOMEM; - - /* space of descriptors for bch decoding */ - dma_desc_dec = dma_desc_nand_read + 2; - dma_desc_dec1 = dma_desc_dec + eccsteps; - dma_desc_dec2 = dma_desc_dec + eccsteps * 2; - - /* space of descriptors for notifying bch channel */ - dma_desc_bch_ddr = dma_desc_dec2 + eccsteps; - - /* space of descriptors for bch encoding */ - dma_desc_enc = dma_desc_bch_ddr + 2; - dma_desc_enc1 = dma_desc_enc + eccsteps; - - /* space of descriptors for nand programing data and oob blocks */ - dma_desc_nand_prog = dma_desc_enc1 + eccsteps; - - /* space of descriptors for nand prog waiting, including pgprog and sync */ - dma_desc_nand_cmd_pgprog = dma_desc_nand_prog + 2; - - /* space of descriptors for notifying nand channel, including ddr and dcsr */ - dma_desc_nand_ddr = dma_desc_nand_cmd_pgprog + 2; - -/************************************* - * Setup of nand programing descriptors - *************************************/ -#if defined(CONFIG_MTD_NAND_DMABUF) - oobbuf = prog_buf + pagesize; -#endif - /* set descriptor for encoding data blocks */ - desc = dma_desc_enc; - for (i = 0; i < eccsteps; i++) { - next = (CPHYSADDR((u32)dma_desc_enc1) + i * (sizeof(jz_dma_desc_8word))) >> 4; - - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | - DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)prog_buf) + i * eccsize; /* DMA source address */ - desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -#endif - desc->ddadr = (next << 24) + eccsize / DIV_DS_BCH; /* size: eccsize bytes */ - desc->dreqt = DMAC_DRSR_RS_BCH_ENC; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - desc++; - } - - /* set descriptor for encoding oob blocks */ - desc = dma_desc_enc1; - for (i = 0; i < eccsteps; i++) { - next = (CPHYSADDR((u32)dma_desc_enc) + (i + 1) * (sizeof(jz_dma_desc_8word))) >> 4; - - desc->dcmd = - DMAC_DCMD_BLAST | DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | - DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address, 28/4 = 7bytes */ - desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -#endif - desc->ddadr = (next << 24) + (oob_per_eccsize + 3) / 4; /* size: 7 bytes -> 2 words */ - desc->dreqt = DMAC_DRSR_RS_BCH_ENC; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - desc++; - } - - next = (CPHYSADDR((u32)dma_desc_nand_ddr)) >> 4; - desc--; - desc->ddadr = (next << 24) + (oob_per_eccsize + 3) / 4; - - /* set the descriptor to set door bell of nand_dma_chan for programing nand */ - desc = dma_desc_nand_ddr; - *pval_nand_ddr = 1 << (nand_dma_chan - nand_dma_chan / HALF_DMA_NUM * HALF_DMA_NUM); - next = (CPHYSADDR((u32)dma_desc_nand_ddr) + sizeof(jz_dma_desc_8word)) >> 4; - desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; - desc->dsadr = CPHYSADDR((u32)pval_nand_ddr); /* DMA source address */ - desc->dtadr = CPHYSADDR(DMAC_DMADBSR(nand_dma_chan / HALF_DMA_NUM)); /* nand_dma_chan's descriptor addres register */ - desc->ddadr = (next << 24) + 1; /* size: 1 word */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - dprintk("*pval_nand_ddr=0x%x\n", *pval_nand_ddr); - - /* set the descriptor to write dccsr of nand_dma_chan for programing nand, dccsr should be set at last */ - desc++; - *pval_nand_dcs = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; /* set value for writing ddr to enable channel nand_dma_chan */ - desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; - desc->dsadr = CPHYSADDR((u32)pval_nand_dcs); /* DMA source address */ - desc->dtadr = CPHYSADDR(DMAC_DCCSR(nand_dma_chan)); /* address of dma door bell set register */ - desc->ddadr = (0 << 24) + 1; /* size: 1 word */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - dprintk("*pval_nand_dcs=0x%x\n", *pval_nand_dcs); - - /* set descriptor for nand programing data block */ - desc = dma_desc_nand_prog; - next = (CPHYSADDR((u32)dma_desc_nand_prog) + sizeof(jz_dma_desc_8word)) >> 4; - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | - DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)prog_buf); /* DMA source address */ -#endif - desc->dtadr = CPHYSADDR((u32)(chip->IO_ADDR_W)); /* DMA target address */ - desc->ddadr = (next << 24) + pagesize / DIV_DS_NAND; /* size: eccsize bytes */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - - /* set descriptor for nand programing oob block */ - desc++; - next = (CPHYSADDR((u32)dma_desc_nand_cmd_pgprog)) >> 4; - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | - DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)oobbuf); /* DMA source address */ -#endif - desc->dtadr = CPHYSADDR((u32)(chip->IO_ADDR_W)); /* DMA target address: dataport */ - desc->ddadr = (next << 24) + oobsize / DIV_DS_NAND; /* size: eccsize bytes */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - - /* set descriptor for __nand_cmd(CMD_PGPROG) */ - desc = dma_desc_nand_cmd_pgprog; - *pval_nand_cmd_pgprog = NAND_CMD_PAGEPROG; - next = (CPHYSADDR((u32)dma_desc_nand_cmd_pgprog) + sizeof(jz_dma_desc_8word)) >> 4; - desc->dcmd = - DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_8BIT | DMAC_DCMD_LINK; - desc->dsadr = CPHYSADDR((u32)pval_nand_cmd_pgprog); /* DMA source address */ - desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_R | cmd_offset); /* DMA target address: cmdport */ - desc->ddadr = (next << 24) + 1; /* size: 1 byte */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - - /* set descriptor for __nand_sync() */ - desc++; -#if USE_IRQ - desc->dcmd = - DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; -#else - desc->dcmd = - DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -#endif - desc->dsadr = CPHYSADDR((u32)pval_nand_ddr); /* DMA source address */ - desc->dtadr = CPHYSADDR((u32)dummy); /* DMA target address, the content is useless */ - desc->ddadr = (0 << 24) + 1; /* size: 1 word */ - desc->dreqt = DMAC_DRSR_RS_NAND; - dprintk("1cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - - /* eccsteps*2 + 2 + 2 + 2: - dma_desc_enc + dma_desc_enc1 + dma_desc_nand_prog(oob) + dma_desc_nand_ddr(csr) - + dma_desc_nand_cmd_pgprog(sync) */ - dma_cache_wback_inv((u32)dma_desc_enc, (eccsteps * 2 + 2 + 2 + 2) * (sizeof(jz_dma_desc_8word))); - /* 4*6: pval_nand_ddr, pval_nand_dcs, pval_bch_ddr, pval_bch_dcs, dummy, pval_nand_cmd_pgprog */ - dma_cache_wback_inv((u32)pval_nand_ddr, 4 * 8); /* 8 words, a cache line */ - -/************************************* - * Setup of nand reading descriptors - *************************************/ -#if defined(CONFIG_MTD_NAND_DMABUF) - oobbuf = read_buf + pagesize; -#endif - /* set descriptor for nand reading data block */ - desc = dma_desc_nand_read; - next = (CPHYSADDR((u32)dma_desc_nand_read) + sizeof(jz_dma_desc_8word)) >> 4; - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | - DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; - desc->dsadr = CPHYSADDR((u32)(chip->IO_ADDR_R)); /* DMA source address */ -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dtadr = CPHYSADDR((u32)read_buf); /* DMA target address */ -#endif - desc->ddadr = (next << 24) + pagesize / DIV_DS_NAND; /* size: eccsize bytes */ - desc->dreqt = DMAC_DRSR_RS_NAND; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - - /* set descriptor for nand reading oob block */ - desc++; - next = (CPHYSADDR((u32)dma_desc_bch_ddr)) >> 4; - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | - DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; - desc->dsadr = CPHYSADDR((u32)(chip->IO_ADDR_R)); /* DMA source address */ -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dtadr = CPHYSADDR((u32)oobbuf); /* DMA target address */ -#endif - desc->ddadr = (next << 24) + oobsize / DIV_DS_NAND; /* size: eccsize bytes */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); - - /* set the descriptor to set door bell for bch */ - desc = dma_desc_bch_ddr; - *pval_bch_ddr = DMAC_DMADBSR_DBS0; // set value for writing ddr to enable channel 0 - next = (CPHYSADDR((u32)dma_desc_bch_ddr) + sizeof(jz_dma_desc_8word)) >> 4; - desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; - desc->dsadr = CPHYSADDR((u32)pval_bch_ddr); /* DMA source address */ - desc->dtadr = CPHYSADDR(DMAC_DMADBSR(0)); /* channel 1's descriptor addres register */ - desc->ddadr = (next << 24) + 1; /* size: 1 word */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - - /* set descriptor for writing dcsr */ - desc++; - *pval_bch_dcs = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; // set value for writing ddr to enable channel 1 - desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; - desc->dsadr = CPHYSADDR((u32)pval_bch_dcs); /* DMA source address */ - desc->dtadr = CPHYSADDR(DMAC_DCCSR(bch_dma_chan)); /* address of dma door bell set register */ - desc->ddadr = (0 << 24) + 1; /* size: 1 word */ - desc->dreqt = DMAC_DRSR_RS_AUTO; - - /* descriptors for data to be written to bch */ - desc = dma_desc_dec; - for (i = 0; i < eccsteps; i++) { - next = CPHYSADDR((u32)dma_desc_dec1 + i * (sizeof(jz_dma_desc_8word))) >> 4; - - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | - DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)read_buf) + i * eccsize; /* DMA source address */ -#endif - desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ - desc->ddadr = (next << 24) + eccsize / DIV_DS_BCH; /* size: eccsize bytes */ - desc->dreqt = DMAC_DRSR_RS_BCH_DEC; - dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - /* descriptors for oob to be written to bch */ - desc = dma_desc_dec1; - for (i = 0; i < eccsteps; i++) { - next = CPHYSADDR((u32)dma_desc_dec2 + i * (sizeof(jz_dma_desc_8word))) >> 4; - - desc->dcmd = - DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | - DMAC_DCMD_DS_8BIT | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address */ -#endif - desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ - desc->ddadr = (next << 24) + oob_per_eccsize; /* size: 7 bytes */ - desc->dreqt = DMAC_DRSR_RS_BCH_DEC; - dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - - /* descriptors for parities to be written to bch */ - desc = dma_desc_dec2; - for (i = 0; i < eccsteps; i++) { - next = (CPHYSADDR((u32)dma_desc_dec) + (i + 1) * (sizeof(jz_dma_desc_8word))) >> 4; - - desc->dcmd = - DMAC_DCMD_BLAST | DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | - DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -#if defined(CONFIG_MTD_NAND_DMABUF) - desc->dsadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA source address */ -#endif - desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ - desc->ddadr = (next << 24) + (eccbytes + 15) / DIV_DS_BCH; /* size: eccbytes bytes */ - desc->dreqt = DMAC_DRSR_RS_BCH_DEC; - dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, - desc->ddadr); - desc++; - } - desc--; - desc->dcmd &= ~DMAC_DCMD_LINK; -#if USE_IRQ - desc->dcmd |= DMAC_DCMD_TIE; -#endif - - dma_cache_wback_inv((u32)dma_desc_nand_read, (2 + 2 + eccsteps * 3) * (sizeof(jz_dma_desc_8word))); - dma_cache_wback_inv((u32)pval_bch_ddr, 4 * 2); /* two words */ - - return 0; -} - -#endif /* CONFIG_MTD_NAND_DMA */ -/* - * Main initialization routine - */ -int __init jznand_init(void) -{ - struct nand_chip *this; - int nr_partitions, ret, i; - - printk(KERN_INFO "JZ NAND init"); -#if defined(CONFIG_MTD_NAND_DMA) -#if defined(CONFIG_MTD_NAND_DMABUF) - printk(KERN_INFO " DMA mode, using DMA buffer in NAND driver.\n"); -#else - printk(KERN_INFO " DMA mode, using DMA buffer in upper layer.\n"); -#endif -#else - printk(KERN_INFO " CPU mode.\n"); -#endif - - - /* Allocate memory for MTD device structure and private data */ - jz_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); - if (!jz_mtd) { - printk("Unable to allocate JzSOC NAND MTD device structure.\n"); - return -ENOMEM; - } - - /* Allocate memory for NAND when using only one plane */ - jz_mtd1 = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); - if (!jz_mtd1) { - printk ("Unable to allocate JzSOC NAND MTD device structure 1.\n"); - kfree(jz_mtd); - return -ENOMEM; - } - - /* Get pointer to private data */ - this = (struct nand_chip *)(&jz_mtd[1]); - - /* Initialize structures */ - memset((char *)jz_mtd, 0, sizeof(struct mtd_info)); - memset((char *)this, 0, sizeof(struct nand_chip)); - - /* Link the private data with the MTD structure */ - jz_mtd->priv = this; - - if (is_share_mode()) { - addr_offset = NAND_ADDR_OFFSET0; - cmd_offset = NAND_CMD_OFFSET0; - } else { - addr_offset = NAND_ADDR_OFFSET1; - cmd_offset = NAND_CMD_OFFSET1; - } - - /* Set & initialize NAND Flash controller */ - jz_device_setup(); - - /* Set address of NAND IO lines to static bank1 by default */ - this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; - this->IO_ADDR_W = (void __iomem *)NAND_DATA_PORT1; - this->cmd_ctrl = jz_hwcontrol; - this->dev_ready = jz_device_ready; - -#ifdef CONFIG_MTD_HW_BCH_ECC - this->ecc.calculate = jzsoc_nand_calculate_bch_ecc; - this->ecc.correct = jzsoc_nand_bch_correct_data; - this->ecc.hwctl = jzsoc_nand_enable_bch_hwecc; - this->ecc.mode = NAND_ECC_HW; - this->ecc.size = 512; - this->ecc.read_page = nand_read_page_hwecc_bch; - this->ecc.write_page = nand_write_page_hwecc_bch; -#if defined(CONFIG_MTD_HW_BCH_8BIT) - this->ecc.bytes = 13; -#else - this->ecc.bytes = 7; -#endif -#endif - -#ifdef CONFIG_MTD_SW_HM_ECC - this->ecc.mode = NAND_ECC_SOFT; -#endif - /* 20 us command delay time */ - this->chip_delay = 20; - /* Scan to find existance of the device */ - ret = nand_scan_ident(jz_mtd, NAND_MAX_CHIPS); - - if (!ret) { - if (this->planenum == 2) { - /* reset nand functions */ - this->erase_cmd = single_erase_cmd_planes; - this->ecc.read_page = nand_read_page_hwecc_bch_planes; - this->ecc.write_page = nand_write_page_hwecc_bch_planes; - this->ecc.read_oob = nand_read_oob_std_planes; - this->ecc.write_oob = nand_write_oob_std_planes; - - printk(KERN_INFO "Nand using two-plane mode, " - "and resized to writesize:%d oobsize:%d blocksize:0x%x \n", - jz_mtd->writesize, jz_mtd->oobsize, jz_mtd->erasesize); - } - } - - /* Determine whether all the partitions will use multiple planes if supported */ - nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); - all_use_planes = 1; - for (i = 0; i < nr_partitions; i++) { - all_use_planes &= partition_info[i].use_planes; - } - - if (!ret) - ret = nand_scan_tail(jz_mtd); - - if (ret){ - kfree (jz_mtd1); - kfree (jz_mtd); - return -ENXIO; - } - -#if defined(CONFIG_MTD_NAND_DMA) - jz4750_nand_dma_init(jz_mtd); -#endif - - ((struct nand_chip *) (&jz_mtd1[1]))->ecc.read_page = nand_read_page_hwecc_bch; - ((struct nand_chip *) (&jz_mtd1[1]))->ecc.write_page = nand_write_page_hwecc_bch; - - /* Register the partitions */ - printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); - - if ((this->planenum == 2) && !all_use_planes) { - for (i = 0; i < nr_partitions; i++) { - if (partition_info[i].use_planes) - add_mtd_partitions(jz_mtd, &partition_info[i], 1); - else - add_mtd_partitions(jz_mtd1, &partition_info[i], 1); - } - } else { - kfree(jz_mtd1); - add_mtd_partitions(jz_mtd, partition_info, nr_partitions); - } - return 0; -} - -module_init(jznand_init); - -/* - * Clean up routine - */ -#ifdef MODULE - -#if defined(CONFIG_MTD_NAND_DMA) -static int jz4750_nand_dma_exit(struct mtd_info *mtd) -{ - int pagesize = mtd->writesize / chip->planenum; - -#if USE_IRQ - free_irq(IRQ_DMA_0 + nand_dma_chan, NULL); - free_irq(IRQ_DMA_0 + bch_dma_chan, NULL); -#endif - - /* space for the error reports of bch decoding((4 * 5 * eccsteps) bytes), - * and the space for the value of ddr and dcs of channel 0 and channel - * nand_dma_chan (4 * (2 + 2) bytes) */ - kfree(errs); - - /* space for dma_desc_nand_read contains dma_desc_nand_prog, - * dma_desc_enc and dma_desc_dec */ - free_page((u32)dma_desc_nand_read); - -#if defined(CONFIG_MTD_NAND_DMABUF) - if (pagesize < 4096) { - free_page((u32)prog_buf); - } else { - free_pages((u32)prog_buf, 1); - } -#endif - - return 0; -} -#endif - -static void __exit jznand_cleanup(void) -{ -#if defined(CONFIG_MTD_NAND_DMA) - jz4750_nand_dma_exit(jz_mtd); -#endif - - /* Unregister partitions */ - del_mtd_partitions(jz_mtd); - - /* Unregister the device */ - del_mtd_device(jz_mtd); - - /* Free the MTD device structure */ - if ((this->planenum == 2) && !all_use_planes) - kfree (jz_mtd1); - kfree(jz_mtd); -} - -module_exit(jznand_cleanup); -#endif diff --git a/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch b/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch index 81e6f8516..99e6b70c2 100644 --- a/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch +++ b/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch @@ -1172,1549 +1172,6 @@ diff -ru linux-2.6/drivers/mmc/host/Makefile /plain/src/qi/linux-2.6.27.git.svn/ obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_IMX) += imxmmc.o -diff -ru linux-2.6/drivers/mtd/mtd_blkdevs.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtd_blkdevs.c ---- linux-2.6/drivers/mtd/mtd_blkdevs.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtd_blkdevs.c 2009-08-12 10:39:09.000000000 +0200 -@@ -39,8 +39,8 @@ - unsigned long block, nsect; - char *buf; - -- block = req->sector << 9 >> tr->blkshift; -- nsect = req->current_nr_sectors << 9 >> tr->blkshift; -+ block = ((unsigned long long)req->sector) << 9 >> tr->blkshift; -+ nsect = ((unsigned long long)req->current_nr_sectors) << 9 >> tr->blkshift; - - buf = req->buffer; - -@@ -275,7 +275,7 @@ - - /* 2.5 has capacity in units of 512 bytes while still - having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ -- set_capacity(gd, (new->size * tr->blksize) >> 9); -+ set_capacity(gd, ((u_int64_t)new->size * tr->blksize) >> 9); - - gd->private_data = new; - new->blkcore_priv = gd; -diff -ru linux-2.6/drivers/mtd/mtdblock.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdblock.c ---- linux-2.6/drivers/mtd/mtdblock.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdblock.c 2009-08-12 10:39:09.000000000 +0200 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -359,12 +360,26 @@ - kfree(dev); - } - -+static int mtdblock_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) -+{ -+ struct gendisk *gd = dev->blkcore_priv; -+ memset(geo, 0, sizeof(*geo)); -+ geo->heads = 4; -+ geo->sectors = 16; -+ geo->cylinders = dev->size/(4*16); -+ -+ printk("cylinders: %x \n", geo->cylinders); -+ printk("sects: %x\n", dev->size); -+ return 0; -+} -+ - static struct mtd_blktrans_ops mtdblock_tr = { - .name = "mtdblock", - .major = 31, - .part_bits = 0, - .blksize = 512, - .open = mtdblock_open, -+ .getgeo = mtdblock_getgeo, - .flush = mtdblock_flush, - .release = mtdblock_release, - .readsect = mtdblock_readsect, -diff -ru linux-2.6/drivers/mtd/mtdchar.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdchar.c ---- linux-2.6/drivers/mtd/mtdchar.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdchar.c 2009-08-12 10:39:09.000000000 +0200 -@@ -145,8 +145,7 @@ - - DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); - -- /* Only sync if opened RW */ -- if ((file->f_mode & 2) && mtd->sync) -+ if (mtd->sync) - mtd->sync(mtd); - - put_mtd_device(mtd); -@@ -165,7 +164,7 @@ - { - struct mtd_file_info *mfi = file->private_data; - struct mtd_info *mtd = mfi->mtd; -- size_t retlen=0; -+ size_mtd_t retlen=0; - size_t total_retlen=0; - int ret=0; - int len; -@@ -259,7 +258,7 @@ - struct mtd_file_info *mfi = file->private_data; - struct mtd_info *mtd = mfi->mtd; - char *kbuf; -- size_t retlen; -+ size_mtd_t retlen; - size_t total_retlen=0; - int ret=0; - int len; -@@ -592,6 +591,72 @@ - break; - } - -+ case MEMWRITEPAGE: -+ { -+ struct mtd_page_buf buf; -+ struct mtd_oob_ops ops; -+ -+ memset(&ops, 0, sizeof(ops)); -+#if 1 -+ if(!(file->f_mode & 2)) -+ return -EPERM; -+#endif -+ -+ if (copy_from_user(&buf, argp, sizeof(struct mtd_page_buf))) -+ return -EFAULT; -+ -+ if (buf.ooblength > mtd->oobsize) -+ return -EINVAL; -+ -+ if (!mtd->write_oob) -+ ret = -EOPNOTSUPP; -+ else -+ ret = access_ok(VERIFY_READ, buf.oobptr, -+ buf.ooblength) ? 0 : EFAULT; -+ -+ if (ret) -+ return ret; -+ -+ ops.len = mtd->writesize; -+ ops.ooblen = buf.ooblength; -+ ops.ooboffs = buf.start & (mtd->oobsize - 1); -+ ops.mode = MTD_OOB_PLACE; -+ -+ if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) -+ return -EINVAL; -+ -+ /* alloc memory and copy oob data from user mode to kernel mode */ -+ ops.oobbuf = kmalloc(buf.ooblength, GFP_KERNEL); -+ if (!ops.oobbuf) -+ return -ENOMEM; -+ -+ if (copy_from_user(ops.oobbuf, buf.oobptr, buf.ooblength)) { -+ kfree(ops.oobbuf); -+ return -EFAULT; -+ } -+ -+ /* alloc memory and copy page data from user mode to kernel mode */ -+ ops.datbuf = kmalloc(mtd->writesize, GFP_KERNEL); -+ if (!ops.datbuf) -+ return -ENOMEM; -+ -+ if (copy_from_user(ops.datbuf, buf.datptr, mtd->writesize)) { -+ kfree(ops.datbuf); -+ return -EFAULT; -+ } -+ -+ buf.start &= ~(mtd->oobsize - 1); -+ ret = mtd->write_oob(mtd, buf.start, &ops); -+ -+ if (copy_to_user(argp + 2*sizeof(uint32_t), &ops.retlen, -+ sizeof(uint32_t))) -+ ret = -EFAULT; -+ -+ kfree(ops.oobbuf); -+ kfree(ops.datbuf); -+ break; -+ } -+ - case MEMLOCK: - { - struct erase_info_user einfo; -@@ -643,9 +708,9 @@ - - case MEMGETBADBLOCK: - { -- loff_t offs; -+ loff_mtd_t offs; - -- if (copy_from_user(&offs, argp, sizeof(loff_t))) -+ if (copy_from_user(&offs, argp, sizeof(loff_mtd_t))) - return -EFAULT; - if (!mtd->block_isbad) - ret = -EOPNOTSUPP; -@@ -656,9 +721,9 @@ - - case MEMSETBADBLOCK: - { -- loff_t offs; -+ loff_mtd_t offs; - -- if (copy_from_user(&offs, argp, sizeof(loff_t))) -+ if (copy_from_user(&offs, argp, sizeof(loff_mtd_t))) - return -EFAULT; - if (!mtd->block_markbad) - ret = -EOPNOTSUPP; -@@ -773,6 +838,7 @@ - } - - default: -+ printk("line : %d\n", __LINE__); - ret = -ENOTTY; - } - -diff -ru linux-2.6/drivers/mtd/mtdcore.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdcore.c ---- linux-2.6/drivers/mtd/mtdcore.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdcore.c 2009-08-12 10:39:09.000000000 +0200 -@@ -297,10 +298,10 @@ - */ - - int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, -- unsigned long count, loff_t to, size_t *retlen) -+ unsigned long count, loff_mtd_t to, size_mtd_t *retlen) - { - unsigned long i; -- size_t totlen = 0, thislen; -+ size_mtd_t totlen = 0, thislen; - int ret = 0; - - if(!mtd->write) { -@@ -344,7 +345,7 @@ - if (!this) - return 0; - -- return sprintf(buf, "mtd%d: %8.8x %8.8x \"%s\"\n", i, this->size, -+ return sprintf(buf, "mtd%d: %09llx %8.8x \"%s\"\n", i, this->size, - this->erasesize, this->name); - } - -diff -ru linux-2.6/drivers/mtd/mtdpart.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdpart.c ---- linux-2.6/drivers/mtd/mtdpart.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/mtdpart.c 2009-08-12 10:39:09.000000000 +0200 -@@ -26,7 +26,7 @@ - struct mtd_part { - struct mtd_info mtd; - struct mtd_info *master; -- u_int32_t offset; -+ u_int64_t offset; - int index; - struct list_head list; - int registered; -@@ -44,8 +44,8 @@ - * to the _real_ device. - */ - --static int part_read(struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, u_char *buf) -+static int part_read(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -+ size_mtd_t *retlen, u_char *buf) - { - struct mtd_part *part = PART(mtd); - int res; -@@ -65,8 +65,8 @@ - return res; - } - --static int part_point(struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, void **virt, resource_size_t *phys) -+static int part_point(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -+ size_mtd_t *retlen, void **virt, resource_size_t *phys) - { - struct mtd_part *part = PART(mtd); - if (from >= mtd->size) -@@ -77,14 +77,14 @@ - len, retlen, virt, phys); - } - --static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len) -+static void part_unpoint(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len) - { - struct mtd_part *part = PART(mtd); - - part->master->unpoint(part->master, from + part->offset, len); - } - --static int part_read_oob(struct mtd_info *mtd, loff_t from, -+static int part_read_oob(struct mtd_info *mtd, loff_mtd_t from, - struct mtd_oob_ops *ops) - { - struct mtd_part *part = PART(mtd); -@@ -105,8 +105,8 @@ - return res; - } - --static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, -- size_t len, size_t *retlen, u_char *buf) -+static int part_read_user_prot_reg(struct mtd_info *mtd, loff_mtd_t from, -+ size_mtd_t len, size_mtd_t *retlen, u_char *buf) - { - struct mtd_part *part = PART(mtd); - return part->master->read_user_prot_reg(part->master, from, -@@ -114,14 +114,14 @@ - } - - static int part_get_user_prot_info(struct mtd_info *mtd, -- struct otp_info *buf, size_t len) -+ struct otp_info *buf, size_mtd_t len) - { - struct mtd_part *part = PART(mtd); - return part->master->get_user_prot_info(part->master, buf, len); - } - --static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, -- size_t len, size_t *retlen, u_char *buf) -+static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_mtd_t from, -+ size_mtd_t len, size_mtd_t *retlen, u_char *buf) - { - struct mtd_part *part = PART(mtd); - return part->master->read_fact_prot_reg(part->master, from, -@@ -129,14 +129,14 @@ - } - - static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, -- size_t len) -+ size_mtd_t len) - { - struct mtd_part *part = PART(mtd); - return part->master->get_fact_prot_info(part->master, buf, len); - } - --static int part_write(struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf) -+static int part_write(struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, -+ size_mtd_t *retlen, const u_char *buf) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) -@@ -149,8 +149,8 @@ - len, retlen, buf); - } - --static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const u_char *buf) -+static int part_panic_write(struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, -+ size_mtd_t *retlen, const u_char *buf) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) -@@ -163,7 +163,7 @@ - len, retlen, buf); - } - --static int part_write_oob(struct mtd_info *mtd, loff_t to, -+static int part_write_oob(struct mtd_info *mtd, loff_mtd_t to, - struct mtd_oob_ops *ops) - { - struct mtd_part *part = PART(mtd); -@@ -178,23 +178,23 @@ - return part->master->write_oob(part->master, to + part->offset, ops); - } - --static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, -- size_t len, size_t *retlen, u_char *buf) -+static int part_write_user_prot_reg(struct mtd_info *mtd, loff_mtd_t from, -+ size_mtd_t len, size_mtd_t *retlen, u_char *buf) - { - struct mtd_part *part = PART(mtd); - return part->master->write_user_prot_reg(part->master, from, - len, retlen, buf); - } - --static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, -- size_t len) -+static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_mtd_t from, -+ size_mtd_t len) - { - struct mtd_part *part = PART(mtd); - return part->master->lock_user_prot_reg(part->master, from, len); - } - - static int part_writev(struct mtd_info *mtd, const struct kvec *vecs, -- unsigned long count, loff_t to, size_t *retlen) -+ unsigned long count, loff_mtd_t to, size_mtd_t *retlen) - { - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) -@@ -235,7 +235,7 @@ - } - EXPORT_SYMBOL_GPL(mtd_erase_callback); - --static int part_lock(struct mtd_info *mtd, loff_t ofs, size_t len) -+static int part_lock(struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len) - { - struct mtd_part *part = PART(mtd); - if ((len + ofs) > mtd->size) -@@ -243,7 +243,7 @@ - return part->master->lock(part->master, ofs + part->offset, len); - } - --static int part_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) -+static int part_unlock(struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len) - { - struct mtd_part *part = PART(mtd); - if ((len + ofs) > mtd->size) -@@ -269,7 +269,7 @@ - part->master->resume(part->master); - } - --static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) -+static int part_block_isbad(struct mtd_info *mtd, loff_mtd_t ofs) - { - struct mtd_part *part = PART(mtd); - if (ofs >= mtd->size) -@@ -278,7 +278,7 @@ - return part->master->block_isbad(part->master, ofs); - } - --static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) -+static int part_block_markbad(struct mtd_info *mtd, loff_mtd_t ofs) - { - struct mtd_part *part = PART(mtd); - int res; -@@ -317,7 +317,7 @@ - - static struct mtd_part *add_one_partition(struct mtd_info *master, - const struct mtd_partition *part, int partno, -- u_int32_t cur_offset) -+ u_int64_t cur_offset) - { - struct mtd_part *slave; - -@@ -345,6 +345,7 @@ - - slave->mtd.read = part_read; - slave->mtd.write = part_write; -+ slave->mtd.priv = master->priv; //add by Nancy - - if (master->panic_write) - slave->mtd.panic_write = part_panic_write; -@@ -395,18 +396,20 @@ - slave->offset = cur_offset; - if (slave->offset == MTDPART_OFS_NXTBLK) { - slave->offset = cur_offset; -- if ((cur_offset % master->erasesize) != 0) { -+ if (((u32)cur_offset % master->erasesize) != 0) { - /* Round up to next erasesize */ -- slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize; -- printk(KERN_NOTICE "Moving partition %d: " -- "0x%08x -> 0x%08x\n", partno, -- cur_offset, slave->offset); -+ //slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize; -+ slave->offset = ((cur_offset >> (ffs(master->erasesize)-1)) + 1) * master->erasesize; -+ printk(KERN_NOTICE "Moving partition %d: " -+ "0x%09llx -> 0x%09llx\n", partno, -+ cur_offset, slave->offset); - } - } -+ - if (slave->mtd.size == MTDPART_SIZ_FULL) - slave->mtd.size = master->size - slave->offset; - -- printk(KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, -+ printk (KERN_NOTICE "0x%09llx-0x%09llx : \"%s\"\n", slave->offset, - slave->offset + slave->mtd.size, slave->mtd.name); - - /* let's do some sanity checks */ -@@ -420,9 +423,10 @@ - } - if (slave->offset + slave->mtd.size > master->size) { - slave->mtd.size = master->size - slave->offset; -- printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n", -+ printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n", - part->name, master->name, slave->mtd.size); - } -+ - if (master->numeraseregions > 1) { - /* Deal with variable erase size stuff */ - int i, max = master->numeraseregions; -@@ -449,7 +453,7 @@ - } - - if ((slave->mtd.flags & MTD_WRITEABLE) && -- (slave->offset % slave->mtd.erasesize)) { -+ ((u32)slave->offset % slave->mtd.erasesize)) { - /* Doesn't start on a boundary of major erase size */ - /* FIXME: Let it be writable if it is on a boundary of - * _minor_ erase size though */ -@@ -458,7 +462,7 @@ - part->name); - } - if ((slave->mtd.flags & MTD_WRITEABLE) && -- (slave->mtd.size % slave->mtd.erasesize)) { -+ ((u32)slave->mtd.size % slave->mtd.erasesize)) { - slave->mtd.flags &= ~MTD_WRITEABLE; - printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", - part->name); -@@ -466,7 +470,7 @@ - - slave->mtd.ecclayout = master->ecclayout; - if (master->block_isbad) { -- uint32_t offs = 0; -+ uint64_t offs = 0; - - while (offs < slave->mtd.size) { - if (master->block_isbad(master, -@@ -501,7 +505,7 @@ - int nbparts) - { - struct mtd_part *slave; -- u_int32_t cur_offset = 0; -+ u_int64_t cur_offset = 0; - int i, j, ret; - - printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); -diff -ru linux-2.6/drivers/mtd/nand/Kconfig /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/Kconfig ---- linux-2.6/drivers/mtd/nand/Kconfig 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/Kconfig 2009-08-12 10:39:09.000000000 +0200 -@@ -406,4 +406,121 @@ - Enables support for NAND Flash chips wired onto Freescale PowerPC - processor localbus with User-Programmable Machine support. - -+config MTD_NAND_JZ4740 -+ tristate "Support NAND Flash device on Jz4740 board" -+ depends on SOC_JZ4740 -+ help -+ Support NAND Flash device on Jz4740 board -+ -+config MTD_NAND_JZ4750 -+ tristate "Support NAND Flash device on Jz4750 board" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ Support NAND Flash device on Jz4750 board -+ -+config MTD_NAND_CS2 -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use NAND on CS2_N of JZSOC' -+ default n -+ -+config MTD_NAND_CS3 -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use NAND on CS3_N of JZSOC' -+ default n -+ -+config MTD_NAND_CS4 -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use NAND on CS4_N of JZSOC' -+ default n -+ -+config MTD_NAND_MULTI_PLANE -+ depends on MTD_NAND_JZ4730 || MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -+ bool 'Use multiple planes if the NAND supports' -+ default y -+ help -+ It is just supported on jz4740 now. -+ -+if MTD_NAND_JZ4740 || MTD_NAND_JZ4730 || MTD_NAND_JZ4750 -+choice -+ prompt "ECC type" -+ default CONFIG_MTD_SW_HM_ECC -+ -+config MTD_HW_HM_ECC -+ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4730 -+ bool 'Select hardware HM ECC' -+ -+config MTD_SW_HM_ECC -+ bool 'Select software HM ECC' -+ -+config MTD_HW_RS_ECC -+ depends on MTD_NAND_JZ4740 -+ bool 'Select hardware RS ECC' -+ -+config MTD_HW_BCH_ECC -+ depends on MTD_NAND_JZ4750 -+ bool 'Select hardware BCH ECC' -+endchoice -+ -+choice -+ prompt "4 bit or 8 bit BCH ecc" -+ depends on MTD_HW_BCH_ECC -+ default CONFIG_MTD_HW_BCH_4BIT -+ -+config MTD_HW_BCH_4BIT -+ bool '4 bit' -+ -+config MTD_HW_BCH_8BIT -+ bool '8 bit' -+ -+endchoice -+ -+config MTD_NAND_DMA -+ depends on MTD_HW_BCH_ECC -+ bool 'Use DMA mode' -+ help -+ This enables using DMA for reading and writing NAND flash, if not selected, -+ then CPU mode is used. -+ -+config MTD_NAND_DMABUF -+ depends on MTD_NAND_DMA -+ bool 'use DMA buffer in NAND driver' -+ help -+ It's better to say NO. If saying yes, DMA buffers will be allocated for -+ NAND reading and writing in NAND driver instead of upper layer. It's -+ slower. Just usable on CS1_N now. By saying NO, upper buffers will be -+ used as DMA buffer. It's faster, but kmalloc instead of vmalloc is required. -+endif -+ -+config MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -+ bool "MTDBLOCK write verify enable" -+ default n -+ help -+ This will enable the write verification, which will read back data to check -+ after doing a write opetaion. -+ -+ It will be used by the JZ mtdblock driver (mtdblock-jz.c). -+ -+config MTD_OOB_COPIES -+ int "how many copies of the fs info in the oob area" -+ default 3 -+ range 0 128 -+ depends on MTD -+ help -+ This defines the copies of the fs info in the oob area inside a block. -+ Value ranges from 0 to (pages_per_block - 1). -+ -+ It will be used by the JZ mtdblock driver (mtdblock-jz.c). -+ -+config MTD_BADBLOCK_FLAG_PAGE -+ int "which page inside a block will store the badblock mark" -+ default 0 -+ range 0 127 -+ depends on MTD -+ help -+ This defines which page of a block will store the badblock mark. -+ Value ranges from 0 to (pages_per_block - 1). -+ -+ Old SLC NANDs store the badblock mark in the first page of a block, but -+ most modern MLC NANDs store it in the last page of a block. -+ - endif # MTD_NAND -diff -ru linux-2.6/drivers/mtd/nand/Makefile /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/Makefile ---- linux-2.6/drivers/mtd/nand/Makefile 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/Makefile 2009-08-12 10:39:09.000000000 +0200 -@@ -34,5 +34,7 @@ - obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o - obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o - obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o -+obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o -+obj-$(CONFIG_MTD_NAND_JZ4750) += jz4750_nand.o - - nand-objs := nand_base.o nand_bbt.o -diff -ru linux-2.6/drivers/mtd/nand/nand_base.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/nand_base.c ---- linux-2.6/drivers/mtd/nand/nand_base.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/nand_base.c 2009-08-12 10:39:09.000000000 +0200 -@@ -52,6 +52,16 @@ - #include - #endif - -+#include -+ -+u8 nand_nce; /* indicates which chip select on JZSOC is used for -+ current nand chip */ -+int global_page; /* page index of large page used for nand with multiple planes */ -+ -+struct mtd_info *jz_mtd1 = NULL; /* for 1 plane operation */ -+char all_use_planes = 1; /* indicates whether multiple planes operation is used -+ by all partitions if multiple planes is supported by NAND */ -+ - /* Define default oob placement schemes for large and small page devices */ - static struct nand_ecclayout nand_oob_8 = { - .eccbytes = 3, -@@ -72,6 +82,20 @@ - }; - - static struct nand_ecclayout nand_oob_64 = { -+#if defined(CONFIG_MTD_HW_RS_ECC) || defined(CONFIG_MTD_HW_BCH_ECC) -+/* Reed-Solomon ECC or BCH ECC */ -+ .eccbytes = 36, -+ .eccpos = { -+ 28, 29, 30, 31, -+ 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63}, -+ .oobfree = { -+ {.offset = 2, -+ . length = 26}} -+#else -+/* HW&SW Hamming ECC */ - .eccbytes = 24, - .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, -@@ -80,12 +104,85 @@ - .oobfree = { - {.offset = 2, - .length = 38}} -+#endif -+}; -+ -+static struct nand_ecclayout nand_oob_128 = { -+#if defined(CONFIG_MTD_HW_RS_ECC) -+/* Reed-Solomon ECC */ -+ .eccbytes = 72, -+ .eccpos = { -+ 56, 57, 58, 59, 60, 61, 62, 63, -+ 64, 65, 66, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = { -+ {.offset = 2, -+ . length = 54}} -+ -+#elif defined(CONFIG_MTD_HW_BCH_ECC) -+#if !defined(CONFIG_MTD_HW_BCH_8BIT) -+/* 4-bit BCH ECC */ -+ .eccbytes = 56, -+ .eccpos = { -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = { -+ {.offset = 2, -+ . length = 70}} -+ -+#else -+/* 8-bit BCH ECC */ -+ .eccbytes = 104, -+ .eccpos = { -+ 24, 25, 26, 27, 28, 29, 30, 31, -+ 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63, -+ 64, 65, 66, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = { -+ {.offset = 2, -+ . length = 22}} -+ -+#endif -+#else -+/* HW&SW Hamming ECC */ -+ .eccbytes = 48, -+ .eccpos = { -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = { -+ {.offset = 2, -+ .length = 78}} -+#endif - }; - - static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, - int new_state); - --static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, -+static int nand_do_write_oob(struct mtd_info *mtd, loff_mtd_t to, - struct mtd_oob_ops *ops); - - /* -@@ -95,6 +192,35 @@ - DEFINE_LED_TRIGGER(nand_led_trigger); - - /** -+ * ffs_ll - find first bit set in a 64bit word. -+ * @word: The word to search -+ */ -+static inline int ffs_ll(u64 word) -+{ -+ u32 low = word & 0xffffffff; -+ u32 high = word >> 32; -+ int i; -+ -+ for(i = 0; i < 32; i++) { -+ if (low & 0x1) -+ break; -+ low >>= 1; -+ } -+ if (i == 32) { -+ for(i = 0; i < 32; i++) { -+ if (high & 0x1) -+ break; -+ high >>= 1; -+ } -+ i += 32; -+ } -+ if (i == 64) -+ return 0; -+ else -+ return (i+1); -+} -+ -+/** - * nand_release_device - [GENERIC] release chip - * @mtd: MTD device structure - * -@@ -169,6 +295,20 @@ - chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); - break; - case 0: -+ nand_nce = NAND_NCE1; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ case 1: -+ nand_nce = NAND_NCE2; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ case 2: -+ nand_nce = NAND_NCE3; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ case 3: -+ nand_nce = NAND_NCE4; -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - break; - - default: -@@ -298,13 +438,19 @@ - * - * Check, if the block is bad. - */ --static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) -+static int nand_block_bad(struct mtd_info *mtd, loff_mtd_t ofs, int getchip) - { -- int page, chipnr, res = 0; -+ int page, page1 = 0, chipnr, res = 0; - struct nand_chip *chip = mtd->priv; - u16 bad; - -- page = (int)(ofs >> chip->page_shift) & chip->pagemask; -+ if (chip->planenum > 1) { -+ page = ((int)(ofs >> chip->page_shift) * chip->planenum + CONFIG_MTD_BADBLOCK_FLAG_PAGE); -+ page1 = page + mtd->erasesize / mtd->writesize; -+ page &= chip->pagemask; -+ page1 &= chip->pagemask; -+ } else -+ page = ((int)(ofs >> chip->page_shift) + CONFIG_MTD_BADBLOCK_FLAG_PAGE) & chip->pagemask; - - if (getchip) { - chipnr = (int)(ofs >> chip->chip_shift); -@@ -343,7 +489,7 @@ - * This is the default implementation, which can be overridden by - * a hardware specific driver. - */ --static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) -+static int nand_default_block_markbad(struct mtd_info *mtd, loff_mtd_t ofs) - { - struct nand_chip *chip = mtd->priv; - uint8_t buf[2] = { 0, 0 }; -@@ -363,6 +509,7 @@ - */ - nand_get_device(chip, mtd, FL_WRITING); - ofs += mtd->oobsize; -+ ofs += (CONFIG_MTD_BADBLOCK_FLAG_PAGE << chip->page_shift); - chip->ops.len = chip->ops.ooblen = 2; - chip->ops.datbuf = NULL; - chip->ops.oobbuf = buf; -@@ -402,7 +549,7 @@ - * Check, if the block is bad. Either by reading the bad block table or - * calling of the scan function. - */ --static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, -+static int nand_block_checkbad(struct mtd_info *mtd, loff_mtd_t ofs, int getchip, - int allowbbt) - { - struct nand_chip *chip = mtd->priv; -@@ -554,7 +701,10 @@ - - /* Emulate NAND_CMD_READOOB */ - if (command == NAND_CMD_READOOB) { -- column += mtd->writesize; -+ if (chip->planenum > 1) -+ column += (mtd->writesize / chip->planenum); -+ else -+ column += mtd->writesize; - command = NAND_CMD_READ0; - } - -@@ -600,6 +750,8 @@ - case NAND_CMD_RNDIN: - case NAND_CMD_STATUS: - case NAND_CMD_DEPLETE1: -+ case 0x81: /* for two-plane page program */ -+ case 0x11: /* for two-plane page program */ - return; - - /* -@@ -878,7 +1029,8 @@ - return 0; - } - --/** -+#ifndef CONFIG_MTD_HW_RS_ECC -+/* HW&SW Hamming ECC *//** - * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function - * @mtd: mtd info structure - * @chip: nand chip info structure -@@ -922,6 +1074,63 @@ - return 0; - } - -+#else /* CONFIG_MTD_HW_RS_ECC */ -+ -+/** -+ * nand_read_page_hwecc_rs - [REPLACABLE] hardware rs ecc based page read function -+ * @mtd: mtd info structure -+ * @chip: nand chip info structure -+ * @buf: buffer to store read data -+ * -+ * Not for syndrome calculating ecc controllers which need a special oob layout -+ */ -+static int nand_read_page_hwecc_rs(struct mtd_info *mtd, struct nand_chip *chip, -+ uint8_t *buf) -+{ -+ int i, eccsize = chip->ecc.size; -+ int eccbytes = chip->ecc.bytes; -+ int eccsteps = chip->ecc.steps; -+ uint8_t *p = buf; -+ uint8_t *ecc_calc = chip->buffers->ecccalc; -+ uint8_t *ecc_code = chip->buffers->ecccode; -+ uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t page; -+ uint8_t flag = 0; -+ -+ page = (buf[3]<<24) + (buf[2]<<16) + (buf[1]<<8) + buf[0]; -+ -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); -+ for (i = 0; i < chip->ecc.total; i++) { -+ ecc_code[i] = chip->oob_poi[eccpos[i]]; -+ if (ecc_code[i] != 0xff) flag = 1; -+ } -+ -+ eccsteps = chip->ecc.steps; -+ p = buf; -+ -+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -+ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -+ int stat; -+ if (flag) { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -+ if (stat < 0) -+ mtd->ecc_stats.failed++; -+ else -+ mtd->ecc_stats.corrected += stat; -+ } -+ else { -+ chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->read_buf(mtd, p, eccsize); -+ } -+ } -+ return 0; -+} -+ -+#endif /* CONFIG_MTD_HW_RS_ECC */ -+ - /** - * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read - * @mtd: mtd info structure -@@ -984,7 +1193,7 @@ - * @len: size of oob to transfer - */ - static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, -- struct mtd_oob_ops *ops, size_t len) -+ struct mtd_oob_ops *ops, size_mtd_t len) - { - switch(ops->mode) { - -@@ -996,7 +1205,7 @@ - case MTD_OOB_AUTO: { - struct nand_oobfree *free = chip->ecc.layout->oobfree; - uint32_t boffs = 0, roffs = ops->ooboffs; -- size_t bytes = 0; -+ size_mtd_t bytes = 0; - - for(; free->length && len; free++, len -= bytes) { - /* Read request not from offset 0 ? */ -@@ -1006,11 +1215,11 @@ - continue; - } - boffs = free->offset + roffs; -- bytes = min_t(size_t, len, -+ bytes = min_t(size_mtd_t, len, - (free->length - roffs)); - roffs = 0; - } else { -- bytes = min_t(size_t, len, free->length); -+ bytes = min_t(size_mtd_t, len, free->length); - boffs = free->offset; - } - memcpy(oob, chip->oob_poi + boffs, bytes); -@@ -1033,7 +1242,7 @@ - * - * Internal function. Called with chip held. - */ --static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, -+static int nand_do_read_ops(struct mtd_info *mtd, loff_mtd_t from, - struct mtd_oob_ops *ops) - { - int chipnr, page, realpage, col, bytes, aligned; -@@ -1067,10 +1276,18 @@ - if (realpage != chip->pagebuf || oob) { - bufpoi = aligned ? buf : chip->buffers->databuf; - -+ global_page = page; -+#if defined(CONFIG_MTD_HW_RS_ECC) || defined(CONFIG_MTD_NAND_DMA) -+ bufpoi[0] = (uint8_t)page; -+ bufpoi[1] = (uint8_t)(page >> 8); -+ bufpoi[2] = (uint8_t)(page >> 16); -+ bufpoi[3] = (uint8_t)(page >> 24); -+#else - if (likely(sndcmd)) { - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); - sndcmd = 0; - } -+#endif - - /* Now read the page into the buffer */ - if (unlikely(ops->mode == MTD_OOB_RAW)) -@@ -1149,7 +1366,7 @@ - sndcmd = 1; - } - -- ops->retlen = ops->len - (size_t) readlen; -+ ops->retlen = ops->len - (size_mtd_t) readlen; - if (oob) - ops->oobretlen = ops->ooblen - oobreadlen; - -@@ -1172,8 +1389,8 @@ - * - * Get hold of the chip and call nand_do_read - */ --static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, uint8_t *buf) -+static int nand_read(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -+ size_mtd_t *retlen, uint8_t *buf) - { - struct nand_chip *chip = mtd->priv; - int ret; -@@ -1346,7 +1563,7 @@ - * - * NAND read out-of-band data from the spare area - */ --static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, -+static int nand_do_read_oob(struct mtd_info *mtd, loff_mtd_t from, - struct mtd_oob_ops *ops) - { - int page, realpage, chipnr, sndcmd = 1; -@@ -1439,7 +1656,7 @@ - * - * NAND read data and/or out-of-band data - */ --static int nand_read_oob(struct mtd_info *mtd, loff_t from, -+static int nand_read_oob(struct mtd_info *mtd, loff_mtd_t from, - struct mtd_oob_ops *ops) - { - struct nand_chip *chip = mtd->priv; -@@ -1602,12 +1819,17 @@ - { - int status; - -- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); -- -- if (unlikely(raw)) -- chip->ecc.write_page_raw(mtd, chip, buf); -- else -+ global_page = page; -+ if (chip->planenum > 1) - chip->ecc.write_page(mtd, chip, buf); -+ else { -+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); -+ -+ if (unlikely(raw)) -+ chip->ecc.write_page_raw(mtd, chip, buf); -+ else -+ chip->ecc.write_page(mtd, chip, buf); -+ } - - /* - * Cached progamming disabled for now, Not sure if its worth the -@@ -1617,7 +1839,15 @@ - - if (!cached || !(chip->options & NAND_CACHEPRG)) { - -- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+/* -+* __nand_cmd(CMD_PAGEPROG) and __nand_sync() have been done by DMA for jz4750 and -+* later chip, status should still be read by "status = chip->waitfunc(mtd, chip)" -+*/ -+#if defined(CONFIG_SOC_JZ4730) || defined(CONFIG_SOC_JZ4740) || \ -+ (!defined(CONFIG_SOC_JZ4730) && !defined(CONFIG_SOC_JZ4740) \ -+ && !defined(CONFIG_MTD_NAND_DMA)) -+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -+#endif - status = chip->waitfunc(mtd, chip); - /* - * See if operation failed and additional status checks are -@@ -1653,7 +1883,7 @@ - static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, - struct mtd_oob_ops *ops) - { -- size_t len = ops->ooblen; -+ size_mtd_t len = ops->ooblen; - - switch(ops->mode) { - -@@ -1665,7 +1895,7 @@ - case MTD_OOB_AUTO: { - struct nand_oobfree *free = chip->ecc.layout->oobfree; - uint32_t boffs = 0, woffs = ops->ooboffs; -- size_t bytes = 0; -+ size_mtd_t bytes = 0; - - for(; free->length && len; free++, len -= bytes) { - /* Write request not from offset 0 ? */ -@@ -1675,11 +1905,11 @@ - continue; - } - boffs = free->offset + woffs; -- bytes = min_t(size_t, len, -+ bytes = min_t(size_mtd_t, len, - (free->length - woffs)); - woffs = 0; - } else { -- bytes = min_t(size_t, len, free->length); -+ bytes = min_t(size_mtd_t, len, free->length); - boffs = free->offset; - } - memcpy(chip->oob_poi + boffs, oob, bytes); -@@ -1703,7 +1933,7 @@ - * - * NAND write with ECC - */ --static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, -+static int nand_do_write_ops(struct mtd_info *mtd, loff_mtd_t to, - struct mtd_oob_ops *ops) - { - int chipnr, realpage, page, blockmask, column; -@@ -1806,8 +2036,8 @@ - * - * NAND write with ECC - */ --static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, -- size_t *retlen, const uint8_t *buf) -+static int nand_write(struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, -+ size_mtd_t *retlen, const uint8_t *buf) - { - struct nand_chip *chip = mtd->priv; - int ret; -@@ -1841,7 +2071,7 @@ - * - * NAND write out-of-band - */ --static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, -+static int nand_do_write_oob(struct mtd_info *mtd, loff_mtd_t to, - struct mtd_oob_ops *ops) - { - int chipnr, page, status, len; -@@ -1919,7 +2149,7 @@ - * @to: offset to write to - * @ops: oob operation description structure - */ --static int nand_write_oob(struct mtd_info *mtd, loff_t to, -+static int nand_write_oob(struct mtd_info *mtd, loff_mtd_t to, - struct mtd_oob_ops *ops) - { - struct nand_chip *chip = mtd->priv; -@@ -2083,7 +2313,7 @@ - /* - * heck if we have a bad block, we do not erase bad blocks ! - */ -- if (nand_block_checkbad(mtd, ((loff_t) page) << -+ if (nand_block_checkbad(mtd, ((loff_mtd_t) page) << - chip->page_shift, 0, allowbbt)) { - printk(KERN_WARNING "nand_erase: attempt to erase a " - "bad block at page 0x%08x\n", page); -@@ -2205,7 +2435,7 @@ - * @mtd: MTD device structure - * @offs: offset relative to mtd start - */ --static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) -+static int nand_block_isbad(struct mtd_info *mtd, loff_mtd_t offs) - { - /* Check for invalid offset */ - if (offs > mtd->size) -@@ -2219,7 +2449,7 @@ - * @mtd: MTD device structure - * @ofs: offset relative to mtd start - */ --static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) -+static int nand_block_markbad(struct mtd_info *mtd, loff_mtd_t ofs) - { - struct nand_chip *chip = mtd->priv; - int ret; -@@ -2379,7 +2609,21 @@ - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; -+ /* The 5th id byte */ -+#if defined(CONFIG_MTD_NAND_MULTI_PLANE) -+ extid = chip->read_byte(mtd); -+ chip->realplanenum = 1 << ((extid & 0x0c) >> 2); -+#else -+ chip->realplanenum = 1; -+#endif - -+ if (chip->realplanenum > 1) { /* use muti planes mode */ -+ chip->planenum = 2; -+ mtd->writesize *= 2; /* two pages as one page */ -+ mtd->oobsize *= 2; -+ mtd->erasesize *= 2; /* two blocks as one block */ -+ } else -+ chip->planenum = 1; - } else { - /* - * Old devices have chip data hardcoded in the device id table -@@ -2417,7 +2661,7 @@ - - chip->bbt_erase_shift = chip->phys_erase_shift = - ffs(mtd->erasesize) - 1; -- chip->chip_shift = ffs(chip->chipsize) - 1; -+ chip->chip_shift = ffs_ll(chip->chipsize) - 1; - - /* Set the bad block position */ - chip->badblockpos = mtd->writesize > 512 ? -@@ -2449,8 +2693,8 @@ - chip->cmdfunc = nand_command_lp; - - printk(KERN_INFO "NAND device: Manufacturer ID:" -- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, -- nand_manuf_ids[maf_idx].name, type->name); -+ " 0x%02x, Chip ID: 0x%02x (%s %s) planenum:%d\n", *maf_id, dev_id, -+ nand_manuf_ids[maf_idx].name, type->name, chip->realplanenum); - - return type; - } -@@ -2517,7 +2761,7 @@ - */ - int nand_scan_tail(struct mtd_info *mtd) - { -- int i; -+ int i, res; - struct nand_chip *chip = mtd->priv; - - if (!(chip->options & NAND_OWN_BUFFERS)) -@@ -2542,6 +2786,16 @@ - case 64: - chip->ecc.layout = &nand_oob_64; - break; -+ case 128: -+ if (chip->planenum > 1) -+ chip->ecc.layout = &nand_oob_64; -+ else -+ chip->ecc.layout = &nand_oob_128; -+ break; -+ case 256: -+ if (chip->planenum > 1) -+ chip->ecc.layout = &nand_oob_128; -+ break; - default: - printk(KERN_WARNING "No oob scheme defined for " - "oobsize %d\n", mtd->oobsize); -@@ -2565,7 +2819,11 @@ - case NAND_ECC_HW: - /* Use standard hwecc read page function ? */ - if (!chip->ecc.read_page) -+#ifndef CONFIG_MTD_HW_RS_ECC - chip->ecc.read_page = nand_read_page_hwecc; -+#else -+ chip->ecc.read_page = nand_read_page_hwecc_rs; -+#endif - if (!chip->ecc.write_page) - chip->ecc.write_page = nand_write_page_hwecc; - if (!chip->ecc.read_oob) -@@ -2575,11 +2833,7 @@ - - case NAND_ECC_HW_SYNDROME: - if ((!chip->ecc.calculate || !chip->ecc.correct || -- !chip->ecc.hwctl) && -- (!chip->ecc.read_page || -- chip->ecc.read_page == nand_read_page_hwecc || -- !chip->ecc.write_page || -- chip->ecc.write_page == nand_write_page_hwecc)) { -+ !chip->ecc.hwctl)) { - printk(KERN_WARNING "No ECC functions supplied, " - "Hardware ECC not possible\n"); - BUG(); -@@ -2600,7 +2854,7 @@ - "%d byte page size, fallback to SW ECC\n", - chip->ecc.size, mtd->writesize); - chip->ecc.mode = NAND_ECC_SOFT; -- -+ - case NAND_ECC_SOFT: - chip->ecc.calculate = nand_calculate_ecc; - chip->ecc.correct = nand_correct_data; -@@ -2703,8 +2957,58 @@ - if (chip->options & NAND_SKIP_BBTSCAN) - return 0; - -- /* Build bad block table */ -- return chip->scan_bbt(mtd); -+ /* Create jz_mtd1 for one plane operation if the NAND support multiple -+ planes operation, because some partitions will only use one plane. */ -+ if ((chip->planenum == 2) && !all_use_planes) { -+ int i, len, numblocks; -+ struct nand_chip *this = (struct nand_chip *) (&jz_mtd1[1]); -+ -+ memcpy(jz_mtd1, mtd, sizeof(*mtd)); -+ jz_mtd1->priv = this; -+ memcpy(this, chip, sizeof(*chip)); -+ -+ this->planenum = 1; -+ jz_mtd1->writesize >>= 1; -+ jz_mtd1->oobsize >>= 1; -+ jz_mtd1->erasesize >>= 1; -+ this->page_shift = chip->page_shift - 1; -+ this->pagemask = (this->chipsize >> this->page_shift) - 1; -+ this->bbt_erase_shift = this->phys_erase_shift = -+ chip->phys_erase_shift - 1; -+ this->ecc.steps >>= 1; -+ this->ecc.total = this->ecc.steps * this->ecc.bytes; -+ this->subpagesize = jz_mtd1->writesize; -+ -+ this->erase_cmd = single_erase_cmd; -+#if defined(CONFIG_MTD_HW_RS_ECC) -+ this->ecc.read_page = nand_read_page_hwecc_rs; -+ this->ecc.write_page = nand_write_page_hwecc; -+#endif -+ this->ecc.read_oob = nand_read_oob_std; -+ this->ecc.write_oob = nand_write_oob_std; -+ this->write_buf = nand_write_buf; -+ this->read_buf = nand_read_buf; -+ -+ /* Firstly, build bad block table as one plane */ -+ res = this->scan_bbt(jz_mtd1); -+ -+ /* Secondly, build bad block table as 2 plane based on bbt of jz_mtd1 */ -+ numblocks = chip->chipsize >> (chip->bbt_erase_shift - 1); /* = (real numblocks * 2) */ -+ len = mtd->size >> (chip->bbt_erase_shift + 2); -+ chip->bbt = kzalloc(len, GFP_KERNEL); -+ -+#define isbad_2plane(block) (((this->bbt[(block) >> 3] >> ((block) & 0x06)) \ -+ | (this->bbt[((block)+2) >> 3] >> (((block)+2) & 0x06))) & 0x03) -+ -+ for (i = 0; i < numblocks; i += 2) { -+ if (isbad_2plane(2*i)) -+ chip->bbt[i >> 3] |= 0x03 << (i & 0x6); -+ } -+ } else { -+ res = chip->scan_bbt(mtd); -+ } -+ -+ return res; - } - - /* module_text_address() isn't exported, and it's mostly a pointless -diff -ru linux-2.6/drivers/mtd/nand/nand_bbt.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/nand_bbt.c ---- linux-2.6/drivers/mtd/nand/nand_bbt.c 2009-08-17 23:58:01.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/nand_bbt.c 2009-08-12 10:39:09.000000000 +0200 -@@ -145,15 +145,15 @@ - { - int res, i, j, act = 0; - struct nand_chip *this = mtd->priv; -- size_t retlen, len, totlen; -- loff_t from; -+ size_mtd_t retlen, len, totlen; -+ loff_mtd_t from; - uint8_t msk = (uint8_t) ((1 << bits) - 1); - - totlen = (num * bits) >> 3; -- from = ((loff_t) page) << this->page_shift; -+ from = ((loff_mtd_t) page) << this->page_shift; - - while (totlen) { -- len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); -+ len = min(totlen, (size_mtd_t) (1 << this->bbt_erase_shift)); - res = mtd->read(mtd, from, len, &retlen, buf); - if (res < 0) { - if (retlen != len) { -@@ -233,8 +233,8 @@ - /* - * Scan read raw data from flash - */ --static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, -- size_t len) -+static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_mtd_t offs, -+ size_mtd_t len) - { - struct mtd_oob_ops ops; - -@@ -251,7 +251,7 @@ - /* - * Scan write data with oob to flash - */ --static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, -+static int scan_write_bbt(struct mtd_info *mtd, loff_mtd_t offs, size_mtd_t len, - uint8_t *buf, uint8_t *oob) - { - struct mtd_oob_ops ops; -@@ -306,7 +306,7 @@ - * Scan a given block full - */ - static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, -- loff_t offs, uint8_t *buf, size_t readlen, -+ loff_mtd_t offs, uint8_t *buf, size_mtd_t readlen, - int scanlen, int len) - { - int ret, j; -@@ -326,7 +326,7 @@ - * Scan a given block partially - */ - static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, -- loff_t offs, uint8_t *buf, int len) -+ loff_mtd_t offs, uint8_t *buf, int len) - { - struct mtd_oob_ops ops; - int j, ret; -@@ -372,8 +372,8 @@ - struct nand_chip *this = mtd->priv; - int i, numblocks, len, scanlen; - int startblock; -- loff_t from; -- size_t readlen; -+ loff_mtd_t from; -+ size_mtd_t readlen; - - printk(KERN_INFO "Scanning device for bad blocks\n"); - -@@ -401,7 +401,7 @@ - * below as it makes shifting and masking less painful */ - numblocks = mtd->size >> (this->bbt_erase_shift - 1); - startblock = 0; -- from = 0; -+ from = (CONFIG_MTD_BADBLOCK_FLAG_PAGE << this->page_shift); //from = 0; - } else { - if (chip >= this->numchips) { - printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", -@@ -411,7 +411,7 @@ - numblocks = this->chipsize >> (this->bbt_erase_shift - 1); - startblock = chip * numblocks; - numblocks += startblock; -- from = startblock << (this->bbt_erase_shift - 1); -+ from = (startblock << (this->bbt_erase_shift - 1)) + (CONFIG_MTD_BADBLOCK_FLAG_PAGE << this->page_shift); //from = startblock << (this->bbt_erase_shift - 1); - } - - for (i = startblock; i < numblocks;) { -@@ -428,8 +428,8 @@ - - if (ret) { - this->bbt[i >> 3] |= 0x03 << (i & 0x6); -- printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", -- i >> 1, (unsigned int)from); -+ printk(KERN_WARNING "Bad eraseblock %d at 0x%09llx\n", -+ i >> 1, (unsigned long long)from); - mtd->ecc_stats.badblocks++; - } - -@@ -495,7 +495,7 @@ - for (block = 0; block < td->maxblocks; block++) { - - int actblock = startblock + dir * block; -- loff_t offs = actblock << this->bbt_erase_shift; -+ loff_mtd_t offs = actblock << this->bbt_erase_shift; - - /* Read first page */ - scan_read_raw(mtd, buf, offs, mtd->writesize); -@@ -565,8 +565,8 @@ - int nrchips, bbtoffs, pageoffs, ooboffs; - uint8_t msk[4]; - uint8_t rcode = td->reserved_block_code; -- size_t retlen, len = 0; -- loff_t to; -+ size_mtd_t retlen, len = 0; -+ loff_mtd_t to; - struct mtd_oob_ops ops; - - ops.ooblen = mtd->oobsize; -@@ -653,12 +653,12 @@ - - bbtoffs = chip * (numblocks >> 2); - -- to = ((loff_t) page) << this->page_shift; -+ to = ((loff_mtd_t) page) << this->page_shift; - - /* Must we save the block contents ? */ - if (td->options & NAND_BBT_SAVECONTENT) { - /* Make it block aligned */ -- to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); -+ to &= ~((loff_mtd_t) ((1 << this->bbt_erase_shift) - 1)); - len = 1 << this->bbt_erase_shift; - res = mtd->read(mtd, to, len, &retlen, buf); - if (res < 0) { -@@ -683,12 +683,12 @@ - pageoffs = page - (int)(to >> this->page_shift); - offs = pageoffs << this->page_shift; - /* Preset the bbt area with 0xff */ -- memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); -+ memset(&buf[offs], 0xff, (size_mtd_t) (numblocks >> sft)); - ooboffs = len + (pageoffs * mtd->oobsize); - - } else { - /* Calc length */ -- len = (size_t) (numblocks >> sft); -+ len = (size_mtd_t) (numblocks >> sft); - /* Make it page aligned ! */ - len = (len + (mtd->writesize - 1)) & - ~(mtd->writesize - 1); -@@ -1015,7 +1015,7 @@ - * - * The function updates the bad block table(s) - */ --int nand_update_bbt(struct mtd_info *mtd, loff_t offs) -+int nand_update_bbt(struct mtd_info *mtd, loff_mtd_t offs) - { - struct nand_chip *this = mtd->priv; - int len, res = 0, writeops = 0; -@@ -1191,7 +1191,7 @@ - * @allowbbt: allow access to bad block table region - * - */ --int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) -+int nand_isbad_bbt(struct mtd_info *mtd, loff_mtd_t offs, int allowbbt) - { - struct nand_chip *this = mtd->priv; - int block; -diff -ru linux-2.6/drivers/mtd/nand/nand_ids.c /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/nand_ids.c ---- linux-2.6/drivers/mtd/nand/nand_ids.c 2009-08-17 23:57:37.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/drivers/mtd/nand/nand_ids.c 2009-08-12 10:39:09.000000000 +0200 -@@ -109,6 +109,10 @@ - {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, - {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, - -+ /* 32 Gigabit */ -+ {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, -+ {"NAND 4GiB 3,3V 8-bit", 0xD5, 0, 4096, 0, LP_OPTIONS}, -+ - /* - * Renesas AND 1 Gigabit. Those chips do not support extended id and - * have a strange page/block layout ! The chosen minimum erasesize is diff -ru linux-2.6/drivers/net/Kconfig /plain/src/qi/linux-2.6.27.git.svn/drivers/net/Kconfig --- linux-2.6/drivers/net/Kconfig 2009-08-17 23:58:01.000000000 +0200 +++ /plain/src/qi/linux-2.6.27.git.svn/drivers/net/Kconfig 2009-08-12 10:39:09.000000000 +0200 @@ -5205,250 +3662,6 @@ diff -ru linux-2.6/include/linux/mmc/host.h /plain/src/qi/linux-2.6.27.git.svn/i static inline void *mmc_priv(struct mmc_host *host) { return (void *)host->private; -diff -ru linux-2.6/include/linux/mtd/mtd.h /plain/src/qi/linux-2.6.27.git.svn/include/linux/mtd/mtd.h ---- linux-2.6/include/linux/mtd/mtd.h 2009-08-17 23:58:03.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/include/linux/mtd/mtd.h 2009-08-12 10:39:09.000000000 +0200 -@@ -30,9 +30,9 @@ - specific to any particular block. */ - struct erase_info { - struct mtd_info *mtd; -- u_int32_t addr; -- u_int32_t len; -- u_int32_t fail_addr; -+ u_int64_t addr; -+ u_int64_t len; -+ u_int64_t fail_addr; - u_long time; - u_long retries; - u_int dev; -@@ -44,7 +44,7 @@ - }; - - struct mtd_erase_region_info { -- u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ -+ u_int64_t offset; /* At which this region starts, from the beginning of the MTD */ - u_int32_t erasesize; /* For this region */ - u_int32_t numblocks; /* Number of blocks of erasesize in this region */ - unsigned long *lockmap; /* If keeping bitmap of locks */ -@@ -87,10 +87,10 @@ - */ - struct mtd_oob_ops { - mtd_oob_mode_t mode; -- size_t len; -- size_t retlen; -- size_t ooblen; -- size_t oobretlen; -+ size_mtd_t len; -+ size_mtd_t retlen; -+ size_mtd_t ooblen; -+ size_mtd_t oobretlen; - uint32_t ooboffs; - uint8_t *datbuf; - uint8_t *oobbuf; -@@ -99,7 +99,7 @@ - struct mtd_info { - u_char type; - u_int32_t flags; -- u_int32_t size; // Total size of the MTD -+ u_int64_t size; // Total size of the MTD - - /* "Major" erase size for the device. Naïve users may take this - * to be the only erase size available, or may use the more detailed -@@ -142,15 +142,15 @@ - - /* This stuff for eXecute-In-Place */ - /* phys is optional and may be set to NULL */ -- int (*point) (struct mtd_info *mtd, loff_t from, size_t len, -- size_t *retlen, void **virt, resource_size_t *phys); -+ int (*point) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -+ size_mtd_t *retlen, void **virt, resource_size_t *phys); - - /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ -- void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); -+ void (*unpoint) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len); - - -- int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -- int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -+ int (*read) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -+ int (*write) (struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, size_mtd_t *retlen, const u_char *buf); - - /* In blackbox flight recorder like scenarios we want to make successful - writes in interrupt context. panic_write() is only intended to be -@@ -159,11 +159,11 @@ - longer, this function can break locks and delay to ensure the write - succeeds (but not sleep). */ - -- int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -+ int (*panic_write) (struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, size_mtd_t *retlen, const u_char *buf); - -- int (*read_oob) (struct mtd_info *mtd, loff_t from, -+ int (*read_oob) (struct mtd_info *mtd, loff_mtd_t from, - struct mtd_oob_ops *ops); -- int (*write_oob) (struct mtd_info *mtd, loff_t to, -+ int (*write_oob) (struct mtd_info *mtd, loff_mtd_t to, - struct mtd_oob_ops *ops); - - /* -@@ -171,33 +171,33 @@ - * flash devices. The user data is one time programmable but the - * factory data is read only. - */ -- int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -- int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -- int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -- int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -- int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -- int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); -+ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_mtd_t len); -+ int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -+ int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_mtd_t len); -+ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -+ int (*write_user_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -+ int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len); - - /* kvec-based read/write methods. - NB: The 'count' parameter is the number of _vectors_, each of - which contains an (ofs, len) tuple. - */ -- int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); -+ int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_mtd_t to, size_mtd_t *retlen); - - /* Sync */ - void (*sync) (struct mtd_info *mtd); - - /* Chip-supported device locking */ -- int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len); -- int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len); -+ int (*lock) (struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len); -+ int (*unlock) (struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len); - - /* Power Management functions */ - int (*suspend) (struct mtd_info *mtd); - void (*resume) (struct mtd_info *mtd); - - /* Bad block management functions */ -- int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); -- int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); -+ int (*block_isbad) (struct mtd_info *mtd, loff_mtd_t ofs); -+ int (*block_markbad) (struct mtd_info *mtd, loff_mtd_t ofs); - - struct notifier_block reboot_notifier; /* default mode before reboot */ - -@@ -242,10 +242,10 @@ - extern int unregister_mtd_user (struct mtd_notifier *old); - - int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, -- unsigned long count, loff_t to, size_t *retlen); -+ unsigned long count, loff_mtd_t to, size_mtd_t *retlen); - - int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, -- unsigned long count, loff_t from, size_t *retlen); -+ unsigned long count, loff_mtd_t from, size_mtd_t *retlen); - - #ifdef CONFIG_MTD_PARTITIONS - void mtd_erase_callback(struct erase_info *instr); -diff -ru linux-2.6/include/linux/mtd/nand.h /plain/src/qi/linux-2.6.27.git.svn/include/linux/mtd/nand.h ---- linux-2.6/include/linux/mtd/nand.h 2009-08-17 23:58:03.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/include/linux/mtd/nand.h 2009-08-12 10:39:09.000000000 +0200 -@@ -37,14 +37,14 @@ - extern void nand_wait_ready(struct mtd_info *mtd); - - /* The maximum number of NAND chips in an array */ --#define NAND_MAX_CHIPS 8 -+#define NAND_MAX_CHIPS 4 - - /* This constant declares the max. oobsize / page, which - * is supported now. If you add a chip with bigger oobsize/page - * adjust this accordingly. - */ --#define NAND_MAX_OOBSIZE 64 --#define NAND_MAX_PAGESIZE 2048 -+#define NAND_MAX_OOBSIZE 256 -+#define NAND_MAX_PAGESIZE 8192 - - /* - * Constants for hardware specific CLE/ALE/NCE function -@@ -54,6 +54,10 @@ - */ - /* Select the chip by setting nCE to low */ - #define NAND_NCE 0x01 -+#define NAND_NCE1 0x08 -+#define NAND_NCE2 0x10 -+#define NAND_NCE3 0x20 -+#define NAND_NCE4 0x40 - /* Select the command latch by setting CLE to high */ - #define NAND_CLE 0x02 - /* Select the address latch by setting ALE to high */ -@@ -377,8 +381,8 @@ - void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); - int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); - void (*select_chip)(struct mtd_info *mtd, int chip); -- int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); -- int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); -+ int (*block_bad)(struct mtd_info *mtd, loff_mtd_t ofs, int getchip); -+ int (*block_markbad)(struct mtd_info *mtd, loff_mtd_t ofs); - void (*cmd_ctrl)(struct mtd_info *mtd, int dat, - unsigned int ctrl); - int (*dev_ready)(struct mtd_info *mtd); -@@ -398,12 +402,14 @@ - int bbt_erase_shift; - int chip_shift; - int numchips; -- unsigned long chipsize; -+ u64 chipsize; - int pagemask; - int pagebuf; - int subpagesize; - uint8_t cellinfo; - int badblockpos; -+ int realplanenum; /* number of planes the NAND has */ -+ int planenum; /* number of planes operating synchronously */ - - nand_state_t state; - -@@ -455,7 +461,7 @@ - char *name; - int id; - unsigned long pagesize; -- unsigned long chipsize; -+ u64 chipsize; - unsigned long erasesize; - unsigned long options; - }; -@@ -543,13 +549,13 @@ - #define NAND_BBT_SCAN_MAXBLOCKS 4 - - extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); --extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs); -+extern int nand_update_bbt(struct mtd_info *mtd, loff_mtd_t offs); - extern int nand_default_bbt(struct mtd_info *mtd); --extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); -+extern int nand_isbad_bbt(struct mtd_info *mtd, loff_mtd_t offs, int allowbbt); - extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, - int allowbbt); --extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, -- size_t * retlen, uint8_t * buf); -+extern int nand_do_read(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -+ size_mtd_t * retlen, uint8_t * buf); - - /* - * Constants for oob configuration -diff -ru linux-2.6/include/linux/mtd/partitions.h /plain/src/qi/linux-2.6.27.git.svn/include/linux/mtd/partitions.h ---- linux-2.6/include/linux/mtd/partitions.h 2009-08-17 23:58:03.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/include/linux/mtd/partitions.h 2009-08-12 10:39:09.000000000 +0200 -@@ -36,8 +36,9 @@ - - struct mtd_partition { - char *name; /* identifier string */ -- u_int32_t size; /* partition size */ -- u_int32_t offset; /* offset within the master MTD space */ -+ u_int64_t size; /* partition size */ -+ u_int64_t offset; /* offset within the master MTD space */ -+ char use_planes; /* flag to specify whether multiple planes of NAND is used in the partition */ - u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ - struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ - struct mtd_info **mtdp; /* pointer to store the MTD object */ diff -ru linux-2.6/include/linux/power_supply.h /plain/src/qi/linux-2.6.27.git.svn/include/linux/power_supply.h --- linux-2.6/include/linux/power_supply.h 2009-08-17 23:58:03.000000000 +0200 +++ /plain/src/qi/linux-2.6.27.git.svn/include/linux/power_supply.h 2009-08-12 10:39:09.000000000 +0200 @@ -5488,106 +3701,6 @@ diff -ru linux-2.6/include/linux/suspend.h /plain/src/qi/linux-2.6.27.git.svn/in /* kernel/power/main.c */ extern int register_pm_notifier(struct notifier_block *nb); extern int unregister_pm_notifier(struct notifier_block *nb); -diff -ru linux-2.6/include/mtd/mtd-abi.h /plain/src/qi/linux-2.6.27.git.svn/include/mtd/mtd-abi.h ---- linux-2.6/include/mtd/mtd-abi.h 2009-08-17 23:58:03.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/include/mtd/mtd-abi.h 2009-08-12 10:39:09.000000000 +0200 -@@ -1,13 +1,23 @@ - /* -+ * $Id: mtd-abi.h,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $ -+ * - * Portions of MTD ABI definition which are shared by kernel and user space - */ - - #ifndef __MTD_ABI_H__ - #define __MTD_ABI_H__ - -+#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into -+ separate files was to avoid #ifdef __KERNEL__ */ -+#define __user -+#endif -+ -+typedef unsigned long long size_mtd_t; -+typedef unsigned long long loff_mtd_t; -+ - struct erase_info_user { -- uint32_t start; -- uint32_t length; -+ uint64_t start; -+ uint64_t length; - }; - - struct mtd_oob_buf { -@@ -16,6 +26,14 @@ - unsigned char __user *ptr; - }; - -+struct mtd_page_buf { -+ uint32_t start; //page start address -+ uint32_t ooblength; -+ uint32_t datlength; -+ unsigned char __user *oobptr; -+ unsigned char __user *datptr; -+}; -+ - #define MTD_ABSENT 0 - #define MTD_RAM 1 - #define MTD_ROM 2 -@@ -50,7 +68,7 @@ - struct mtd_info_user { - uint8_t type; - uint32_t flags; -- uint32_t size; // Total size of the MTD -+ uint64_t size; // Total size of the MTD - uint32_t erasesize; - uint32_t writesize; - uint32_t oobsize; // Amount of OOB data per block (e.g. 16) -@@ -61,7 +79,7 @@ - }; - - struct region_info_user { -- uint32_t offset; /* At which this region starts, -+ uint64_t offset; /* At which this region starts, - * from the beginning of the MTD */ - uint32_t erasesize; /* For this region */ - uint32_t numblocks; /* Number of blocks in this region */ -@@ -84,8 +102,8 @@ - #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) - #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) - #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) --#define MEMGETBADBLOCK _IOW('M', 11, loff_t) --#define MEMSETBADBLOCK _IOW('M', 12, loff_t) -+#define MEMGETBADBLOCK _IOW('M', 11, loff_mtd_t) -+#define MEMSETBADBLOCK _IOW('M', 12, loff_mtd_t) - #define OTPSELECT _IOR('M', 13, int) - #define OTPGETREGIONCOUNT _IOW('M', 14, int) - #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) -@@ -93,6 +111,7 @@ - #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) - #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) - #define MTDFILEMODE _IO('M', 19) -+#define MEMWRITEPAGE _IOWR('M', 20, struct mtd_page_buf) - #define MTDREFRESH _IO('M', 23) - - /* -@@ -102,7 +121,8 @@ - uint32_t useecc; - uint32_t eccbytes; - uint32_t oobfree[8][2]; -- uint32_t eccpos[32]; -+ uint32_t eccpos[104]; /* more fields(13*8) are required for -+ * 8-bit BCH ECC and 4KB pagesize nand, by Regen */ - }; - - struct nand_oobfree { -@@ -117,7 +137,7 @@ - */ - struct nand_ecclayout { - uint32_t eccbytes; -- uint32_t eccpos[64]; -+ uint32_t eccpos[128]; - uint32_t oobavail; - struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; - }; diff -ru linux-2.6/include/sound/pcm.h /plain/src/qi/linux-2.6.27.git.svn/include/sound/pcm.h --- linux-2.6/include/sound/pcm.h 2009-08-17 23:58:03.000000000 +0200 +++ /plain/src/qi/linux-2.6.27.git.svn/include/sound/pcm.h 2009-08-12 10:39:09.000000000 +0200