Dear Sir:
Submitter Loren Chen Date 2012-04-26 21:40:01 Message ID chenhy88tw@hotmail.com Download mbox | patch Permalink /patch/????/ State New Headers show Comments Loren Chen - 2012-04-26 21:40:01
Hello All.
This patch simplifies add for Macronix MX25L6445E flash part chip support.
Signed-off-by: Loren Chen chenhy88tw@hotmail.com 5 file changed, 10 insertions(+), 0 deletions(-)
Patch
diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 0000000..9b9a828 --- /dev/null +++ b/Readme.txt @@ -0,0 +1,14 @@ +Purpose: To support Macronix MX25L6445E flash part chip build for DOS +Mosified engineer: Loren Chen +[TAG]: Loren_20120426 + +Modified files: +1. flashchip.c +2. flashchip.h +3. spi.h +4. spi25.c + +Signed-off-by: LorenChen Developer loren.chen@dfi.com.tw + +eMail: +chychen.chen@msa.hinet.net \ No newline at end of file diff --git a/chipdrivers.h b/chipdrivers.h index bd81098..c0ae6d7 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); //(Loren_20120426) 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); //(Loren_20120426) 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 b6296c5..1fbb458 100644 --- a/flashchips.c +++ b/flashchips.c @@ -4254,14 +4254,16 @@ const struct flashchip flashchips[] = { .total_size = 2048, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, + .tested = TEST_OK_PRW, //(Loren_20120426) .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 */ + //(Loren_20120426->>>) + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = spi_block_erase_20_4or64k, /* This erase function has 64k blocksize for eLiteFlash */ + //(Loren_20120426-<<<) }, { .eraseblocks = { {64 * 1024, 32} }, /* Not supported in MX25L1605 (eLiteFlash) and MX25L1605D */ .block_erase = spi_block_erase_52, @@ -4359,16 +4361,18 @@ const struct flashchip flashchips[] = { .total_size = 4096, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, + .tested = TEST_OK_PRW, //(Loren_20120426) .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + //(Loren_20120426->>>) + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = spi_block_erase_20_4or64k, + //(Loren_20120426-<<<) }, { - .eraseblocks = { {4 * 1024, 1024} }, + .eraseblocks = { {64 * 1024, 64} }, //(Loren_20120426) .block_erase = spi_block_erase_d8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, @@ -4427,13 +4431,49 @@ 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, //(Loren_20120426) .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, +//(Loren_20120426->>>) + .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} }, +//(Loren_20120426-<<<) .block_erase = spi_block_erase_20, }, { .eraseblocks = { {64 * 1024, 128} }, diff --git a/flashchips.h b/flashchips.h index de3c79d..7964b1c 100644 --- a/flashchips.h +++ b/flashchips.h @@ -367,7 +367,10 @@ #define MACRONIX_MX25L8005 0x2014 /* Same as MX25V8005 */ #define MACRONIX_MX25L1605 0x2015 /* MX25L1605{,A,D} */ #define MACRONIX_MX25L3205 0x2016 /* MX25L3205{,A} */ -#define MACRONIX_MX25L6405 0x2017 /* MX25L6405{,D}, MX25L6406E, MX25L6436E */ +//(Loren_20120426->>>) +#define MACRONIX_MX25L6405 0x2017 /* MX25L6405, MX25L6406E */ +#define MACRONIX_MX25L6445E 0x16 /* MX25L6445E, MX25L6405D ID = REMS2 answer */ +//(Loren_20120426-<<<) #define MACRONIX_MX25L12805 0x2018 /* MX25L12805 */ #define MACRONIX_MX25L1635D 0x2415 #define MACRONIX_MX25L1635E 0x2515 /* MX25L1635{E} */ diff --git a/internal.c b/internal.c index 479cbf7..b8dc1e6 100644 --- a/internal.c +++ b/internal.c @@ -292,6 +292,15 @@ int internal_init(void) "You have been warned.\n" "========================================================================\n");
+ //(Loren_20120426->>>) + msg_perr("Signed-off-by: LorenChen Developer chenhy88tw@hotmail.com\n" + "Build Date: 2012/04/26.\n" + "Thanks to Idwer Vollering [vidwer@gmail.com]\n" + "and the one on the Internet who provided this patch codes\n" + "and flashrom@flashrom.org.\n" + "========================================================================\n"); + //(Loren_20120426-<<<) + if (force_laptop || (not_a_laptop && (is_laptop == 2))) { msg_perr("Proceeding anyway because user forced us to.\n"); } else { diff --git a/spi.h b/spi.h index 5f07eae..a4b9c74 100644 --- a/spi.h +++ b/spi.h @@ -40,6 +40,23 @@ #define JEDEC_REMS_OUTSIZE 0x04 #define JEDEC_REMS_INSIZE 0x02
+//(Loren_20120426->>>) +/* 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 +//(Loren_20120426-<<<) + /* Read Serial Flash Discoverable Parameters (SFDP) */ #define JEDEC_SFDP 0x5a #define JEDEC_SFDP_OUTSIZE 0x05 /* 8b op, 24b addr, 8b dummy */ diff --git a/spi25.c b/spi25.c index b7e8189..147b7a0 100644 --- a/spi25.c +++ b/spi25.c @@ -22,6 +22,7 @@ * Contains the common SPI chip driver functions */
+#include <stdlib.h> //(Loren_20120426) #include <string.h> #include "flash.h" #include "flashchips.h" @@ -68,6 +69,29 @@ static int spi_rems(struct flashctx *flash, unsigned char *readarr) return 0; }
+//(Loren_20120426->>>) +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; +} +//(Loren_20120426-<<<) + 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 +198,60 @@ int probe_spi_rdid(struct flashctx *flash) return probe_spi_rdid_generic(flash, 3); }
+//(Loren_20120426->>>) +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; +} +//(Loren_20120426-<<<) + int probe_spi_rdid4(struct flashctx *flash) { /* Some SPI controllers do not support commands with writecnt=1 and @@ -698,6 +776,81 @@ int spi_block_erase_20(struct flashctx *flash, unsigned int addr, return 0; }
+//(Loren_20120426->>>) +/* 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 " + "flashrom@flashrom.org\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; +} +//(Loren_20120426-<<<) + int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen) {
HTH, Loren Chen