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