diff options
author | William Juul <william.juul@datarespons.no> | 2007-10-31 13:53:06 +0100 |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2008-08-12 11:31:15 -0500 |
commit | cfa460adfdefcc30d104e1a9ee44994ee349bb7b (patch) | |
tree | 59400f96629aec9c968b0e3251628302824f5d35 /drivers/mtd/nand/diskonchip.c | |
parent | cd82919e6c8a73b363a26f34b734923844e52d1c (diff) | |
download | u-boot-imx-cfa460adfdefcc30d104e1a9ee44994ee349bb7b.zip u-boot-imx-cfa460adfdefcc30d104e1a9ee44994ee349bb7b.tar.gz u-boot-imx-cfa460adfdefcc30d104e1a9ee44994ee349bb7b.tar.bz2 |
Update MTD to that of Linux 2.6.22.1
A lot changed in the Linux MTD code, since it was last ported from
Linux to U-Boot. This patch takes U-Boot NAND support to the level
of Linux 2.6.22.1 and will enable support for very large NAND devices
(4KB pages) and ease the compatibility between U-Boot and Linux
filesystems.
This patch is tested on two custom boards with PPC and ARM
processors running YAFFS in U-Boot and Linux using gcc-4.1.2
cross compilers.
MAKEALL ppc/arm has some issues:
* DOC/OneNand/nand_spl is not building (I have not tried porting
these parts, and since I do not have any HW and I am not familiar
with this code/HW I think its best left to someone else.)
Except for the issues mentioned above, I have ported all drivers
necessary to run MAKEALL ppc/arm without errors and warnings. Many
drivers were trivial to port, but some were not so trivial. The
following drivers must be examined carefully and maybe rewritten to
some degree:
cpu/ppc4xx/ndfc.c
cpu/arm926ejs/davinci/nand.c
board/delta/nand.c
board/zylonite/nand.c
Signed-off-by: William Juul <william.juul@tandberg.com>
Signed-off-by: Stig Olsen <stig.olsen@tandberg.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'drivers/mtd/nand/diskonchip.c')
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 554 |
1 files changed, 279 insertions, 275 deletions
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index fdd85c1..a03f982 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -16,7 +16,7 @@ * * Interface to generic NAND code for M-Systems DiskOnChip devices * - * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $ + * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $ */ #include <common.h> @@ -39,13 +39,13 @@ #include <linux/mtd/inftl.h> /* Where to look for the devices? */ -#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS -#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0 +#ifndef CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS +#define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0 #endif static unsigned long __initdata doc_locations[] = { #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) -#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH +#ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, @@ -65,7 +65,7 @@ static unsigned long __initdata doc_locations[] = { 0xff000000, #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) 0xff000000, -##else +#else #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif 0xffffffff }; @@ -77,7 +77,7 @@ struct doc_priv { unsigned long physadr; u_char ChipID; u_char CDSNControl; - int chips_per_floor; /* The number of chips detected on each floor */ + int chips_per_floor; /* The number of chips detected on each floor */ int curfloor; int curchip; int mh0_page; @@ -85,14 +85,10 @@ struct doc_priv { struct mtd_info *nextdoc; }; -/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL - MediaHeader. The spec says to just keep going, I think, but that's just - silly. */ -#define MAX_MEDIAHEADER_SCAN 8 - /* This is the syndrome computed by the HW ecc generator upon reading an empty page, one with all 0xff for data and stored ecc code. */ static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; + /* This is the ecc value computed by the HW ecc generator upon writing an empty page, one with all 0xff for data. */ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; @@ -103,35 +99,36 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) -static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int bitmask); static void doc200x_select_chip(struct mtd_info *mtd, int chip); -static int debug=0; +static int debug = 0; module_param(debug, int, 0); -static int try_dword=1; +static int try_dword = 1; module_param(try_dword, int, 0); -static int no_ecc_failures=0; +static int no_ecc_failures = 0; module_param(no_ecc_failures, int, 0); -#ifdef CONFIG_MTD_PARTITIONS -static int no_autopart=0; +static int no_autopart = 0; module_param(no_autopart, int, 0); -#endif -#ifdef MTD_NAND_DISKONCHIP_BBTWRITE -static int inftl_bbt_write=1; +static int show_firmware_partition = 0; +module_param(show_firmware_partition, int, 0); + +#ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE +static int inftl_bbt_write = 1; #else -static int inftl_bbt_write=0; +static int inftl_bbt_write = 0; #endif module_param(inftl_bbt_write, int, 0); -static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; +static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS; module_param(doc_config_location, ulong, 0); MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); - /* Sector size for HW ECC */ #define SECTOR_SIZE 512 /* The sector bytes are packed into NB_DATA 10 bit words */ @@ -155,7 +152,7 @@ static struct rs_control *rs_decoder; * some comments, improved a minor bit and converted it to make use * of the generic Reed-Solomon libary. tglx */ -static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) +static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) { int i, j, nerr, errpos[8]; uint8_t parity; @@ -176,11 +173,11 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] * where x = alpha^(FCR + i) */ - for(j = 1; j < NROOTS; j++) { - if(ds[j] == 0) + for (j = 1; j < NROOTS; j++) { + if (ds[j] == 0) continue; tmp = rs->index_of[ds[j]]; - for(i = 0; i < NROOTS; i++) + for (i = 0; i < NROOTS; i++) s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; } @@ -201,7 +198,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) * but they are given by the design of the de/encoder circuit * in the DoC ASIC's. */ - for(i = 0;i < nerr; i++) { + for (i = 0; i < nerr; i++) { int index, bitpos, pos = 1015 - errpos[i]; uint8_t val; if (pos >= NB_DATA && pos < 1019) @@ -213,8 +210,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) can be modified since pos is even */ index = (pos >> 3) ^ 1; bitpos = pos & 7; - if ((index >= 0 && index < SECTOR_SIZE) || - index == (SECTOR_SIZE + 1)) { + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { val = (uint8_t) (errval[i] >> (2 + bitpos)); parity ^= val; if (index < SECTOR_SIZE) @@ -224,9 +220,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) bitpos = (bitpos + 10) & 7; if (bitpos == 0) bitpos = 8; - if ((index >= 0 && index < SECTOR_SIZE) || - index == (SECTOR_SIZE + 1)) { - val = (uint8_t)(errval[i] << (8 - bitpos)); + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { + val = (uint8_t) (errval[i] << (8 - bitpos)); parity ^= val; if (index < SECTOR_SIZE) data[index] ^= val; @@ -261,7 +256,8 @@ static int _DoC_WaitReady(struct doc_priv *doc) void __iomem *docptr = doc->virtadr; unsigned long timeo = jiffies + (HZ * 10); - if(debug) printk("_DoC_WaitReady...\n"); + if (debug) + printk("_DoC_WaitReady...\n"); /* Out-of-line routine to wait for chip response */ if (DoC_is_MillenniumPlus(doc)) { while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { @@ -306,7 +302,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc) DoC_Delay(doc, 2); } - if(debug) printk("DoC_WaitReady OK\n"); + if (debug) + printk("DoC_WaitReady OK\n"); return ret; } @@ -316,7 +313,8 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; - if(debug)printk("write_byte %02x\n", datum); + if (debug) + printk("write_byte %02x\n", datum); WriteDOC(datum, docptr, CDSNSlowIO); WriteDOC(datum, docptr, 2k_CDSN_IO); } @@ -331,37 +329,39 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) ReadDOC(docptr, CDSNSlowIO); DoC_Delay(doc, 2); ret = ReadDOC(docptr, 2k_CDSN_IO); - if (debug) printk("read_byte returns %02x\n", ret); + if (debug) + printk("read_byte returns %02x\n", ret); return ret; } -static void doc2000_writebuf(struct mtd_info *mtd, - const u_char *buf, int len) +static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("writebuf of %d bytes: ", len); - for (i=0; i < len; i++) { + if (debug) + printk("writebuf of %d bytes: ", len); + for (i = 0; i < len; i++) { WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); if (debug && i < 16) printk("%02x ", buf[i]); } - if (debug) printk("\n"); + if (debug) + printk("\n"); } -static void doc2000_readbuf(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("readbuf of %d bytes: ", len); + if (debug) + printk("readbuf of %d bytes: ", len); - for (i=0; i < len; i++) { + for (i = 0; i < len; i++) { buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); } } @@ -374,28 +374,28 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, void __iomem *docptr = doc->virtadr; int i; - if (debug) printk("readbuf_dword of %d bytes: ", len); + if (debug) + printk("readbuf_dword of %d bytes: ", len); - if (unlikely((((unsigned long)buf)|len) & 3)) { - for (i=0; i < len; i++) { - *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); + if (unlikely((((unsigned long)buf) | len) & 3)) { + for (i = 0; i < len; i++) { + *(uint8_t *) (&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); } } else { - for (i=0; i < len; i+=4) { - *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); + for (i = 0; i < len; i += 4) { + *(uint32_t*) (&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); } } } -static int doc2000_verifybuf(struct mtd_info *mtd, - const u_char *buf, int len) +static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - for (i=0; i < len; i++) + for (i = 0; i < len; i++) if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) return -EFAULT; return 0; @@ -408,12 +408,15 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) uint16_t ret; doc200x_select_chip(mtd, nr); - doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); - this->write_byte(mtd, NAND_CMD_READID); - doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); - doc200x_hwcontrol(mtd, NAND_CTL_SETALE); - this->write_byte(mtd, 0); - doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); + doc200x_hwcontrol(mtd, NAND_CMD_READID, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + + /* We cant' use dev_ready here, but at least we wait for the + * command to complete + */ + udelay(50); ret = this->read_byte(mtd) << 8; ret |= this->read_byte(mtd); @@ -426,12 +429,13 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) } ident; void __iomem *docptr = doc->virtadr; - doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); - doc2000_write_byte(mtd, NAND_CMD_READID); - doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); - doc200x_hwcontrol(mtd, NAND_CTL_SETALE); - doc2000_write_byte(mtd, 0); - doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); + doc200x_hwcontrol(mtd, NAND_CMD_READID, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + udelay(50); ident.dword = readl(docptr + DoC_2k_CDSN_IO); if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { @@ -465,7 +469,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd) printk(KERN_DEBUG "Detected %d chips per floor.\n", i); } -static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) { struct doc_priv *doc = this->priv; @@ -496,30 +500,28 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; - /*ReadDOC(docptr, CDSNSlowIO); */ + //ReadDOC(docptr, CDSNSlowIO); /* 11.4.5 -- delay twice to allow extended length cycle */ DoC_Delay(doc, 2); ReadDOC(docptr, ReadPipeInit); - /*return ReadDOC(docptr, Mil_CDSN_IO); */ + //return ReadDOC(docptr, Mil_CDSN_IO); return ReadDOC(docptr, LastDataRead); } -static void doc2001_writebuf(struct mtd_info *mtd, - const u_char *buf, int len) +static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - for (i=0; i < len; i++) + for (i = 0; i < len; i++) WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); /* Terminate write pipeline */ WriteDOC(0x00, docptr, WritePipeTerm); } -static void doc2001_readbuf(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -529,15 +531,14 @@ static void doc2001_readbuf(struct mtd_info *mtd, /* Start read pipeline */ ReadDOC(docptr, ReadPipeInit); - for (i=0; i < len-1; i++) + for (i = 0; i < len - 1; i++) buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); /* Terminate read pipeline */ buf[i] = ReadDOC(docptr, LastDataRead); } -static int doc2001_verifybuf(struct mtd_info *mtd, - const u_char *buf, int len) +static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -547,7 +548,7 @@ static int doc2001_verifybuf(struct mtd_info *mtd, /* Start read pipeline */ ReadDOC(docptr, ReadPipeInit); - for (i=0; i < len-1; i++) + for (i = 0; i < len - 1; i++) if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { ReadDOC(docptr, LastDataRead); return i; @@ -567,81 +568,84 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); ret = ReadDOC(docptr, Mplus_LastDataRead); - if (debug) printk("read_byte returns %02x\n", ret); + if (debug) + printk("read_byte returns %02x\n", ret); return ret; } -static void doc2001plus_writebuf(struct mtd_info *mtd, - const u_char *buf, int len) +static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("writebuf of %d bytes: ", len); - for (i=0; i < len; i++) { + if (debug) + printk("writebuf of %d bytes: ", len); + for (i = 0; i < len; i++) { WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); if (debug && i < 16) printk("%02x ", buf[i]); } - if (debug) printk("\n"); + if (debug) + printk("\n"); } -static void doc2001plus_readbuf(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("readbuf of %d bytes: ", len); + if (debug) + printk("readbuf of %d bytes: ", len); /* Start read pipeline */ ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); - for (i=0; i < len-2; i++) { + for (i = 0; i < len - 2; i++) { buf[i] = ReadDOC(docptr, Mil_CDSN_IO); if (debug && i < 16) printk("%02x ", buf[i]); } /* Terminate read pipeline */ - buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); + buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead); if (debug && i < 16) - printk("%02x ", buf[len-2]); - buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); + printk("%02x ", buf[len - 2]); + buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead); if (debug && i < 16) - printk("%02x ", buf[len-1]); - if (debug) printk("\n"); + printk("%02x ", buf[len - 1]); + if (debug) + printk("\n"); } -static int doc2001plus_verifybuf(struct mtd_info *mtd, - const u_char *buf, int len) +static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("verifybuf of %d bytes: ", len); + if (debug) + printk("verifybuf of %d bytes: ", len); /* Start read pipeline */ ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); - for (i=0; i < len-2; i++) + for (i = 0; i < len - 2; i++) if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { ReadDOC(docptr, Mplus_LastDataRead); ReadDOC(docptr, Mplus_LastDataRead); return i; } - if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead)) - return len-2; - if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead)) - return len-1; + if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead)) + return len - 2; + if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead)) + return len - 1; return 0; } @@ -652,7 +656,8 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) void __iomem *docptr = doc->virtadr; int floor = 0; - if(debug)printk("select chip (%d)\n", chip); + if (debug) + printk("select chip (%d)\n", chip); if (chip == -1) { /* Disable flash internally */ @@ -661,7 +666,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) } floor = chip / doc->chips_per_floor; - chip -= (floor * doc->chips_per_floor); + chip -= (floor * doc->chips_per_floor); /* Assert ChipEnable and deassert WriteProtect */ WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); @@ -678,65 +683,54 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip) void __iomem *docptr = doc->virtadr; int floor = 0; - if(debug)printk("select chip (%d)\n", chip); + if (debug) + printk("select chip (%d)\n", chip); if (chip == -1) return; floor = chip / doc->chips_per_floor; - chip -= (floor * doc->chips_per_floor); + chip -= (floor * doc->chips_per_floor); /* 11.4.4 -- deassert CE before changing chip */ - doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); WriteDOC(floor, docptr, FloorSelect); WriteDOC(chip, docptr, CDSNDeviceSelect); - doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); doc->curchip = chip; doc->curfloor = floor; } -static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) +#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE) + +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; - switch(cmd) { - case NAND_CTL_SETNCE: - doc->CDSNControl |= CDSN_CTRL_CE; - break; - case NAND_CTL_CLRNCE: - doc->CDSNControl &= ~CDSN_CTRL_CE; - break; - case NAND_CTL_SETCLE: - doc->CDSNControl |= CDSN_CTRL_CLE; - break; - case NAND_CTL_CLRCLE: - doc->CDSNControl &= ~CDSN_CTRL_CLE; - break; - case NAND_CTL_SETALE: - doc->CDSNControl |= CDSN_CTRL_ALE; - break; - case NAND_CTL_CLRALE: - doc->CDSNControl &= ~CDSN_CTRL_ALE; - break; - case NAND_CTL_SETWP: - doc->CDSNControl |= CDSN_CTRL_WP; - break; - case NAND_CTL_CLRWP: - doc->CDSNControl &= ~CDSN_CTRL_WP; - break; + if (ctrl & NAND_CTRL_CHANGE) { + doc->CDSNControl &= ~CDSN_CTRL_MSK; + doc->CDSNControl |= ctrl & CDSN_CTRL_MSK; + if (debug) + printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); + WriteDOC(doc->CDSNControl, docptr, CDSNControl); + /* 11.4.3 -- 4 NOPs after CSDNControl write */ + DoC_Delay(doc, 4); + } + if (cmd != NAND_CMD_NONE) { + if (DoC_is_2000(doc)) + doc2000_write_byte(mtd, cmd); + else + doc2001_write_byte(mtd, cmd); } - if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); - WriteDOC(doc->CDSNControl, docptr, CDSNControl); - /* 11.4.3 -- 4 NOPs after CSDNControl write */ - DoC_Delay(doc, 4); } -static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) +static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -757,9 +751,9 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col if (command == NAND_CMD_SEQIN) { int readcmd; - if (column >= mtd->oobblock) { + if (column >= mtd->writesize) { /* OOB area */ - column -= mtd->oobblock; + column -= mtd->writesize; readcmd = NAND_CMD_READOOB; } else if (column < 256) { /* First 256 bytes --> READ0 */ @@ -783,25 +777,26 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col WriteDOC(column, docptr, Mplus_FlashAddress); } if (page_addr != -1) { - WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress); - WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); /* One more address cycle for higher density devices */ if (this->chipsize & 0x0c000000) { - WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); printk("high density\n"); } } WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); /* deassert ALE */ - if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID) + if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || + command == NAND_CMD_READOOB || command == NAND_CMD_READID) WriteDOC(0, docptr, Mplus_FlashControl); } /* * program and erase have their own busy handlers * status and sequential in needs no delay - */ + */ switch (command) { case NAND_CMD_PAGEPROG: @@ -818,26 +813,26 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); - while ( !(this->read_byte(mtd) & 0x40)); + while (!(this->read_byte(mtd) & 0x40)) ; return; - /* This applies to read commands */ + /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay - */ + */ if (!this->dev_ready) { - udelay (this->chip_delay); + udelay(this->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ - ndelay (100); + ndelay(100); /* wait until command is processed */ - while (!this->dev_ready(mtd)); + while (!this->dev_ready(mtd)) ; } static int doc200x_dev_ready(struct mtd_info *mtd) @@ -850,23 +845,25 @@ static int doc200x_dev_ready(struct mtd_info *mtd) /* 11.4.2 -- must NOP four times before checking FR/B# */ DoC_Delay(doc, 4); if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { - if(debug) + if (debug) printk("not ready\n"); return 0; } - if (debug)printk("was ready\n"); + if (debug) + printk("was ready\n"); return 1; } else { /* 11.4.2 -- must NOP four times before checking FR/B# */ DoC_Delay(doc, 4); if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { - if(debug) + if (debug) printk("not ready\n"); return 0; } /* 11.4.2 -- Must NOP twice if it's ready */ DoC_Delay(doc, 2); - if (debug)printk("was ready\n"); + if (debug) + printk("was ready\n"); return 1; } } @@ -885,7 +882,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ - switch(mode) { + switch (mode) { case NAND_ECC_READ: WriteDOC(DOC_ECC_RESET, docptr, ECCConf); WriteDOC(DOC_ECC_EN, docptr, ECCConf); @@ -904,7 +901,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ - switch(mode) { + switch (mode) { case NAND_ECC_READ: WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); @@ -917,8 +914,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) } /* This code is only called on write */ -static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - unsigned char *ecc_code) +static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -962,7 +958,8 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, often. It could be optimized away by examining the data in the writebuf routine, and remembering the result. */ for (i = 0; i < 512; i++) { - if (dat[i] == 0xff) continue; + if (dat[i] == 0xff) + continue; emptymatch = 0; break; } @@ -970,17 +967,20 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, /* If emptymatch still =1, we do have an all-0xff data buffer. Return all-0xff ecc value instead of the computed one, so it'll look just like a freshly-erased page. */ - if (emptymatch) memset(ecc_code, 0xff, 6); + if (emptymatch) + memset(ecc_code, 0xff, 6); #endif return 0; } -static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *isnull) { int i, ret = 0; struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; + uint8_t calc_ecc[6]; volatile u_char dummy; int emptymatch = 1; @@ -1013,18 +1013,20 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ all-0xff data and stored ecc block. Check the stored ecc. */ if (emptymatch) { for (i = 0; i < 6; i++) { - if (read_ecc[i] == 0xff) continue; + if (read_ecc[i] == 0xff) + continue; emptymatch = 0; break; } } /* If emptymatch still =1, check the data block. */ if (emptymatch) { - /* Note: this somewhat expensive test should not be triggered - often. It could be optimized away by examining the data in - the readbuf routine, and remembering the result. */ + /* Note: this somewhat expensive test should not be triggered + often. It could be optimized away by examining the data in + the readbuf routine, and remembering the result. */ for (i = 0; i < 512; i++) { - if (dat[i] == 0xff) continue; + if (dat[i] == 0xff) + continue; emptymatch = 0; break; } @@ -1033,7 +1035,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ erased block, in which case the ECC will not come out right. We'll suppress the error and tell the caller everything's OK. Because it is. */ - if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); + if (!emptymatch) + ret = doc_ecc_decode(rs_decoder, dat, calc_ecc); if (ret > 0) printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); } @@ -1048,13 +1051,22 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ return ret; } -/*u_char mydatabuf[528]; */ - -static struct nand_oobinfo doc200x_oobinfo = { - .useecc = MTD_NANDECC_AUTOPLACE, +//u_char mydatabuf[528]; + +/* The strange out-of-order .oobfree list below is a (possibly unneeded) + * attempt to retain compatibility. It used to read: + * .oobfree = { {8, 8} } + * Since that leaves two bytes unusable, it was changed. But the following + * scheme might affect existing jffs2 installs by moving the cleanmarker: + * .oobfree = { {6, 10} } + * jffs2 seems to handle the above gracefully, but the current scheme seems + * safer. The only problem with it is that any code that parses oobfree must + * be able to handle out-of-order segments. + */ +static struct nand_ecclayout doc200x_oobinfo = { .eccbytes = 6, .eccpos = {0, 1, 2, 3, 4, 5}, - .oobfree = { {8, 8} } + .oobfree = {{8, 8}, {6, 2}} }; /* Find the (I)NFTL Media Header, and optionally also the mirror media header. @@ -1063,28 +1075,28 @@ static struct nand_oobinfo doc200x_oobinfo = { either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media header. The page #s of the found media headers are placed in mh0_page and mh1_page in the DOC private structure. */ -static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, - const char *id, int findmirror) +static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift); + unsigned offs; int ret; size_t retlen; - end = min(end, mtd->size); /* paranoia */ - for (offs = 0; offs < end; offs += mtd->erasesize) { - ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); - if (retlen != mtd->oobblock) continue; + for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { + ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + if (retlen != mtd->writesize) + continue; if (ret) { - printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", - offs); + printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs); } - if (memcmp(buf, id, 6)) continue; + if (memcmp(buf, id, 6)) + continue; printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs); if (doc->mh0_page == -1) { doc->mh0_page = offs >> this->page_shift; - if (!findmirror) return 1; + if (!findmirror) + return 1; continue; } doc->mh1_page = offs >> this->page_shift; @@ -1097,8 +1109,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, /* Only one mediaheader was found. We want buf to contain a mediaheader on return, so we'll have to re-read the one we found. */ offs = doc->mh0_page << this->page_shift; - ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); - if (retlen != mtd->oobblock) { + ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + if (retlen != mtd->writesize) { /* Insanity. Give up. */ printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); return 0; @@ -1106,8 +1118,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, return 1; } -static inline int __init nftl_partscan(struct mtd_info *mtd, - struct mtd_partition *parts) +static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -1115,19 +1126,23 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, u_char *buf; struct NFTLMediaHeader *mh; const unsigned psize = 1 << this->page_shift; + int numparts = 0; unsigned blocks, maxblocks; int offs, numheaders; - buf = kmalloc(mtd->oobblock, GFP_KERNEL); + buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } - if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out; - mh = (struct NFTLMediaHeader *) buf; + if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1))) + goto out; + mh = (struct NFTLMediaHeader *)buf; + + mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits); + mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN); + mh->FormattedSize = le32_to_cpu(mh->FormattedSize); -/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */ -/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */ printk(KERN_INFO " DataOrgID = %s\n" " NumEraseUnits = %d\n" " FirstPhysicalEUN = %d\n" @@ -1136,7 +1151,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, mh->DataOrgID, mh->NumEraseUnits, mh->FirstPhysicalEUN, mh->FormattedSize, mh->UnitSizeFactor); -/*#endif */ blocks = mtd->size >> this->phys_erase_shift; maxblocks = min(32768U, mtd->erasesize - psize); @@ -1145,8 +1159,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, /* Auto-determine UnitSizeFactor. The constraints are: - There can be at most 32768 virtual blocks. - There can be at most (virtual block size - page size) - virtual blocks (because MediaHeader+BBT must fit in 1). - */ + virtual blocks (because MediaHeader+BBT must fit in 1). + */ mh->UnitSizeFactor = 0xff; while (blocks > maxblocks) { blocks >>= 1; @@ -1179,31 +1193,35 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, offs <<= this->page_shift; offs += mtd->erasesize; - /*parts[0].name = " DiskOnChip Boot / Media Header partition"; */ - /*parts[0].offset = 0; */ - /*parts[0].size = offs; */ + if (show_firmware_partition == 1) { + parts[0].name = " DiskOnChip Firmware / Media Header partition"; + parts[0].offset = 0; + parts[0].size = offs; + numparts = 1; + } + + parts[numparts].name = " DiskOnChip BDTL partition"; + parts[numparts].offset = offs; + parts[numparts].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift; - parts[0].name = " DiskOnChip BDTL partition"; - parts[0].offset = offs; - parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift; + offs += parts[numparts].size; + numparts++; - offs += parts[0].size; if (offs < mtd->size) { - parts[1].name = " DiskOnChip Remainder partition"; - parts[1].offset = offs; - parts[1].size = mtd->size - offs; - ret = 2; - goto out; + parts[numparts].name = " DiskOnChip Remainder partition"; + parts[numparts].offset = offs; + parts[numparts].size = mtd->size - offs; + numparts++; } - ret = 1; -out: + + ret = numparts; + out: kfree(buf); return ret; } /* This is a stripped-down copy of the code in inftlmount.c */ -static inline int __init inftl_partscan(struct mtd_info *mtd, - struct mtd_partition *parts) +static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -1220,15 +1238,16 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, if (inftl_bbt_write) end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); - buf = kmalloc(mtd->oobblock, GFP_KERNEL); + buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } - if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out; + if (!find_media_headers(mtd, buf, "BNAND", 0)) + goto out; doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); - mh = (struct INFTLMediaHeader *) buf; + mh = (struct INFTLMediaHeader *)buf; mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); @@ -1237,8 +1256,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, mh->FormatFlags = le32_to_cpu(mh->FormatFlags); mh->PercentUsed = le32_to_cpu(mh->PercentUsed); -/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */ -/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */ printk(KERN_INFO " bootRecordID = %s\n" " NoOfBootImageBlocks = %d\n" " NoOfBinaryPartitions = %d\n" @@ -1256,7 +1273,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, ((unsigned char *) &mh->OsakVersion)[2] & 0xf, ((unsigned char *) &mh->OsakVersion)[3] & 0xf, mh->PercentUsed); -/*#endif */ vshift = this->phys_erase_shift + mh->BlockMultiplierBits; @@ -1282,8 +1298,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, ip->spareUnits = le32_to_cpu(ip->spareUnits); ip->Reserved0 = le32_to_cpu(ip->Reserved0); -/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */ -/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */ printk(KERN_INFO " PARTITION[%d] ->\n" " virtualUnits = %d\n" " firstUnit = %d\n" @@ -1293,16 +1307,14 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, i, ip->virtualUnits, ip->firstUnit, ip->lastUnit, ip->flags, ip->spareUnits); -/*#endif */ -/* - if ((i == 0) && (ip->firstUnit > 0)) { + if ((show_firmware_partition == 1) && + (i == 0) && (ip->firstUnit > 0)) { parts[0].name = " DiskOnChip IPL / Media Header partition"; parts[0].offset = 0; parts[0].size = mtd->erasesize * ip->firstUnit; numparts = 1; } -*/ if (ip->flags & INFTL_BINARY) parts[numparts].name = " DiskOnChip BDK partition"; @@ -1311,8 +1323,10 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, parts[numparts].offset = ip->firstUnit << vshift; parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; numparts++; - if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit; - if (ip->flags & INFTL_LAST) break; + if (ip->lastUnit > lastvunit) + lastvunit = ip->lastUnit; + if (ip->flags & INFTL_LAST) + break; } lastvunit++; if ((lastvunit << vshift) < end) { @@ -1322,7 +1336,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, numparts++; } ret = numparts; -out: + out: kfree(buf); return ret; } @@ -1334,11 +1348,12 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) struct doc_priv *doc = this->priv; struct mtd_partition parts[2]; - memset((char *) parts, 0, sizeof(parts)); + memset((char *)parts, 0, sizeof(parts)); /* On NFTL, we have to find the media headers before we can read the BBTs, since they're stored in the media header eraseblocks. */ numparts = nftl_partscan(mtd, parts); - if (!numparts) return -EIO; + if (!numparts) + return -EIO; this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | NAND_BBT_VERSION; @@ -1385,8 +1400,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) this->bbt_td->pages[0] = 2; this->bbt_md = NULL; } else { - this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | - NAND_BBT_VERSION; + this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; if (inftl_bbt_write) this->bbt_td->options |= NAND_BBT_WRITE; this->bbt_td->offs = 8; @@ -1396,8 +1410,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) this->bbt_td->reserved_block_code = 0x01; this->bbt_td->pattern = "MSYS_BBT"; - this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | - NAND_BBT_VERSION; + this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; if (inftl_bbt_write) this->bbt_md->options |= NAND_BBT_WRITE; this->bbt_md->offs = 8; @@ -1412,12 +1425,13 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) At least as nand_bbt.c is currently written. */ if ((ret = nand_scan_bbt(mtd, NULL))) return ret; - memset((char *) parts, 0, sizeof(parts)); + memset((char *)parts, 0, sizeof(parts)); numparts = inftl_partscan(mtd, parts); /* At least for now, require the INFTL Media Header. We could probably do without it for non-INFTL use, since all it gives us is autopartitioning, but I want to give it more thought. */ - if (!numparts) return -EIO; + if (!numparts) + return -EIO; add_mtd_device(mtd); #ifdef CONFIG_MTD_PARTITIONS if (!no_autopart) @@ -1431,7 +1445,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd) struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - this->write_byte = doc2000_write_byte; this->read_byte = doc2000_read_byte; this->write_buf = doc2000_writebuf; this->read_buf = doc2000_readbuf; @@ -1449,7 +1462,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd) struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - this->write_byte = doc2001_write_byte; this->read_byte = doc2001_read_byte; this->write_buf = doc2001_writebuf; this->read_buf = doc2001_readbuf; @@ -1481,16 +1493,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - this->write_byte = NULL; this->read_byte = doc2001plus_read_byte; this->write_buf = doc2001plus_writebuf; this->read_buf = doc2001plus_readbuf; this->verify_buf = doc2001plus_verifybuf; this->scan_bbt = inftl_scan_bbt; - this->hwcontrol = NULL; + this->cmd_ctrl = NULL; this->select_chip = doc2001plus_select_chip; this->cmdfunc = doc2001plus_command; - this->enable_hwecc = doc2001plus_enable_hwecc; + this->ecc.hwctl = doc2001plus_enable_hwecc; doc->chips_per_floor = 1; mtd->name = "DiskOnChip Millennium Plus"; @@ -1498,7 +1509,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) return 1; } -static inline int __init doc_probe(unsigned long physadr) +static int __init doc_probe(unsigned long physadr) { unsigned char ChipID; struct mtd_info *mtd; @@ -1527,20 +1538,16 @@ static inline int __init doc_probe(unsigned long physadr) save_control = ReadDOC(virtadr, DOCControl); /* Reset the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, - virtadr, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, - virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); /* Enable the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, - virtadr, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, - virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); ChipID = ReadDOC(virtadr, ChipID); - switch(ChipID) { + switch (ChipID) { case DOC_ChipID_Doc2k: reg = DoC_2k_ECCStatus; break; @@ -1556,15 +1563,13 @@ static inline int __init doc_probe(unsigned long physadr) ReadDOC(virtadr, Mplus_Power); /* Reset the Millennium Plus ASIC */ - tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | - DOC_MODE_BDECT; + tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT; WriteDOC(tmp, virtadr, Mplus_DOCControl); WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); mdelay(1); /* Enable the Millennium Plus ASIC */ - tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | - DOC_MODE_BDECT; + tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT; WriteDOC(tmp, virtadr, Mplus_DOCControl); WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); mdelay(1); @@ -1588,7 +1593,7 @@ static inline int __init doc_probe(unsigned long physadr) goto notfound; } /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; + tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; if ((tmp == tmpb) || (tmp != tmpc)) { @@ -1618,11 +1623,11 @@ static inline int __init doc_probe(unsigned long physadr) if (ChipID == DOC_ChipID_DocMilPlus16) { WriteDOC(~newval, virtadr, Mplus_AliasResolution); oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); - WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */ + WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it } else { WriteDOC(~newval, virtadr, AliasResolution); oldval = ReadDOC(doc->virtadr, AliasResolution); - WriteDOC(newval, virtadr, AliasResolution); /* restore it */ + WriteDOC(newval, virtadr, AliasResolution); // restore it } newval = ~newval; if (oldval == newval) { @@ -1634,16 +1639,13 @@ static inline int __init doc_probe(unsigned long physadr) printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); len = sizeof(struct mtd_info) + - sizeof(struct nand_chip) + - sizeof(struct doc_priv) + - (2 * sizeof(struct nand_bbt_descr)); - mtd = kmalloc(len, GFP_KERNEL); + sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); + mtd = kzalloc(len, GFP_KERNEL); if (!mtd) { printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); ret = -ENOMEM; goto fail; } - memset(mtd, 0, len); nand = (struct nand_chip *) (mtd + 1); doc = (struct doc_priv *) (nand + 1); @@ -1655,17 +1657,19 @@ static inline int __init doc_probe(unsigned long physadr) nand->priv = doc; nand->select_chip = doc200x_select_chip; - nand->hwcontrol = doc200x_hwcontrol; + nand->cmd_ctrl = doc200x_hwcontrol; nand->dev_ready = doc200x_dev_ready; nand->waitfunc = doc200x_wait; nand->block_bad = doc200x_block_bad; - nand->enable_hwecc = doc200x_enable_hwecc; - nand->calculate_ecc = doc200x_calculate_ecc; - nand->correct_data = doc200x_correct_data; + nand->ecc.hwctl = doc200x_enable_hwecc; + nand->ecc.calculate = doc200x_calculate_ecc; + nand->ecc.correct = doc200x_correct_data; - nand->autooob = &doc200x_oobinfo; - nand->eccmode = NAND_ECC_HW6_512; - nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; + nand->ecc.layout = &doc200x_oobinfo; + nand->ecc.mode = NAND_ECC_HW_SYNDROME; + nand->ecc.size = 512; + nand->ecc.bytes = 6; + nand->options = NAND_USE_FLASH_BBT; doc->physadr = physadr; doc->virtadr = virtadr; @@ -1699,11 +1703,11 @@ static inline int __init doc_probe(unsigned long physadr) doclist = mtd; return 0; -notfound: + notfound: /* Put back the contents of the DOCControl register, in case it's not actually a DiskOnChip. */ WriteDOC(save_control, virtadr, DOCControl); -fail: + fail: iounmap(virtadr); return ret; } @@ -1740,7 +1744,7 @@ static int __init init_nanddoc(void) */ rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); if (!rs_decoder) { - printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); + printk(KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); return -ENOMEM; } @@ -1750,7 +1754,7 @@ static int __init init_nanddoc(void) if (ret < 0) goto outerr; } else { - for (i=0; (doc_locations[i] != 0xffffffff); i++) { + for (i = 0; (doc_locations[i] != 0xffffffff); i++) { doc_probe(doc_locations[i]); } } @@ -1762,7 +1766,7 @@ static int __init init_nanddoc(void) goto outerr; } return 0; -outerr: + outerr: free_rs(rs_decoder); return ret; } |