From: "Wagner, Helge (GE Intelligent Platforms)" <[email protected]>

-Fixed spi_block_erase_d8() block size for MX25L3205 was wrong.
-Now using spi_block_erase_20_4or64k() erase function instead of
spi_block_erase_20() which can handle both 4KB and 64KB block sizes for
those flash chips that might have same id but different erase block
sizes.
-New probe function added (probe_spi_mx_2017()) to differentiate
MX25L6445E and MX25L6405.

Signed-off-by: Helge Wagner <[email protected]>
Signed-off-by: Stefan Tauner <[email protected]>
---
White space errors removed, rebased to work with flashctx.
No further changes iirc, although i spotted various things that should
be changed before merging it.

 chipdrivers.h |    2 +
 flashchips.c  |   52 ++++++++++++++++----
 flashchips.h  |    1 +
 spi.h         |   15 ++++++
 spi25.c       |  147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 208 insertions(+), 9 deletions(-)

diff --git a/chipdrivers.h b/chipdrivers.h
index 0c78b0d..62806f9 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -33,9 +33,11 @@ int probe_spi_rdid4(struct flashctx *flash);
 int probe_spi_rems(struct flashctx *flash);
 int probe_spi_res1(struct flashctx *flash);
 int probe_spi_res2(struct flashctx *flash);
+int probe_spi_mx_2017(struct flashctx *flash);
 int spi_write_enable(struct flashctx *flash);
 int spi_write_disable(struct flashctx *flash);
 int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int 
blocklen);
+int spi_block_erase_20_4or64k(struct flashctx *flash, unsigned int addr, 
unsigned int blocklen);
 int spi_block_erase_52(struct flashctx *flash, unsigned int addr, unsigned int 
blocklen);
 int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int 
blocklen);
 int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int 
