
Some old dataflash chips don't have device ID, we should identif them using bits in the flash status byte. Add a variable status_byte in struct flash_info, and assign correct value for above old chips. Add those chips to the supported flash chip table and identify them through the new variable status_byte.
Signed-off-by: Haikun Wang haikun.wang@freescale.com --- drivers/mtd/spi/sf_dataflash.c | 226 +++++++++++++++++++---------------------- 1 file changed, 107 insertions(+), 119 deletions(-)
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 648f3ca..cd8d908 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -67,11 +67,87 @@ #define OP_WRITE_SECURITY_REVC 0x9A #define OP_WRITE_SECURITY 0x9B /* revision D */
+#define ATMEL_VENDOR_ID 0x1f + struct dataflash { uint8_t command[16]; unsigned short page_offset; /* offset in flash address */ };
+struct flash_info { + char *name; + + /* + * 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 OP_ERASE_PAGE. */ + unsigned nr_pages; + uint16_t pagesize; + uint16_t pageoffset; + uint8_t status_byte; + + uint16_t flags; +#define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ +#define IS_POW2PS 0x0001 /* uses 2^N byte pages */ +}; + +static struct flash_info dataflash_data[] = { + /* + * 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. + * + * Those two entries have different name spelling format in order to + * show their difference obviously. + * The upper case refer to the chip isn't in normal 2^N bytes page-size + * mode. + * The lower case refer to the chip is in normal 2^N bytes page-size + * mode. + * + * These newer chips also support 128-byte security registers (with + * 64 bytes one-time-programmable) and software write-protection. + */ + { "AT45DB011B", 0x1f2200, 512, 264, 9, 0, SUP_POW2PS}, + { "at45db011d", 0x1f2200, 512, 256, 8, 0, SUP_POW2PS | IS_POW2PS}, + + { "AT45DB021B", 0x1f2300, 1024, 264, 9, 0, SUP_POW2PS}, + { "at45db021d", 0x1f2300, 1024, 256, 8, 0, SUP_POW2PS | IS_POW2PS}, + + { "AT45DB041x", 0x1f2400, 2048, 264, 9, 0, SUP_POW2PS}, + { "at45db041d", 0x1f2400, 2048, 256, 8, 0, SUP_POW2PS | IS_POW2PS}, + + { "AT45DB081B", 0x1f2500, 4096, 264, 9, 0, SUP_POW2PS}, + { "at45db081d", 0x1f2500, 4096, 256, 8, 0, SUP_POW2PS | IS_POW2PS}, + + { "AT45DB161x", 0x1f2600, 4096, 528, 10, 0, SUP_POW2PS}, + { "at45db161d", 0x1f2600, 4096, 512, 9, 0, SUP_POW2PS | IS_POW2PS}, + + /* rev C */ + { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0, 0}, + + { "AT45DB321x", 0x1f2701, 8192, 528, 10, 0, SUP_POW2PS}, + { "at45db321d", 0x1f2701, 8192, 512, 9, 0, SUP_POW2PS | IS_POW2PS}, + + { "AT45DB642x", 0x1f2800, 8192, 1056, 11, 0, SUP_POW2PS}, + { "at45db642d", 0x1f2800, 8192, 1024, 10, 0, SUP_POW2PS | IS_POW2PS}, + /* + * Older chips support only legacy commands, identifing + * capacity using bits in the status byte. + */ + { "AT45DB011B-NOID", 0, 512, 264, 9, 0x0c, 0}, + { "AT45DB021B-NOID", 0, 1024, 264, 9, 0x14, 0}, + { "AT45DB041x-NOID", 0, 2048, 264, 9, 0x1c, 0}, + { "AT45DB081B-NOID", 0, 4096, 264, 9, 0x24, 0}, + { "AT45DB161x-NOID", 0, 4096, 528, 10, 0x2c, 0}, + { "AT45DB321x-NOID", 0, 8192, 528, 10, 0x34, 0}, + { "AT45DB642x-NOID", 0, 8192, 1056, 11, 0x38, 0}, + { "AT45DB642x-NOID", 0, 8192, 1056, 11, 0x3c, 0}, +}; + /* * Return the status of the DataFlash device. */ @@ -452,67 +528,7 @@ static int add_dataflash(struct udevice *dev, char *name, int nr_pages, return 0; }
-struct flash_info { - char *name; - - /* - * 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 OP_ERASE_PAGE. */ - unsigned nr_pages; - uint16_t pagesize; - uint16_t pageoffset; - - uint16_t flags; -#define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ -#define IS_POW2PS 0x0001 /* uses 2^N byte pages */ -}; - -static struct flash_info dataflash_data[] = { - /* - * 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. - * - * Those two entries have different name spelling format in order to - * show their difference obviously. - * The upper case refer to the chip isn't in normal 2^N bytes page-size - * mode. - * The lower case refer to the chip is in normal 2^N bytes page-size - * mode. - * - * 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}, - - { "AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, - { "at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, - { "at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, - { "at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, - { "at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */ - - { "AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, - { "at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, - { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, -}; - -static int jedec_probe(struct spi_slave *spi, u8 *id, +static int jedec_probe(struct spi_slave *spi, u8 *id, u8 status_byte, struct flash_info **pp_info) { int tmp; @@ -529,7 +545,7 @@ static int jedec_probe(struct spi_slave *spi, u8 *id, * That's not an error; only rev C and newer chips handle it, and * only Atmel sells these chips. */ - if (id[0] != 0x1f) + if (id[0] != ATMEL_VENDOR_ID && !status_byte) return -EINVAL;
jedec = id[0]; @@ -541,7 +557,7 @@ static int jedec_probe(struct spi_slave *spi, u8 *id, for (tmp = 0, info = dataflash_data; tmp < ARRAY_SIZE(dataflash_data); tmp++, info++) { - if (info->jedec_id == jedec) { + if (info->jedec_id && info->jedec_id == jedec) { if (info->flags & SUP_POW2PS) { status = dataflash_status(spi); if (status < 0) { @@ -564,6 +580,16 @@ static int jedec_probe(struct spi_slave *spi, u8 *id, *pp_info = info; return 0; } + } else if (!info->jedec_id && info->status_byte) { + /* + * if there's a device there, assume it's dataflash. + * board setup should have set spi->max_speed_max to + * match f(car) for continuous reads, mode 0 or 3. + */ + if (status_byte == info->status_byte) { + *pp_info = info; + return 0; + } } }
@@ -573,8 +599,8 @@ static int jedec_probe(struct spi_slave *spi, u8 *id, * class is involved (legacy chip id scheme). */ printf("SPI DataFlash: Unsupported flash IDs: "); - printf("manuf %02x, jedec %04x, ext_jedec %04x\n", - id[0], jedec, id[3] << 8 | id[4]); + printf("manuf %02x, jedec %04x, ext_jedec %04x, status_byte %02x\n", + id[0], jedec, id[3] << 8 | id[4], status_byte); return -EPROTONOSUPPORT; }
@@ -614,71 +640,33 @@ static int spi_dataflash_probe(struct udevice *dev) }
/* + * Older chips support only legacy commands, identifing + * capacity using bits in the status byte. + */ + status = dataflash_status(spi); + if (status <= 0 || status == 0xff) { + printf("SPI DataFlash: read status error %d\n", status); + if (status == 0 || status == 0xff) + status = -ENODEV; + goto err_read_cmd; + } + + /* * Try to detect dataflash by JEDEC ID. + * Otherwise try to detect by status. * If it succeeds we know we have either a C or D part. * D will support power of 2 pagesize option. * Both support the security register, though with different * write procedures. */ - ret = jedec_probe(spi, idcode, &info); + ret = jedec_probe(spi, idcode, (status & 0x3c), &info); if (!ret) add_dataflash(dev, info->name, info->nr_pages, info->pagesize, info->pageoffset, (info->flags & SUP_POW2PS) ? 'd' : 'c'); else { - /* - * Older chips support only legacy commands, identifing - * capacity using bits in the status byte. - */ - status = dataflash_status(spi); - if (status <= 0 || status == 0xff) { - printf("SPI DataFlash: read status error %d\n", status); - if (status == 0 || status == 0xff) - status = -ENODEV; - goto err_read_cmd; - } - /* - * if there's a device there, assume it's dataflash. - * board setup should have set spi->max_speed_max to - * match f(car) for continuous reads, mode 0 or 3. - */ - switch (status & 0x3c) { - case 0x0c: /* 0 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB011B", - 512, 264, 9, 0); - break; - case 0x14: /* 0 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB021B", - 1024, 264, 9, 0); - break; - case 0x1c: /* 0 1 1 1 x x */ - status = add_dataflash(dev, "AT45DB041x", - 2048, 264, 9, 0); - break; - case 0x24: /* 1 0 0 1 x x */ - status = add_dataflash(dev, "AT45DB081B", - 4096, 264, 9, 0); - break; - case 0x2c: /* 1 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB161x", - 4096, 528, 10, 0); - break; - case 0x34: /* 1 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB321x", - 8192, 528, 10, 0); - break; - case 0x38: /* 1 1 1 x x x */ - case 0x3c: - status = add_dataflash(dev, "AT45DB642x", - 8192, 1056, 11, 0); - break; - /* obsolete AT45DB1282 not (yet?) supported */ - default: - dev_info(&spi->dev, "unsupported device (%x)\n", - status & 0x3c); - status = -ENODEV; - goto err_read_cmd; - } + status = -ENODEV; + goto err_read_cmd; }
/* Assign spi data */