From 0b9df97a84ce79217623e2bb32cf86458cdbb043 Mon Sep 17 00:00:00 2001 From: Stefan Tauner Date: Mon, 7 May 2012 22:12:16 +0000 Subject: dummyflasher.c: add support for SFDP by adding a new emulator chip: MX25L6436 The chip features a complete 1.0 SFDP JEDEC flash parameter table and also a vendor-specific extension table (defining voltages, lock bits etc). NB: the MX25L6436 uses the same RDID as the MX25L6405. Corresponding to flashrom svn r1534. Signed-off-by: Stefan Tauner Acked-by: Carl-Daniel Hailfinger --- dummyflasher.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 11 deletions(-) (limited to 'dummyflasher.c') diff --git a/dummyflasher.c b/dummyflasher.c index 50e8bf3..29256c2 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -46,6 +46,7 @@ enum emu_chip { EMULATE_ST_M25P10_RES, EMULATE_SST_SST25VF040_REMS, EMULATE_SST_SST25VF032B, + EMULATE_MACRONIX_MX25L6436, }; static enum emu_chip emu_chip = EMULATE_NONE; static char *emu_persistent_image = NULL; @@ -63,6 +64,33 @@ unsigned char spi_ignorelist[256]; int spi_blacklist_size = 0; int spi_ignorelist_size = 0; static uint8_t emu_status = 0; + +/* A legit complete SFDP table based on the MX25L6436E (rev. 1.8) datasheet. */ +static const uint8_t const sfdp_table[] = { + 0x53, 0x46, 0x44, 0x50, // @0x00: SFDP signature + 0x00, 0x01, 0x01, 0xFF, // @0x04: revision 1.0, 2 headers + 0x00, 0x00, 0x01, 0x09, // @0x08: JEDEC SFDP header rev. 1.0, 9 DW long + 0x1C, 0x00, 0x00, 0xFF, // @0x0C: PTP0 = 0x1C (instead of 0x30) + 0xC2, 0x00, 0x01, 0x04, // @0x10: Macronix header rev. 1.0, 4 DW long + 0x48, 0x00, 0x00, 0xFF, // @0x14: PTP1 = 0x48 (instead of 0x60) + 0xFF, 0xFF, 0xFF, 0xFF, // @0x18: hole. + 0xE5, 0x20, 0xC9, 0xFF, // @0x1C: SFDP parameter table start + 0xFF, 0xFF, 0xFF, 0x03, // @0x20 + 0x00, 0xFF, 0x08, 0x6B, // @0x24 + 0x08, 0x3B, 0x00, 0xFF, // @0x28 + 0xEE, 0xFF, 0xFF, 0xFF, // @0x2C + 0xFF, 0xFF, 0x00, 0x00, // @0x30 + 0xFF, 0xFF, 0x00, 0xFF, // @0x34 + 0x0C, 0x20, 0x0F, 0x52, // @0x38 + 0x10, 0xD8, 0x00, 0xFF, // @0x3C: SFDP parameter table end + 0xFF, 0xFF, 0xFF, 0xFF, // @0x40: hole. + 0xFF, 0xFF, 0xFF, 0xFF, // @0x44: hole. + 0x00, 0x36, 0x00, 0x27, // @0x48: Macronix parameter table start + 0xF4, 0x4F, 0xFF, 0xFF, // @0x4C + 0xD9, 0xC8, 0xFF, 0xFF, // @0x50 + 0xFF, 0xFF, 0xFF, 0xFF, // @0x54: Macronix parameter table end +}; + #endif #endif @@ -301,6 +329,19 @@ int dummy_init(void) msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " "write)\n"); } + if (!strcmp(tmp, "MX25L6436")) { + emu_chip = EMULATE_MACRONIX_MX25L6436; + emu_chip_size = 8 * 1024 * 1024; + emu_max_byteprogram_size = 256; + emu_max_aai_size = 0; + emu_jedec_se_size = 4 * 1024; + emu_jedec_be_52_size = 32 * 1024; + emu_jedec_be_d8_size = 64 * 1024; + emu_jedec_ce_60_size = emu_chip_size; + emu_jedec_ce_c7_size = emu_chip_size; + msg_pdbg("Emulating Macronix MX25L6436 SPI flash chip (RDID, " + "SFDP)\n"); + } #endif if (emu_chip == EMULATE_NONE) { msg_perr("Invalid chip specified for emulation: %s\n", tmp); @@ -449,7 +490,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, const unsigned char *writearr, unsigned char *readarr) { - unsigned int offs, i; + unsigned int offs, i, toread; static int unsigned aai_offs; if (writecnt == 0) { @@ -503,20 +544,30 @@ static int emulate_spi_chip_response(unsigned int writecnt, readarr[1] = 0x44; break; case JEDEC_RDID: - if (emu_chip != EMULATE_SST_SST25VF032B) + switch (emu_chip) { + case EMULATE_SST_SST25VF032B: + if (readcnt > 0) + readarr[0] = 0xbf; + if (readcnt > 1) + readarr[1] = 0x25; + if (readcnt > 2) + readarr[2] = 0x4a; break; - /* Respond with SST_SST25VF032B. */ - if (readcnt > 0) - readarr[0] = 0xbf; - if (readcnt > 1) - readarr[1] = 0x25; - if (readcnt > 2) - readarr[2] = 0x4a; + case EMULATE_MACRONIX_MX25L6436: + if (readcnt > 0) + readarr[0] = 0xc2; + if (readcnt > 1) + readarr[1] = 0x20; + if (readcnt > 2) + readarr[2] = 0x17; + break; + default: /* ignore */ + break; + } break; - case JEDEC_RDSR: { + case JEDEC_RDSR: memset(readarr, emu_status, readcnt); break; - } /* FIXME: this should be chip-specific. */ case JEDEC_EWSR: case JEDEC_WREN: @@ -673,6 +724,41 @@ static int emulate_spi_chip_response(unsigned int writecnt, /* emu_jedec_ce_c7_size is emu_chip_size. */ memset(flashchip_contents, 0xff, emu_jedec_ce_c7_size); break; + case JEDEC_SFDP: + if (emu_chip != EMULATE_MACRONIX_MX25L6436) + break; + if (writecnt < 4) + break; + offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; + + /* SFDP expects one dummy byte after the address. */ + if (writecnt == 4) { + /* The dummy byte was not written, make sure it is read instead. + * Shifting and shortening the read array does achieve this goal. + */ + readarr++; + readcnt--; + } else { + /* The response is shifted if more than 5 bytes are written, because SFDP data is + * already shifted out by the chip while those superfluous bytes are written. */ + offs += writecnt - 5; + } + + /* The SFDP spec implies that the start address of an SFDP read may be truncated to fit in the + * SFDP table address space, i.e. the start address may be wrapped around at SFDP table size. + * This is a reasonable implementation choice in hardware because it saves a few gates. */ + if (offs >= sizeof(sfdp_table)) { + msg_pdbg("Wrapping the start address around the SFDP table boundary (using 0x%x " + "instead of 0x%x).\n", (unsigned int)(offs % sizeof(sfdp_table)), offs); + offs %= sizeof(sfdp_table); + } + toread = min(sizeof(sfdp_table) - offs, readcnt); + memcpy(readarr, sfdp_table + offs, toread); + if (toread < readcnt) + msg_pdbg("Crossing the SFDP table boundary in a single " + "continuous chunk produces undefined results " + "after that point.\n"); + break; default: /* No special response. */ break; @@ -703,6 +789,7 @@ static int dummy_spi_send_command(struct flashctx *flash, unsigned int writecnt, case EMULATE_ST_M25P10_RES: case EMULATE_SST_SST25VF040_REMS: case EMULATE_SST_SST25VF032B: + case EMULATE_MACRONIX_MX25L6436: if (emulate_spi_chip_response(writecnt, readcnt, writearr, readarr)) { msg_pdbg("Invalid command sent to flash chip!\n"); -- cgit v1.1