From 74216be41a61a809ad17b091068307e3d89f4a2f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 30 Jul 2008 11:18:42 +0300 Subject: [MTD] [NAND] nandsim: support random page read command Commit 3d45955962496879dead8d4dd70bb9a23b07154b ("subpage read feature as a way to improve performance") broke nandsim because nandsim does not support the "random page read" NAND command. This patch adds corresponding support. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/nandsim.c | 57 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 17 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index ecd70e2504f6..7428a6c1135e 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -207,13 +207,16 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I #define STATE_CMD_READID 0x0000000A /* read ID */ #define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */ #define STATE_CMD_RESET 0x0000000C /* reset */ +#define STATE_CMD_RNDOUT 0x0000000D /* random output command */ +#define STATE_CMD_RNDOUTSTART 0x0000000E /* random output start command */ #define STATE_CMD_MASK 0x0000000F /* command states mask */ /* After an address is input, the simulator goes to one of these states */ #define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */ #define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */ -#define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */ -#define STATE_ADDR_MASK 0x00000030 /* address states mask */ +#define STATE_ADDR_COLUMN 0x00000030 /* column address was accepted */ +#define STATE_ADDR_ZERO 0x00000040 /* one byte zero address was accepted */ +#define STATE_ADDR_MASK 0x00000070 /* address states mask */ /* Durind data input/output the simulator is in these states */ #define STATE_DATAIN 0x00000100 /* waiting for data input */ @@ -240,7 +243,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I #define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */ #define ACTION_MASK 0x00700000 /* action mask */ -#define NS_OPER_NUM 12 /* Number of operations supported by the simulator */ +#define NS_OPER_NUM 13 /* Number of operations supported by the simulator */ #define NS_OPER_STATES 6 /* Maximum number of states in operation */ #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ @@ -373,7 +376,10 @@ static struct nandsim_operations { {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}}, /* Large page devices read page */ {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY, - STATE_DATAOUT, STATE_READY}} + STATE_DATAOUT, STATE_READY}}, + /* Large page devices random page read */ + {OPT_LARGEPAGE, {STATE_CMD_RNDOUT, STATE_ADDR_COLUMN, STATE_CMD_RNDOUTSTART | ACTION_CPY, + STATE_DATAOUT, STATE_READY}}, }; struct weak_block { @@ -937,12 +943,18 @@ static char *get_state_name(uint32_t state) return "STATE_CMD_ERASE2"; case STATE_CMD_RESET: return "STATE_CMD_RESET"; + case STATE_CMD_RNDOUT: + return "STATE_CMD_RNDOUT"; + case STATE_CMD_RNDOUTSTART: + return "STATE_CMD_RNDOUTSTART"; case STATE_ADDR_PAGE: return "STATE_ADDR_PAGE"; case STATE_ADDR_SEC: return "STATE_ADDR_SEC"; case STATE_ADDR_ZERO: return "STATE_ADDR_ZERO"; + case STATE_ADDR_COLUMN: + return "STATE_ADDR_COLUMN"; case STATE_DATAIN: return "STATE_DATAIN"; case STATE_DATAOUT: @@ -973,6 +985,7 @@ static int check_command(int cmd) switch (cmd) { case NAND_CMD_READ0: + case NAND_CMD_READ1: case NAND_CMD_READSTART: case NAND_CMD_PAGEPROG: case NAND_CMD_READOOB: @@ -982,7 +995,8 @@ static int check_command(int cmd) case NAND_CMD_READID: case NAND_CMD_ERASE2: case NAND_CMD_RESET: - case NAND_CMD_READ1: + case NAND_CMD_RNDOUT: + case NAND_CMD_RNDOUTSTART: return 0; case NAND_CMD_STATUS_MULTI: @@ -1021,6 +1035,10 @@ static uint32_t get_state_by_command(unsigned command) return STATE_CMD_ERASE2; case NAND_CMD_RESET: return STATE_CMD_RESET; + case NAND_CMD_RNDOUT: + return STATE_CMD_RNDOUT; + case NAND_CMD_RNDOUTSTART: + return STATE_CMD_RNDOUTSTART; } NS_ERR("get_state_by_command: unknown command, BUG\n"); @@ -1582,6 +1600,11 @@ static void switch_state(struct nandsim *ns) ns->regs.num = 1; break; + case STATE_ADDR_COLUMN: + /* Column address is always 2 bytes */ + ns->regs.num = ns->geom.pgaddrbytes - ns->geom.secaddrbytes; + break; + default: NS_ERR("switch_state: BUG! unknown address state\n"); } @@ -1693,15 +1716,21 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) return; } - /* - * Chip might still be in STATE_DATAOUT - * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or - * STATE_DATAOUT_STATUS_M state. If so, switch state. - */ + /* Check that the command byte is correct */ + if (check_command(byte)) { + NS_ERR("write_byte: unknown command %#x\n", (uint)byte); + return; + } + if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M - || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT)) + || NS_STATE(ns->state) == STATE_DATAOUT) { + int row = ns->regs.row; + switch_state(ns); + if (byte == NAND_CMD_RNDOUT) + ns->regs.row = row; + } /* Check if chip is expecting command */ if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { @@ -1715,12 +1744,6 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); } - /* Check that the command byte is correct */ - if (check_command(byte)) { - NS_ERR("write_byte: unknown command %#x\n", (uint)byte); - return; - } - NS_DBG("command byte corresponding to %s state accepted\n", get_state_name(get_state_by_command(byte))); ns->regs.command = byte; -- cgit v1.2.3-58-ga151 From 650da9d0b7c401619c1df2953e975606b8d5dcbb Mon Sep 17 00:00:00 2001 From: "akpm@linux-foundation.org" Date: Tue, 29 Jul 2008 21:27:14 -0700 Subject: [MTD] [NAND] fsl_elbc_nand.c: fix printk warning drivers/mtd/nand/fsl_elbc_nand.c:890: warning: format '%x' expects type 'unsigned int', but argument 3 has type 'resource_size_t' Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/fsl_elbc_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 9dff51351f4f..98ad3cefcaf4 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -887,7 +887,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, goto err; } - priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", res.start); + priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start); if (!priv->mtd.name) { ret = -ENOMEM; goto err; -- cgit v1.2.3-58-ga151 From 771999b65f79264acde4b855e5d35696eca5e80c Mon Sep 17 00:00:00 2001 From: "akpm@linux-foundation.org" Date: Tue, 29 Jul 2008 22:22:40 -0700 Subject: [MTD] DataFlash: bugfix, binary page sizes now handled The wrong version of the "teach dataflash about binary density" patch just got merged (v2 not v3) ... this restores the missing updates: * Fix the cmdlinepart *regression* that caused testing failures (!!) by restoring the original part labels in relevant cases. * Don't reference things that don't exist (!) - An opcode that doesn't even exist for DataFlash - The part is "at45db642" not "at45db641" - ID zero in this JEDEC table * Make the JEDEC probe routine report and handle errors better: - If the SPI calls fail, return the error codes. - Don't depend on ordering of table entries. - Unrecognized ids are different from parts that have no ID. We won't actually know how to handle them correctly; display the ID and ignore the chip. * Move the original block comment about the "legacy" chip ID scheme back next to the code to which it applies ... not next to the new JEDEC query code, which uses an entirely different strategy. * Don't print a guessed erasesize; /proc/mtd has the real value. And add a few more comments. Signed-off-by: David Brownell Cc: Bryan Wu Cc: Michael Hennerich Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/devices/mtd_dataflash.c | 130 +++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 47 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 54e36bfc2c3b..8bd0dea6885f 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -15,6 +15,8 @@ #include #include #include +#include + #include #include @@ -487,9 +489,8 @@ add_dataflash(struct spi_device *spi, char *name, device->write = dataflash_write; device->priv = priv; - dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes, " - "erasesize %d bytes\n", name, device->size/1024, - pagesize, pagesize * 8); /* 8 pages = 1 block */ + dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes\n", + name, DIV_ROUND_UP(device->size, 1024), pagesize); dev_set_drvdata(&spi->dev, priv); if (mtd_has_partitions()) { @@ -518,65 +519,57 @@ add_dataflash(struct spi_device *spi, char *name, return add_mtd_device(device) == 1 ? -ENODEV : 0; } -/* - * Detect and initialize DataFlash device: - * - * Device Density ID code #Pages PageSize Offset - * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 - * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1024 264 9 - * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 - * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 - * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 - * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 - * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 - * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 - */ - struct flash_info { char *name; - /* JEDEC id zero means "no ID" (most older chips); otherwise it has - * a high byte of zero plus three data bytes: the manufacturer id, - * then a two byte device id. + /* JEDEC id has a high byte of zero plus three data bytes: + * the manufacturer id, then a two byte device id. */ uint32_t jedec_id; - /* The size listed here is what works with OPCODE_SE, which isn't - * necessarily called a "sector" by the vendor. - */ + /* The size listed here is what works with OP_ERASE_PAGE. */ unsigned nr_pages; uint16_t pagesize; uint16_t pageoffset; uint16_t flags; -#define SUP_POW2PS 0x02 -#define IS_POW2PS 0x01 +#define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ +#define IS_POW2PS 0x0001 /* uses 2^N byte pages */ }; static struct flash_info __devinitdata dataflash_data [] = { - { "at45db011d", 0x1f2200, 512, 264, 9, SUP_POW2PS}, + /* + * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, + * one with IS_POW2PS and the other without. The entry with the + * non-2^N byte page size can't name exact chip revisions without + * losing backwards compatibility for cmdlinepart. + * + * These newer chips also support 128-byte security registers (with + * 64 bytes one-time-programmable) and software write-protection. + */ + { "AT45DB011B", 0x1f2200, 512, 264, 9, SUP_POW2PS}, { "at45db011d", 0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS}, - { "at45db021d", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, + { "AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, { "at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS}, - { "at45db041d", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, + { "AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, { "at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS}, - { "at45db081d", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, + { "AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, { "at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS}, - { "at45db161d", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, + { "AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, { "at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS}, - { "at45db321c", 0x1f2700, 8192, 528, 10, }, + { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */ - { "at45db321d", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, + { "AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, { "at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS}, - { "at45db641d", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, - { "at45db641d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, + { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, + { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, }; static struct flash_info *__devinit jedec_probe(struct spi_device *spi) @@ -588,17 +581,23 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) struct flash_info *info; int status; - /* JEDEC also defines an optional "extended device information" * string for after vendor-specific data, after the three bytes * we use here. Supporting some chips might require using it. + * + * If the vendor ID isn't Atmel's (0x1f), assume this call failed. + * That's not an error; only rev C and newer chips handle it, and + * only Atmel sells these chips. */ tmp = spi_write_then_read(spi, &code, 1, id, 3); if (tmp < 0) { DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", spi->dev.bus_id, tmp); - return NULL; + return ERR_PTR(tmp); } + if (id[0] != 0x1f) + return NULL; + jedec = id[0]; jedec = jedec << 8; jedec |= id[1]; @@ -609,19 +608,53 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) tmp < ARRAY_SIZE(dataflash_data); tmp++, info++) { if (info->jedec_id == jedec) { + DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n", + dev_name(&spi->dev), + (info->flags & SUP_POW2PS) + ? ", binary pagesize" : "" + ); if (info->flags & SUP_POW2PS) { status = dataflash_status(spi); - if (status & 0x1) - /* return power of 2 pagesize */ - return ++info; - else - return info; + if (status < 0) { + DEBUG(MTD_DEBUG_LEVEL1, + "%s: status error %d\n", + dev_name(&spi->dev), status); + return ERR_PTR(status); + } + if (status & 0x1) { + if (info->flags & IS_POW2PS) + return info; + } else { + if (!(info->flags & IS_POW2PS)) + return info; + } } } } - return NULL; + + /* + * Treat other chips as errors ... we won't know the right page + * size (it might be binary) even when we can tell which density + * class is involved (legacy chip id scheme). + */ + dev_warn(&spi->dev, "JEDEC id %06x not handled\n", jedec); + return ERR_PTR(-ENODEV); } +/* + * Detect and initialize DataFlash device, using JEDEC IDs on newer chips + * or else the ID code embedded in the status bits: + * + * Device Density ID code #Pages PageSize Offset + * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 + * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1024 264 9 + * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 + * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 + * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 + * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 + * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 + * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 + */ static int __devinit dataflash_probe(struct spi_device *spi) { int status; @@ -632,14 +665,17 @@ static int __devinit dataflash_probe(struct spi_device *spi) * If it succeeds we know we have either a C or D part. * D will support power of 2 pagesize option. */ - info = jedec_probe(spi); - + if (IS_ERR(info)) + return PTR_ERR(info); if (info != NULL) return add_dataflash(spi, info->name, info->nr_pages, info->pagesize, info->pageoffset); - + /* + * Older chips support only legacy commands, identifing + * capacity using bits in the status byte. + */ status = dataflash_status(spi); if (status <= 0 || status == 0xff) { DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", @@ -661,13 +697,13 @@ static int __devinit dataflash_probe(struct spi_device *spi) status = add_dataflash(spi, "AT45DB021B", 1024, 264, 9); break; case 0x1c: /* 0 1 1 1 x x */ - status = add_dataflash(spi, "AT45DB041B", 2048, 264, 9); + status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9); break; case 0x24: /* 1 0 0 1 x x */ status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9); break; case 0x2c: /* 1 0 1 1 x x */ - status = add_dataflash(spi, "AT45DB161B", 4096, 528, 10); + status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10); break; case 0x34: /* 1 1 0 1 x x */ status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10); -- cgit v1.2.3-58-ga151 From 4a22442faeb33bdf34016a7b1f6b3d6ecd4e33e5 Mon Sep 17 00:00:00 2001 From: Jerry Hicks Date: Wed, 30 Jul 2008 12:49:59 -0700 Subject: [MTD] [NOR] drivers/mtd/chips/jedec_probe.c: fix Am29DL800BB device ID The device id for Am29DL800BB in jedec_probe.c is wrong. Reference: http://www.spansion.com/datasheets/21519c4.pdf I discovered this while working with u-boot. The u-boot folks mentioned Linux as an upstream reference, thought I'd post a heads-up here too. Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/chips/jedec_probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index dbba5abf0db8..f84ab6182148 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -41,7 +41,7 @@ /* AMD */ -#define AM29DL800BB 0x22C8 +#define AM29DL800BB 0x22CB #define AM29DL800BT 0x224A #define AM29F800BB 0x2258 -- cgit v1.2.3-58-ga151 From fc1f397b2c7ef1c9bad58778e4041dfabf20c71c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 30 Jul 2008 12:34:56 -0700 Subject: [MTD] [NAND] drivers/mtd/nand/nandsim.c needs div64.h drivers/mtd/nand/nandsim.c: In function 'divide': drivers/mtd/nand/nandsim.c:462: error: implicit declaration of function 'do_div' Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/nandsim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 7428a6c1135e..5d08514f553c 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-58-ga151 From 963724462a11668185dc67879ea8fe7590973322 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 30 Jul 2008 12:34:57 -0700 Subject: [MTD] [NAND] diskonchip.c fix sparse endian warnings Signed-off-by: Harvey Harrison Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/diskonchip.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 765d4f0f7c86..e4226e02d63e 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1125,9 +1125,9 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio 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); + le16_to_cpus(&mh->NumEraseUnits); + le16_to_cpus(&mh->FirstPhysicalEUN); + le32_to_cpus(&mh->FormattedSize); printk(KERN_INFO " DataOrgID = %s\n" " NumEraseUnits = %d\n" @@ -1235,12 +1235,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); mh = (struct INFTLMediaHeader *)buf; - mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); - mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); - mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions); - mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); - mh->FormatFlags = le32_to_cpu(mh->FormatFlags); - mh->PercentUsed = le32_to_cpu(mh->PercentUsed); + le32_to_cpus(&mh->NoOfBootImageBlocks); + le32_to_cpus(&mh->NoOfBinaryPartitions); + le32_to_cpus(&mh->NoOfBDTLPartitions); + le32_to_cpus(&mh->BlockMultiplierBits); + le32_to_cpus(&mh->FormatFlags); + le32_to_cpus(&mh->PercentUsed); printk(KERN_INFO " bootRecordID = %s\n" " NoOfBootImageBlocks = %d\n" @@ -1277,12 +1277,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti /* Scan the partitions */ for (i = 0; (i < 4); i++) { ip = &(mh->Partitions[i]); - ip->virtualUnits = le32_to_cpu(ip->virtualUnits); - ip->firstUnit = le32_to_cpu(ip->firstUnit); - ip->lastUnit = le32_to_cpu(ip->lastUnit); - ip->flags = le32_to_cpu(ip->flags); - ip->spareUnits = le32_to_cpu(ip->spareUnits); - ip->Reserved0 = le32_to_cpu(ip->Reserved0); + le32_to_cpus(&ip->virtualUnits); + le32_to_cpus(&ip->firstUnit); + le32_to_cpus(&ip->lastUnit); + le32_to_cpus(&ip->flags); + le32_to_cpus(&ip->spareUnits); + le32_to_cpus(&ip->Reserved0); printk(KERN_INFO " PARTITION[%d] ->\n" " virtualUnits = %d\n" -- cgit v1.2.3-58-ga151 From e274f025e2caaadc1a6dd41adc9c9a19be075110 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 30 Jul 2008 12:34:59 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: fix bug - do not clobber the status from the first 256 bytes if operating on 512 pages Singed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/bf5xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index e87a57297328..3254348f8581 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -273,7 +273,7 @@ static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, dat += 256; read_ecc += 8; calc_ecc += 8; - ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); + ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); } return ret; -- cgit v1.2.3-58-ga151 From cf840392e83914b9fcdbce8a8a2bc17a84cf0353 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 30 Jul 2008 12:35:00 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: fix bug - hw ecc calc by making sure we extract 11 bits from each register instead of 10 Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/bf5xx_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 3254348f8581..fc58afe4733a 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -298,7 +298,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, ecc0 = bfin_read_NFC_ECC0(); ecc1 = bfin_read_NFC_ECC1(); - code[0] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11); + code[0] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); @@ -310,7 +310,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, if (page_size == 512) { ecc0 = bfin_read_NFC_ECC2(); ecc1 = bfin_read_NFC_ECC3(); - code[1] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11); + code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); /* second 3 bytes in ecc_code for second 256 * bytes of 512 page size -- cgit v1.2.3-58-ga151 From fcb90ba7e9ba9a17ca5103be3f3ae3a446dadc14 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 30 Jul 2008 12:35:01 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: add support for the ECC layout the Blackfin bootrom uses Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/Kconfig | 12 ++++++++++++ drivers/mtd/nand/bf5xx_nand.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 71406e517857..c075b47e11ad 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -109,6 +109,18 @@ config MTD_NAND_BF5XX_HWECC Enable the use of the BF5XX's internal ECC generator when using NAND. +config MTD_NAND_BF5XX_BOOTROM_ECC + bool "Use Blackfin BootROM ECC Layout" + default n + depends on MTD_NAND_BF5XX_HWECC + help + If you wish to modify NAND pages and allow the Blackfin on-chip + BootROM to boot from them, say Y here. This is only necessary + if you are booting U-Boot out of NAND and you wish to update + U-Boot from Linux' userspace. Otherwise, you should say N here. + + If unsure, say N. + config MTD_NAND_RTC_FROM4 tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)" depends on SH_SOLUTION_ENGINE diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index fc58afe4733a..3555f6b3ebe0 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -91,6 +91,41 @@ static const unsigned short bfin_nfc_pin_req[] = P_NAND_ALE, 0}; +#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC +static uint8_t bbt_pattern[] = { 0xff }; + +static struct nand_bbt_descr bootrom_bbt = { + .options = 0, + .offs = 63, + .len = 1, + .pattern = bbt_pattern, +}; + +static struct nand_ecclayout bootrom_ecclayout = { + .eccbytes = 24, + .eccpos = { + 0x8 * 0, 0x8 * 0 + 1, 0x8 * 0 + 2, + 0x8 * 1, 0x8 * 1 + 1, 0x8 * 1 + 2, + 0x8 * 2, 0x8 * 2 + 1, 0x8 * 2 + 2, + 0x8 * 3, 0x8 * 3 + 1, 0x8 * 3 + 2, + 0x8 * 4, 0x8 * 4 + 1, 0x8 * 4 + 2, + 0x8 * 5, 0x8 * 5 + 1, 0x8 * 5 + 2, + 0x8 * 6, 0x8 * 6 + 1, 0x8 * 6 + 2, + 0x8 * 7, 0x8 * 7 + 1, 0x8 * 7 + 2 + }, + .oobfree = { + { 0x8 * 0 + 3, 5 }, + { 0x8 * 1 + 3, 5 }, + { 0x8 * 2 + 3, 5 }, + { 0x8 * 3 + 3, 5 }, + { 0x8 * 4 + 3, 5 }, + { 0x8 * 5 + 3, 5 }, + { 0x8 * 6 + 3, 5 }, + { 0x8 * 7 + 3, 5 }, + } +}; +#endif + /* * Data structures for bf5xx nand flash controller driver */ @@ -712,6 +747,11 @@ static int bf5xx_nand_probe(struct platform_device *pdev) /* setup hardware ECC data struct */ if (hardware_ecc) { +#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC + chip->badblock_pattern = &bootrom_bbt; + chip->ecc.layout = &bootrom_ecclayout; +#endif + if (plat->page_size == NFC_PG_SIZE_256) { chip->ecc.bytes = 3; chip->ecc.size = 256; -- cgit v1.2.3-58-ga151 From 2445af3853928bf3ee7960e09f548a1b07924091 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 30 Jul 2008 12:35:02 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: add proper devinit/devexit markings to probe/remove functions Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/bf5xx_nand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 3555f6b3ebe0..e259a7b75b2d 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -640,7 +640,7 @@ static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info) #endif } -static int bf5xx_nand_remove(struct platform_device *pdev) +static int __devexit bf5xx_nand_remove(struct platform_device *pdev) { struct bf5xx_nand_info *info = to_nand_info(pdev); struct mtd_info *mtd = NULL; @@ -673,7 +673,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev) * it can allocate all necessary resources then calls the * nand layer to look for devices */ -static int bf5xx_nand_probe(struct platform_device *pdev) +static int __devinit bf5xx_nand_probe(struct platform_device *pdev) { struct bf5xx_nand_platform *plat = to_nand_plat(pdev); struct bf5xx_nand_info *info = NULL; @@ -815,7 +815,7 @@ static int bf5xx_nand_resume(struct platform_device *dev) /* driver device registration */ static struct platform_driver bf5xx_nand_driver = { .probe = bf5xx_nand_probe, - .remove = bf5xx_nand_remove, + .remove = __devexit_p(bf5xx_nand_remove), .suspend = bf5xx_nand_suspend, .resume = bf5xx_nand_resume, .driver = { -- cgit v1.2.3-58-ga151 From a0dd20184becf5c90996d9ee0bb69426fe63581a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 30 Jul 2008 12:35:02 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: enable Blackfin nand HWECC support by default Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c075b47e11ad..02f9cc30d77b 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -104,6 +104,7 @@ config MTD_NAND_BF5XX config MTD_NAND_BF5XX_HWECC bool "BF5XX NAND Hardware ECC" + default y depends on MTD_NAND_BF5XX help Enable the use of the BF5XX's internal ECC generator when -- cgit v1.2.3-58-ga151 From 0ee002b041cb45ab3cc5384b86271d41ccf90fe1 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 30 Jul 2008 12:35:03 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: use standard dev_err() rather than printk() Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/bf5xx_nand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index e259a7b75b2d..6cf7fb86c256 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -684,8 +684,7 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "(%p)\n", pdev); if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) { - printk(KERN_ERR DRV_NAME - ": Requesting Peripherals failed\n"); + dev_err(&pdev->dev, "requesting Peripherals failed\n"); return -EFAULT; } -- cgit v1.2.3-58-ga151 From 4f0ca70e52b67f41287d853f0d572dafa875e485 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 30 Jul 2008 12:35:04 -0700 Subject: [MTD] [NAND] Blackfin NFC Driver: Cleanup the error exit path of bf5xx_nand_probe function Signed-off-by: Bryan Wu Cc: Mike Frysinger Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/bf5xx_nand.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 6cf7fb86c256..9af2a2cc1153 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -549,7 +549,6 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, /* * System initialization functions */ - static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) { int ret; @@ -582,6 +581,13 @@ static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) return 0; } +static void bf5xx_nand_dma_remove(struct bf5xx_nand_info *info) +{ + /* Free NFC DMA channel */ + if (hardware_ecc) + free_dma(CH_NFC); +} + /* * BF5XX NFC hardware initialization * - pin mux setup @@ -658,6 +664,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) } peripheral_free_list(bfin_nfc_pin_req); + bf5xx_nand_dma_remove(info); /* free the common resources */ kfree(info); @@ -683,21 +690,21 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "(%p)\n", pdev); + if (!plat) { + dev_err(&pdev->dev, "no platform specific information\n"); + return -EINVAL; + } + if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) { dev_err(&pdev->dev, "requesting Peripherals failed\n"); return -EFAULT; } - if (!plat) { - dev_err(&pdev->dev, "no platform specific information\n"); - goto exit_error; - } - info = kzalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { dev_err(&pdev->dev, "no memory for flash info\n"); err = -ENOMEM; - goto exit_error; + goto out_err_kzalloc; } platform_set_drvdata(pdev, info); @@ -741,8 +748,8 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) /* initialise the hardware */ err = bf5xx_nand_hw_init(info); - if (err != 0) - goto exit_error; + if (err) + goto out_err_hw_init; /* setup hardware ECC data struct */ if (hardware_ecc) { @@ -772,7 +779,7 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) /* scan hardware nand chip and setup mtd info data struct */ if (nand_scan(mtd, 1)) { err = -ENXIO; - goto exit_error; + goto out_err_nand_scan; } /* add NAND partition */ @@ -781,11 +788,14 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "initialised ok\n"); return 0; -exit_error: - bf5xx_nand_remove(pdev); +out_err_nand_scan: + bf5xx_nand_dma_remove(info); +out_err_hw_init: + platform_set_drvdata(pdev, NULL); + kfree(info); +out_err_kzalloc: + peripheral_free_list(bfin_nfc_pin_req); - if (err == 0) - err = -EINVAL; return err; } -- cgit v1.2.3-58-ga151 From e4c094a595ba8ea402e6b2153f7bbf6ef039eea0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 30 Jul 2008 12:35:04 -0700 Subject: [MTD] [NAND] drivers/mtd/nand/nandsim.c: fix printk warnings Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/nandsim.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 5d08514f553c..556e8131ecdc 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -586,7 +586,8 @@ static int init_nandsim(struct mtd_info *mtd) if (ns->busw == 16) NS_WARN("16-bit flashes support wasn't tested\n"); - printk("flash size: %llu MiB\n", ns->geom.totsz >> 20); + printk("flash size: %llu MiB\n", + (unsigned long long)ns->geom.totsz >> 20); printk("page size: %u bytes\n", ns->geom.pgsz); printk("OOB area size: %u bytes\n", ns->geom.oobsz); printk("sector size: %u KiB\n", ns->geom.secsz >> 10); @@ -595,8 +596,9 @@ static int init_nandsim(struct mtd_info *mtd) printk("bus width: %u\n", ns->busw); printk("bits in sector size: %u\n", ns->geom.secshift); printk("bits in page size: %u\n", ns->geom.pgshift); - printk("bits in OOB size: %u\n", ns->geom.oobshift); - printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10); + printk("bits in OOB size: %u\n", ns->geom.oobshift); + printk("flash size with OOB: %llu KiB\n", + (unsigned long long)ns->geom.totszoob >> 10); printk("page address bytes: %u\n", ns->geom.pgaddrbytes); printk("sector address bytes: %u\n", ns->geom.secaddrbytes); printk("options: %#x\n", ns->options); -- cgit v1.2.3-58-ga151