mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00
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 <stefan.tauner@alumni.tuwien.ac.at> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
This commit is contained in:
parent
f5e62cb151
commit
0b9df97a84
109
dummyflasher.c
109
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");
|
||||
|
@ -435,6 +435,8 @@ vendor):
|
||||
.sp
|
||||
.RB "* SST " SST25VF032B " SPI flash chip (RDID, AAI write)"
|
||||
.sp
|
||||
.RB "* Macronix " MX25L6436 " SPI flash chip (RDID, SFDP)"
|
||||
.sp
|
||||
Example:
|
||||
.B "flashrom -p dummy:emulate=SST25VF040.REMS"
|
||||
.TP
|
||||
|
Loading…
x
Reference in New Issue
Block a user