blocklen);
diff --git a/flashchips.c b/flashchips.c
index 789f17f..19d5163 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -4751,14 +4751,14 @@ const struct flashchip flashchips[] = {
                .total_size     = 2048,
                .page_size      = 256,
                .feature_bits   = FEATURE_WRSR_WREN,
-               .tested         = TEST_OK_PREW,
+               .tested         = TEST_OK_PRW,
                .probe          = probe_spi_rdid,
                .probe_timing   = TIMING_ZERO,
                .block_erasers  =
                {
                        {
-                               .eraseblocks = { {4 * 1024, 512} },
-                               .block_erase = spi_block_erase_20,      /* This 
erase function has 64k blocksize for eLiteFlash */
+                               .eraseblocks = { {64 * 1024, 32} },
+                               .block_erase = spi_block_erase_20_4or64k,       
/* This erase function has 64k blocksize for eLiteFlash */
                        }, {
                                .eraseblocks = { {64 * 1024, 32} },     /* Not 
supported in MX25L1605 (eLiteFlash) and MX25L1605D */
                                .block_erase = spi_block_erase_52,
@@ -4856,16 +4856,16 @@ const struct flashchip flashchips[] = {
                .total_size     = 4096,
                .page_size      = 256,
                .feature_bits   = FEATURE_WRSR_WREN,
-               .tested         = TEST_OK_PREW,
+               .tested         = TEST_OK_PRW,
                .probe          = probe_spi_rdid,
                .probe_timing   = TIMING_ZERO,
                .block_erasers  =
                {
                        {
-                               .eraseblocks = { {4 * 1024, 1024} },
-                               .block_erase = spi_block_erase_20,
+                               .eraseblocks = { {64 * 1024, 64} },
+                               .block_erase = spi_block_erase_20_4or64k,
                        }, {
-                               .eraseblocks = { {4 * 1024, 1024} },
+                               .eraseblocks = { {64 * 1024, 64} },
                                .block_erase = spi_block_erase_d8,
                        }, {
                                .eraseblocks = { {4 * 1024 * 1024, 1} },
@@ -4924,13 +4924,47 @@ const struct flashchip flashchips[] = {
                .total_size     = 8192,
                .page_size      = 256,
                .feature_bits   = FEATURE_WRSR_WREN,
-               .tested         = TEST_OK_PREW,
-               .probe          = probe_spi_rdid,
+               .tested         = TEST_OK_PROBE,
+               .probe          = probe_spi_mx_2017,
                .probe_timing   = TIMING_ZERO,
                .block_erasers  =
                {
                        {
                                .eraseblocks = { {64 * 1024, 128} },
+                               .block_erase = spi_block_erase_20_4or64k,
+                       }, {
+                               .eraseblocks = { {64 * 1024, 128} },
+                               .block_erase = spi_block_erase_d8,
+                       }, {
+                               .eraseblocks = { {8 * 1024 * 1024, 1} },
+                               .block_erase = spi_block_erase_60,
+                       }, {
+                               .eraseblocks = { {8 * 1024 * 1024, 1} },
+                               .block_erase = spi_block_erase_c7,
+                       }
+               },
+               .unlock         = spi_disable_blockprotect,
+               .write          = spi_chip_write_256,
+               .read           = spi_chip_read,
+               .voltage        = {2700, 3600},
+       },
+
+       {
+               .vendor         = "Macronix",
+               .name           = "MX25L6445E",
+               .bustype        = BUS_SPI,
+               .manufacture_id = MACRONIX_ID,
+               .model_id       = MACRONIX_MX25L6445E,
+               .total_size     = 8192,
+               .page_size      = 256,
+               .feature_bits   = FEATURE_WRSR_WREN,
+               .tested         = TEST_OK_PREW,
+               .probe          = probe_spi_mx_2017,
+               .probe_timing   = TIMING_ZERO,
+               .block_erasers  =
+               {
+                       {
+                               .eraseblocks = { {4 * 1024, 2048} },
                                .block_erase = spi_block_erase_20,
                        }, {
                                .eraseblocks = { {64 * 1024, 128} },
diff --git a/flashchips.h b/flashchips.h
index 0fe2cc4..bfbbacd 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -383,6 +383,7 @@
 #define MACRONIX_MX25L1605     0x2015  /* MX25L1605{,A,D} */
 #define MACRONIX_MX25L3205     0x2016  /* MX25L3205{,A} */
 #define MACRONIX_MX25L6405     0x2017  /* MX25L6405{,D}, MX25L6406E, 
MX25L6436E */
+#define MACRONIX_MX25L6445E    0x16    /* MX25L6445E, MX25L6405D ID = REMS2 
answer */
 #define MACRONIX_MX25L12805    0x2018  /* MX25L12805 */
 #define MACRONIX_MX25L1635D    0x2415
 #define MACRONIX_MX25L1635E    0x2515  /* MX25L1635{E} */
diff --git a/spi.h b/spi.h
index a57f1b6..8a2c246 100644
--- a/spi.h
+++ b/spi.h
@@ -45,6 +45,21 @@
 #define JEDEC_SFDP_OUTSIZE     0x05    /* 8b op, 24b addr, 8b dummy */
 /*      JEDEC_SFDP_INSIZE : any length */
 
+/* Read Electronic Manufacturer Signature for 2x I/O mode */
+#define JEDEC_REMS2            0xef
+#define JEDEC_REMS2_OUTSIZE    0x04
+#define JEDEC_REMS2_INSIZE     0x02
+
+/* Read Electronic Manufacturer Signature for 4x I/O mode */
+#define JEDEC_REMS4            0xdf
+#define JEDEC_REMS4_OUTSIZE    0x04
+#define JEDEC_REMS4_INSIZE     0x02
+
+/* Read Electronic Manufacturer Signature for 4x I/O DT mode */
+#define JEDEC_REMS4D           0xcf
+#define JEDEC_REMS4D_OUTSIZE   0x04
+#define JEDEC_REMS4D_INSIZE    0x02
+
 /* Read Electronic Signature */
 #define JEDEC_RES              0xab
 #define JEDEC_RES_OUTSIZE      0x04
diff --git a/spi25.c b/spi25.c
index 900df9c..a3ae8f5 100644
--- a/spi25.c
+++ b/spi25.c
@@ -22,6 +22,7 @@
  * Contains the common SPI chip driver functions
  */
 
+#include <stdlib.h>
 #include <string.h>
 #include "flash.h"
 #include "flashchips.h"
@@ -68,6 +69,27 @@ static int spi_rems(struct flashctx *flash, unsigned char 
*readarr)
        return 0;
 }
 
+static int spi_rems2(struct flashctx *flash, unsigned char *readarr)
+{
+       unsigned char cmd[JEDEC_REMS2_OUTSIZE] = { JEDEC_REMS2, 0, 0, 0 };
+       uint32_t readaddr;
+       int ret;
+
+       ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS2_INSIZE, cmd, 
readarr);
+       if (ret == SPI_INVALID_ADDRESS) {
+               /* Find the lowest even address allowed for reads. */
+               readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
+               cmd[1] = (readaddr >> 16) & 0xff,
+               cmd[2] = (readaddr >> 8) & 0xff,
+               cmd[3] = (readaddr >> 0) & 0xff,
+               ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS2_INSIZE, 
cmd, readarr);
+       }
+       if (ret)
+               return ret;
+       msg_cspew("REMS2 returned %02x %02x. ", readarr[0], readarr[1]);
+       return 0;
+}
+
 static int spi_res(struct flashctx *flash, unsigned char *readarr, int bytes)
 {
        unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
@@ -174,6 +196,58 @@ int probe_spi_rdid(struct flashctx *flash)
        return probe_spi_rdid_generic(flash, 3);
 }
 
+int probe_spi_mx_2017(struct flashctx *flash)
+{
+       unsigned char readarr[4];
+       uint32_t id1;
+       uint32_t id2;
+       uint32_t id3;
+       uint32_t id4;
+
+       if (spi_rdid(flash, readarr, 3)) {
+               msg_cdbg("\n");
+               return 0;
+       }
+       id1 = readarr[0];
+       id2 = (readarr[1] << 8) | readarr[2];
+
+       if (id1 == MACRONIX_ID && id2 == MACRONIX_MX25L6405) {
+       /* Now we have detected the 2017h class of Macronix flash devices.
+        * We can further differentiate two classes:
+        * -those who support the REMS2 function do always have 4KB sector size
+        *  (at least i have not found one with 64KB yet),
+        * and
+        * -those who don't support the REMS2 function might have 4KB or 64KB
+        *  (some have 4KB, e.g. MX25L6406E, some have 64KB, e.g. MX25L6405 
(not D))
+        *  for erase function 20h.
+        */
+               if (spi_rems2(flash, readarr)) {
+                       msg_cdbg("\n");
+                       return 0;
+               }
+               id3 = readarr[0];
+               id4 = readarr[1];
+               msg_cdbg("%s: id1 0x%02x, id2 0x%02x, id3 0x%02x, id4 
0x%02x\n", __func__, id1, id2, id3, id4);
+               if (id3 == MACRONIX_ID && id4 == MACRONIX_MX25L6445E) {
+               /* MACRONIX_MX25L6445E class, always 4KB sector */
+                       if (flash->model_id == MACRONIX_MX25L6445E)
+                               return 1;
+                       else
+                               return 0;
+               } else {
+               /* MACRONIX_MX25L6405 class, might have 4KB or 64KB sector */
+                       if (flash->model_id == MACRONIX_MX25L6405)
+                               return 1;
+                       else
+                               return 0;
+               }
+       } else {
+               msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
+       }
+       /* neither MACRONIX_MX25L6405 nor MACRONIX_MX25L6445E */
+       return 0;
+}
+
 int probe_spi_rdid4(struct flashctx *flash)
 {
        /* Some SPI controllers do not support commands with writecnt=1 and
@@ -701,6 +775,79 @@ int spi_block_erase_20(struct flashctx *flash, unsigned 
int addr,
        return 0;
 }
 
+/* Sector size might be 4KB or 64KB, but on call to this function this is 
unknown.
+ * So we do a first erase command and then check if mem in the complete 64KB 
sector is erased.
+ * If not we assume 4KB and so we repeat the erase for each 4KB sector in the 
64KB block
+ * (which is not erased already).
+ * PLEASE NOTE: the .eraseblocks block size must be set to 64KB if you use 
this function.
+ */
+int spi_block_erase_20_4or64k(struct flashctx *flash, unsigned int addr, 
unsigned int blocklen)
+{
+       int result, i, j, fully_erased, sector_erased;
+       unsigned int curraddr, currblocklen;
+       uint8_t *readbuf;
+
+       if (blocklen != (64 * 1024)) {
+               msg_gerr("%s: blocklen not 64KB! Please report a bug at "
+                        "[email protected]\n", __func__);
+               return 1;
+       }
+
+       readbuf = malloc(blocklen);
+       if (!readbuf) {
+               msg_gerr("Out of memory!\n");
+               exit(1);
+       }
+
+       for (i = 0; i < 16; i++) {      /* there are 16 4KB sectors in 64KB */
+
+               curraddr = addr + (i * (4 * 1024));
+
+               if (i > 0) {
+                       /* Skip the sector erase if the sector is already 
erased */
+                       sector_erased = 1;
+                       result = flash->read(flash, readbuf, curraddr, (4 * 
1024));
+                       if (result) {
+                               msg_gerr("Erase impossible because read failed "
+                                        "at 0x%x (len 0x%x)\n", curraddr, (4 * 
1024));
+                               break;
+                       }
+                       for (j = 0; j < currblocklen; j++)
+                               if (readbuf[j] != 0xFF)
+                                       sector_erased = 0;
+                       if (sector_erased)
+                               continue;       /* Sector is already erased */
+               }
+
+               result = spi_block_erase_20 (flash, curraddr, (4 * 1024)); /* 
last parameter (blocklen) is unused */
+               if (result) break;
+
+               if (0 == i) {
+                       curraddr += 4 * 1024;
+                       currblocklen = (64*1024)-(4*1024);
+                       fully_erased = 1;
+                       result = flash->read(flash, readbuf, curraddr, 
currblocklen);
+                       if (result) {
+                               msg_gerr("Erase impossible because read failed "
+                                        "at 0x%x (len 0x%x)\n", curraddr, 
currblocklen);
+                               break;
+                       }
+                       for (j = 0; j < currblocklen; j++)
+                               if (readbuf[j] != 0xFF)
+                                       fully_erased = 0;
+                       if (fully_erased) {
+                       /* This means either that the SE command has erased the 
full 64KB
+                        * or that the remaining 64KB sector was already erased 
before.
+                        * Anyhow, we can now exit without calling the SE 
command again.
+                        */
+                               break;
+                       }
+               }
+        }
+       free(readbuf);
+        return result;
+}
+
 int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
                       unsigned int blocklen)
 {
-- 
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to