From bf68eec871054ac32ad25ac917916e83d2c33a5f Mon Sep 17 00:00:00 2001
From: Benoit Rat <benoit@sevensols.com>
Date: Fri, 3 Oct 2014 09:49:06 +0200
Subject: [PATCH] Read EDI bytes in JEDEC to support AT45DB641E

Standard JEDEC ID is only 24bits to identify a DF chip.

It also has an optional Extended Device Info (EDI) on bytes 4 and/or 5
that need to be read in order differentiate some DF chips. (i.e, the
difference between AT45DB641E and AT45DB642D is made by byte 4).

We have had two new fields in the struct flash_info:
- edi_nbytes: number of optional bytes to read (1 or 2)
- edi_jedec:  EDI value for a given chip
---
 drivers/mtd/devices/mtd_dataflash.c | 56 +++++++++++++++++++++++++------------
 1 file changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index cdc0120..3de8ac0 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -675,6 +675,11 @@ struct flash_info {
	uint16_t	pageoffset;

	uint16_t	flags;
+	/* JEDEC has an optional Extended Device Info (EDI) on bytes
+	 * 4 and/or 5 that need to be read to differentiate some DF chips
+	 */
+	uint8_t		edi_nbytes;
+	uint16_t	edi_jedec;
 #define SUP_POW2PS	0x0002		/* supports 2^N byte pages */
 #define IS_POW2PS	0x0001		/* uses 2^N byte pages */
 };
@@ -690,36 +695,40 @@ static struct flash_info dataflash_data [] = {
	 * 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},
+	{ "AT45DB011B",  0x1f2200, 512, 264, 9, SUP_POW2PS, 0, 0x0},
+	{ "at45db011d",  0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS, 0, 0x0},

-	{ "AT45DB021B",  0x1f2300, 1024, 264, 9, SUP_POW2PS},
-	{ "at45db021d",  0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS},
+	{ "AT45DB021B",  0x1f2300, 1024, 264, 9, SUP_POW2PS, 0, 0x0},
+	{ "at45db021d",  0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS, 0, 0x0},

-	{ "AT45DB041x",  0x1f2400, 2048, 264, 9, SUP_POW2PS},
-	{ "at45db041d",  0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS},
+	{ "AT45DB041x",  0x1f2400, 2048, 264, 9, SUP_POW2PS, 0, 0x0},
+	{ "at45db041d",  0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS, 0, 0x0},

-	{ "AT45DB081B",  0x1f2500, 4096, 264, 9, SUP_POW2PS},
-	{ "at45db081d",  0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS},
+	{ "AT45DB081B",  0x1f2500, 4096, 264, 9, SUP_POW2PS, 0, 0x0},
+	{ "at45db081d",  0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS, 0, 0x0},

-	{ "AT45DB161x",  0x1f2600, 4096, 528, 10, SUP_POW2PS},
-	{ "at45db161d",  0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS},
+	{ "AT45DB161x",  0x1f2600, 4096, 528, 10, SUP_POW2PS, 0, 0x0},
+	{ "at45db161d",  0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS, 0, 0x0},

-	{ "AT45DB321x",  0x1f2700, 8192, 528, 10, 0},		/* rev C */
+	{ "AT45DB321x",  0x1f2700, 8192, 528, 10, 0, 0, 0x0},		/* rev C */

-	{ "AT45DB321x",  0x1f2701, 8192, 528, 10, SUP_POW2PS},
-	{ "at45db321d",  0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS},
+	{ "AT45DB321x",  0x1f2701, 8192, 528, 10, SUP_POW2PS, 0, 0x0},
+	{ "at45db321d",  0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS, 0, 0x0},

-	{ "AT45DB642x",  0x1f2800, 8192, 1056, 11, SUP_POW2PS},
-	{ "at45db642d",  0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
+	{ "AT45DB642x",  0x1f2800, 8192, 1056, 11, SUP_POW2PS,1, 0x0},
+	{ "at45db642d",  0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS,1, 0x0},
+
+	{ "AT45DB641E",  0x1f2800, 32768, 264, 9, SUP_POW2PS,1, 0x1},
+	{ "at45db641e",  0x1f2800, 32768, 256, 8, SUP_POW2PS | IS_POW2PS,1, 0x1},
 };

 static struct flash_info * jedec_probe(struct spi_device *spi)
 {
	int			tmp;
	uint8_t			code = OP_READ_ID;
-	uint8_t			id[3];
+	uint8_t			id[5];
	uint32_t		jedec;
+	uint16_t		jedec_edi;
	struct flash_info	*info;
	int status;

@@ -731,7 +740,7 @@ static struct flash_info * jedec_probe(struct spi_device *spi)
	 * 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);
+	tmp = spi_write_then_read(spi, &code, 1, id, 5);
	if (tmp < 0) {
		pr_debug("%s: error %d reading JEDEC ID\n",
			dev_name(&spi->dev), tmp);
@@ -745,11 +754,17 @@ static struct flash_info * jedec_probe(struct spi_device *spi)
	jedec |= id[1];
	jedec = jedec << 8;
	jedec |= id[2];
+
+	//EDI bytes to support newest chips
+	jedec_edi = id[3];
+	jedec_edi = jedec_edi << 8;
+	jedec_edi |= id[4];

	for (tmp = 0, info = dataflash_data;
			tmp < ARRAY_SIZE(dataflash_data);
			tmp++, info++) {
-		if (info->jedec_id == jedec) {
+		if (info->jedec_id == jedec)
+		if (info->edi_jedec == (jedec_edi >> (16-8*info->edi_nbytes))) {
			pr_debug("%s: OTP, sector protect%s\n",
				dev_name(&spi->dev),
				(info->flags & SUP_POW2PS)
@@ -796,6 +811,7 @@ static struct flash_info * jedec_probe(struct spi_device *spi)
  *   AT45DB0321B 32Mbit  (4M)    xx1101xx (0x34)   8192    528     10
  *   AT45DB0642  64Mbit  (8M)    xx111xxx (0x3c)   8192   1056     11
  *   AT45DB1282  128Mbit (16M)   xx0100xx (0x10)  16384   1056     11
+ *   AT45DB0641E 64Mbit  (8M)    xx111xxx (0x3c)  32768    264      9
  */
 static int dataflash_probe(struct device_d *dev)
 {
@@ -811,6 +827,10 @@ static int dataflash_probe(struct device_d *dev)
	 * write procedures.
	 */
	info = jedec_probe(spi);
+
+	pr_debug("MTD: %s 0x%08x %d %d %d %x\n",
+	info->name,info->jedec_id,
+	info->nr_pages,info->pagesize,info->pageoffset,info->flags);
	if (IS_ERR(info))
		return PTR_ERR(info);
	if (info != NULL)
--
1.9.1
