summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2008-05-15 03:19:49 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2008-05-15 03:19:49 +0000
commita4868c44b56424d3f0c28ad1a6aa95bdd7eae04b (patch)
tree2c2ae700648ed4075c83e65f89fa6d62ee161f8b
parentc7d29013db37b25e842d5208d0c5664282715055 (diff)
Add support for the JEDEC RES (Read Electronic Signature and Resume from
Powerdown) SPI command to flashrom to identify older SPI chips which can't handle JEDEC RDID. Since RES gives a one-byte identifier which is shared among many different vendors and even different sizes, we want to match RES as a last resort if RDID returns 0xff 0xff 0xff. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Peter Stuge <peter@stuge.se> This is a heavily reworked version of a patch by Fredrik Tolf, which was Signed-off-by: Fredrik Tolf <fredrik@dolda2000.com> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3320 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r--util/flashrom/flash.h6
-rw-r--r--util/flashrom/flashchips.c63
-rw-r--r--util/flashrom/spi.c41
-rw-r--r--util/flashrom/spi.h5
4 files changed, 82 insertions, 33 deletions
diff --git a/util/flashrom/flash.h b/util/flashrom/flash.h
index 4f73e0d1da..5d7b64508c 100644
--- a/util/flashrom/flash.h
+++ b/util/flashrom/flash.h
@@ -177,6 +177,8 @@ extern struct flashchip flashchips[];
/*
* MX25 chips are SPI, first byte of device ID is memory type,
* second byte of device ID is log(bitsize)-9.
+ * Generalplus SPI chips seem to be compatible with Macronix
+ * and use the same set of IDs.
*/
#define MX_ID 0xC2 /* Macronix (MX) */
#define MX_25L512 0x2010 /* 2^19 kbit or 2^16 kByte */
@@ -266,6 +268,7 @@ extern struct flashchip flashchips[];
#define ST_M25P10A 0x2011
#define ST_M25P20 0x2012
#define ST_M25P40 0x2013
+#define ST_M25P40_RES 0x12
#define ST_M25P80 0x2014
#define ST_M25P16 0x2015
#define ST_M25P32 0x2016
@@ -366,7 +369,8 @@ int coreboot_init(void);
extern char *lb_part, *lb_vendor;
/* spi.c */
-int probe_spi(struct flashchip *flash);
+int probe_spi_rdid(struct flashchip *flash);
+int probe_spi_res(struct flashchip *flash);
int it87xx_probe_spi_flash(const char *name);
int spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
void spi_write_enable();
diff --git a/util/flashrom/flashchips.c b/util/flashrom/flashchips.c
index 123dfca3c4..ab80bd00e5 100644
--- a/util/flashrom/flashchips.c
+++ b/util/flashrom/flashchips.c
@@ -49,26 +49,26 @@ struct flashchip flashchips[] = {
{"Fujitsu", "MBM29F400TC", FUJITSU_ID, MBM29F400TC_STRANGE, 512, 64 * 1024, TEST_UNTESTED, probe_m29f400bt, erase_m29f400bt, write_coreboot_m29f400bt},
{"Intel", "82802AB", INTEL_ID, 173, 512, 64 * 1024, TEST_UNTESTED, probe_82802ab, erase_82802ab, write_82802ab},
{"Intel", "82802AC", INTEL_ID, 172, 1024, 64 * 1024, TEST_UNTESTED, probe_82802ab, erase_82802ab, write_82802ab},
- {"Macronix", "MX25L4005", MX_ID, MX_25L4005, 512, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"Macronix", "MX25L8005", MX_ID, MX_25L8005, 1024, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"Macronix", "MX25L1605", MX_ID, MX_25L1605, 2048, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"Macronix", "MX25L3205", MX_ID, MX_25L3205, 4096, 256, TEST_OK_PREW, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Macronix", "MX25L4005", MX_ID, MX_25L4005, 512, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Macronix", "MX25L8005", MX_ID, MX_25L8005, 1024, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Macronix", "MX25L1605", MX_ID, MX_25L1605, 2048, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Macronix", "MX25L3205", MX_ID, MX_25L3205, 4096, 256, TEST_OK_PREW, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
{"Macronix", "MX29F002", MX_ID, MX_29F002, 256, 64 * 1024, TEST_UNTESTED, probe_29f002, erase_29f002, write_29f002},
#ifndef DISABLE_DOC
{"M-Systems", "MD-2802", MSYSTEMS_ID, MSYSTEMS_MD2802, 8, 8 * 1024, TEST_UNTESTED, probe_md2802, erase_md2802, write_md2802, read_md2802},
#endif
- {"PMC", "Pm25LV010", PMC_ID, PMC_25LV010, 128, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"PMC", "Pm25LV016B", PMC_ID, PMC_25LV016B, 2048, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"PMC", "Pm25LV020", PMC_ID, PMC_25LV020, 256, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"PMC", "Pm25LV040", PMC_ID, PMC_25LV040, 512, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"PMC", "Pm25LV080B", PMC_ID, PMC_25LV080B, 1024, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"PMC", "Pm25LV512", PMC_ID, PMC_25LV512, 64, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"PMC", "Pm25LV010", PMC_ID, PMC_25LV010, 128, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"PMC", "Pm25LV016B", PMC_ID, PMC_25LV016B, 2048, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"PMC", "Pm25LV020", PMC_ID, PMC_25LV020, 256, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"PMC", "Pm25LV040", PMC_ID, PMC_25LV040, 512, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"PMC", "Pm25LV080B", PMC_ID, PMC_25LV080B, 1024, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"PMC", "Pm25LV512", PMC_ID, PMC_25LV512, 64, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
{"PMC", "Pm49FL002", PMC_ID_NOPREFIX,PMC_49FL002, 256, 16 * 1024, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_49fl004},
{"PMC", "Pm49FL004", PMC_ID_NOPREFIX,PMC_49FL004, 512, 64 * 1024, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_49fl004},
{"Sharp", "LHF00L04", SHARP_ID, SHARP_LHF00L04, 1024, 64 * 1024, TEST_UNTESTED, probe_lhf00l04, erase_lhf00l04, write_lhf00l04},
- {"Spansion", "S25FL016A", SPANSION_ID, SPANSION_S25FL016A, 2048, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"SST", "SST25VF016B", SST_ID, SST_25VF016B, 2048, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"SST", "SST25VF040B", SST_ID, SST_25VF040B, 512, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Spansion", "S25FL016A", SPANSION_ID, SPANSION_S25FL016A, 2048, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"SST", "SST25VF016B", SST_ID, SST_25VF016B, 2048, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"SST", "SST25VF040B", SST_ID, SST_25VF040B, 512, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
{"SST", "SST28SF040A", SST_ID, SST_28SF040, 512, 256, TEST_UNTESTED, probe_28sf040, erase_28sf040, write_28sf040},
{"SST", "SST29EE020A", SST_ID, SST_29EE020A, 256, 128, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_jedec},
{"SST", "SST39SF010A", SST_ID, SST_39SF010, 128, 4096, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_39sf020},
@@ -91,15 +91,16 @@ struct flashchip flashchips[] = {
{"SST", "SST49LF040B", SST_ID, SST_49LF040B, 512, 64 * 1024, TEST_UNTESTED, probe_sst_fwhub, erase_sst_fwhub, write_sst_fwhub},
{"SST", "SST49LF080A", SST_ID, SST_49LF080A, 1024, 4096, TEST_UNTESTED, probe_jedec, erase_49lf040, write_49lf040},
{"SST", "SST49LF160C", SST_ID, SST_49LF160C, 2048, 4 * 1024, TEST_UNTESTED, probe_49lfxxxc, erase_49lfxxxc, write_49lfxxxc},
- {"ST", "M25P05-A", ST_ID, ST_M25P05A, 64, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P10-A", ST_ID, ST_M25P10A, 128, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P20", ST_ID, ST_M25P20, 256, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P40", ST_ID, ST_M25P40, 512, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P80", ST_ID, ST_M25P80, 1024, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P16", ST_ID, ST_M25P16, 2048, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P32", ST_ID, ST_M25P32, 4096, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P64", ST_ID, ST_M25P64, 8192, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"ST", "M25P128", ST_ID, ST_M25P128, 16384, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P05-A", ST_ID, ST_M25P05A, 64, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P10-A", ST_ID, ST_M25P10A, 128, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P20", ST_ID, ST_M25P20, 256, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P40", ST_ID, ST_M25P40, 512, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P40-old", ST_ID, ST_M25P40_RES, 512, 256, TEST_UNTESTED, probe_spi_res, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P80", ST_ID, ST_M25P80, 1024, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P16", ST_ID, ST_M25P16, 2048, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P32", ST_ID, ST_M25P32, 4096, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P64", ST_ID, ST_M25P64, 8192, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"ST", "M25P128", ST_ID, ST_M25P128, 16384, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
{"ST", "M29F002B", ST_ID, ST_M29F002B, 256, 64 * 1024, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_jedec},
{"ST", "M29F002T/NT", ST_ID, ST_M29F002T, 256, 64 * 1024, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_jedec},
{"ST", "M29F040B", ST_ID, ST_M29F040B, 512, 64 * 1024, TEST_UNTESTED, probe_29f040b, erase_29f040b, write_29f040b},
@@ -118,10 +119,10 @@ struct flashchip flashchips[] = {
{"SyncMOS", "S29C51001T", SYNCMOS_ID, S29C51001T, 128, 128, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_49f002},
{"SyncMOS", "S29C51002T", SYNCMOS_ID, S29C51002T, 256, 128, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_49f002},
{"SyncMOS", "S29C51004T", SYNCMOS_ID, S29C51004T, 512, 128, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_49f002},
- {"Winbond", "W25x10", WINBOND_NEX_ID, W_25X10, 128, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"Winbond", "W25x20", WINBOND_NEX_ID, W_25X20, 256, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"Winbond", "W25x40", WINBOND_NEX_ID, W_25X40, 512, 256, TEST_OK_PREW, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
- {"Winbond", "W25x80", WINBOND_NEX_ID, W_25X80, 1024, 256, TEST_UNTESTED, probe_spi, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Winbond", "W25x10", WINBOND_NEX_ID, W_25X10, 128, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Winbond", "W25x20", WINBOND_NEX_ID, W_25X20, 256, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Winbond", "W25x40", WINBOND_NEX_ID, W_25X40, 512, 256, TEST_OK_PREW, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
+ {"Winbond", "W25x80", WINBOND_NEX_ID, W_25X80, 1024, 256, TEST_UNTESTED, probe_spi_rdid, spi_chip_erase_c7, spi_chip_write, spi_chip_read},
{"Winbond", "W29C011", WINBOND_ID, W_29C011, 128, 128, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_jedec},
{"Winbond", "W29C020C", WINBOND_ID, W_29C020C, 256, 128, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_jedec},
{"Winbond", "W29C040P", WINBOND_ID, W_29C040P, 512, 256, TEST_UNTESTED, probe_jedec, erase_chip_jedec, write_jedec},
@@ -136,11 +137,11 @@ struct flashchip flashchips[] = {
{"Winbond", "W39V080FA", WINBOND_ID, W_39V080FA, 1024, 64*1024, TEST_UNTESTED, probe_winbond_fwhub, erase_winbond_fwhub, write_winbond_fwhub},
{"Winbond", "W39V080FA (dual mode)",WINBOND_ID, W_39V080FA_DM, 512, 64*1024, TEST_UNTESTED, probe_winbond_fwhub, erase_winbond_fwhub, write_winbond_fwhub},
- {"EON", "unknown EON SPI chip", EON_ID_NOPREFIX,GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi, NULL, NULL},
- {"Macronix", "unknown Macronix SPI chip", MX_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi, NULL, NULL},
- {"PMC", "unknown PMC SPI chip", PMC_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi, NULL, NULL},
- {"SST", "unknown SST SPI chip", SST_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi, NULL, NULL},
- {"ST", "unknown ST SPI chip", ST_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi, NULL, NULL},
+ {"EON", "unknown EON SPI chip", EON_ID_NOPREFIX,GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi_rdid, NULL, NULL},
+ {"Macronix", "unknown Macronix SPI chip", MX_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi_rdid, NULL, NULL},
+ {"PMC", "unknown PMC SPI chip", PMC_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi_rdid, NULL, NULL},
+ {"SST", "unknown SST SPI chip", SST_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi_rdid, NULL, NULL},
+ {"ST", "unknown ST SPI chip", ST_ID, GENERIC_DEVICE_ID, 0, 256, TEST_UNTESTED, probe_spi_rdid, NULL, NULL},
{NULL,}
};
diff --git a/util/flashrom/spi.c b/util/flashrom/spi.c
index 786d555ee9..ddb9ff8fdc 100644
--- a/util/flashrom/spi.c
+++ b/util/flashrom/spi.c
@@ -49,6 +49,16 @@ static int spi_rdid(unsigned char *readarr)
return 0;
}
+static int spi_res(unsigned char *readarr)
+{
+ const unsigned char cmd[JEDEC_RES_OUTSIZE] = {JEDEC_RES, 0, 0, 0};
+
+ if (spi_command(JEDEC_RES_OUTSIZE, JEDEC_RES_INSIZE, cmd, readarr))
+ return 1;
+ printf_debug("RES returned %02x.\n", readarr[0]);
+ return 0;
+}
+
void spi_write_enable()
{
const unsigned char cmd[JEDEC_WREN_OUTSIZE] = {JEDEC_WREN};
@@ -65,7 +75,7 @@ void spi_write_disable()
spi_command(JEDEC_WRDI_OUTSIZE, JEDEC_WRDI_INSIZE, cmd, NULL);
}
-int probe_spi(struct flashchip *flash)
+int probe_spi_rdid(struct flashchip *flash)
{
unsigned char readarr[3];
uint32_t manuf_id;
@@ -102,6 +112,35 @@ int probe_spi(struct flashchip *flash)
return 0;
}
+int probe_spi_res(struct flashchip *flash)
+{
+ unsigned char readarr[3];
+ uint32_t model_id;
+ if (!spi_rdid(readarr)) {
+ /* Check if RDID returns 0xff 0xff 0xff, then we use RES. */
+ if ((readarr[0] != 0xff) || (readarr[1] != 0xff) ||
+ (readarr[2] != 0xff))
+ return 0;
+ } else {
+ /* We couldn't issue RDID, it's pointless to try RES. */
+ return 0;
+ }
+ if (!spi_res(readarr)) {
+ model_id = readarr[0];
+ printf_debug("%s: id 0x%x\n", __FUNCTION__, model_id);
+ if (model_id == flash->model_id) {
+ /* Print the status register to tell the
+ * user about possible write protection.
+ */
+ spi_prettyprint_status_register(flash);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
uint8_t spi_read_status_register()
{
const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = {JEDEC_RDSR};
diff --git a/util/flashrom/spi.h b/util/flashrom/spi.h
index 15bac4ec52..f5c877cdcb 100644
--- a/util/flashrom/spi.h
+++ b/util/flashrom/spi.h
@@ -29,6 +29,11 @@
#define JEDEC_RDID_OUTSIZE 0x01
#define JEDEC_RDID_INSIZE 0x03
+/* Read Electronic Signature */
+#define JEDEC_RES 0xab
+#define JEDEC_RES_OUTSIZE 0x04
+#define JEDEC_RES_INSIZE 0x01
+
/* Write Enable */
#define JEDEC_WREN 0x06
#define JEDEC_WREN_OUTSIZE 0x01