mtd: m25p80.c add support for non-JEDEC ID devices
hartleys
hartleys at visionengravers.com
Thu Jan 22 11:41:15 EST 2009
Add support to the m25p80 driver for non-JEDEC ID devices.
Some SPI flash chips do not support the "Read JEDEC ID" command and end
up returning all 0xff's. The following patch detects this and trys
probing the chip using the "Read Manufacture/Device ID" command.
This patch has been tested on an EP93xx based ARM platform with a
SST25LF020A 2Mbit SPI Serial Flash device.
Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
---
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 7c3fc76..0834a55 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -43,6 +43,7 @@
#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash
chip */
#define OPCODE_SE 0xd8 /* Sector erase (usually
64KiB) */
#define OPCODE_RDID 0x9f /* Read JEDEC ID */
+#define OPCODE_RDID_NON_JEDEC 0x90 /* Read non-JEDEC ID */
/* Status Register bits. */
#define SR_WIP 1 /* Write in progress */
@@ -546,12 +547,16 @@ static struct flash_info __devinitdata m25p_data
[] = {
{ "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, },
{ "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, },
{ "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, },
+
+ /* Non JEDEC ID SST -- large erase sizes are "overlays",
"sectors" are 4K */
+ { "sst25lf020a", 0xbf43, 0, 32 * 1024, 8, SECT_4K, },
+ { "sst25lf040a", 0xbf44, 0, 32 * 1024, 16, SECT_4K, },
};
static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
{
int tmp;
- u8 code = OPCODE_RDID;
+ u8 code[4];
u8 id[5];
u32 jedec;
u16 ext_jedec;
@@ -561,7 +566,8 @@ static struct flash_info *__devinit
jedec_probe(struct spi_device *spi)
* string for after vendor-specific data, after the three bytes
* we use here. Supporting some chips might require using it.
*/
- tmp = spi_write_then_read(spi, &code, 1, id, 5);
+ code[0] = OPCODE_RDID;
+ tmp = spi_write_then_read(spi, code, 1, id, 5);
if (tmp < 0) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC
ID\n",
dev_name(&spi->dev), tmp);
@@ -585,6 +591,31 @@ static struct flash_info *__devinit
jedec_probe(struct spi_device *spi)
}
}
dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
+
+ /* Try reading the non-JEDEC Manufacture/Device ID */
+ code[0] = OPCODE_RDID_NON_JEDEC;
+ code[1] = 0x00;
+ code[2] = 0x00;
+ code[3] = 0x00;
+ tmp = spi_write_then_read(spi, code, 4, id, 2);
+ if (tmp < 0) {
+ DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading ID\n",
+ spi->dev.bus_id, tmp);
+ return NULL;
+ }
+
+ jedec = id[0];
+ jedec = jedec << 8;
+ jedec |= id[1];
+
+ for (tmp = 0, info = m25p_data;
+ tmp < ARRAY_SIZE(m25p_data);
+ tmp++, info++) {
+ if (info->jedec_id == jedec)
+ return info;
+ }
+ dev_err(&spi->dev, "unrecognized id %04x\n", jedec);
+
return NULL;
}
More information about the linux-mtd
mailing list