[U-Boot] [PATCH 5/5] sf: sf_dataflash: Update probing method of old chips which not support Device ID
Haikun Wang
haikun.wang at freescale.com
Thu Jul 2 11:12:52 CEST 2015
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 at 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 */
--
2.1.0.27.g96db324
More information about the U-Boot
mailing list