summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/spi/spi_flash.c12
-rw-r--r--src/drivers/spi/spi_flash_internal.h2
-rw-r--r--src/drivers/spi/stmicro.c30
3 files changed, 29 insertions, 15 deletions
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index ff69a9a1c1..4a86146503 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -368,9 +368,6 @@ static struct {
{ 0, VENDOR_ID_WINBOND, spi_flash_probe_winbond, },
#endif
/* Keep it sorted by best detection */
-#if CONFIG(SPI_FLASH_STMICRO)
- { 0, VENDOR_ID_STMICRO_FF, spi_flash_probe_stmicro, },
-#endif
#if CONFIG(SPI_FLASH_ADESTO)
{ 0, VENDOR_ID_ADESTO, spi_flash_probe_adesto, },
#endif
@@ -402,6 +399,15 @@ int spi_flash_generic_probe(const struct spi_slave *spi,
printk(BIOS_INFO, "Manufacturer: %02x\n", *idp);
+ /* If no result from RDID command and STMicro parts are enabled attempt
+ to wake the part from deep sleep and obtain alternative id info. */
+ if (CONFIG(SPI_FLASH_STMICRO) && *idp == 0xff) {
+ if (stmicro_release_deep_sleep_identify(spi, idcode))
+ return -1;
+ idp = idcode;
+ shift = 0;
+ }
+
/* search the table for matches in shift and id */
for (i = 0; i < (int)ARRAY_SIZE(flashes); ++i)
if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h
index f99c90ed36..58172ce929 100644
--- a/src/drivers/spi/spi_flash_internal.h
+++ b/src/drivers/spi/spi_flash_internal.h
@@ -81,6 +81,8 @@ int spi_flash_probe_sst(const struct spi_slave *spi, u8 *idcode,
struct spi_flash *flash);
int spi_flash_probe_stmicro(const struct spi_slave *spi, u8 *idcode,
struct spi_flash *flash);
+/* Release from deep sleep an provide alternative rdid information. */
+int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode);
int spi_flash_probe_winbond(const struct spi_slave *spi, u8 *idcode,
struct spi_flash *flash);
int spi_flash_probe_gigadevice(const struct spi_slave *spi, u8 *idcode,
diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c
index 57bd3ddbb5..83d0749311 100644
--- a/src/drivers/spi/stmicro.c
+++ b/src/drivers/spi/stmicro.c
@@ -289,24 +289,30 @@ static const struct spi_flash_ops spi_flash_ops = {
.erase = spi_flash_cmd_erase,
};
+int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode)
+{
+ if (spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4))
+ return -1;
+
+ /* Assuming ST parts identify with 0x1X to release from deep
+ power down and read electronic signature. */
+ if ((idcode[3] & 0xf0) != 0x10)
+ return -1;
+
+ /* Fix up the idcode to mimic rdid jedec instruction. */
+ idcode[0] = 0x20;
+ idcode[1] = 0x20;
+ idcode[2] = idcode[3] + 1;
+
+ return 0;
+}
+
int spi_flash_probe_stmicro(const struct spi_slave *spi, u8 *idcode,
struct spi_flash *flash)
{
const struct stmicro_spi_flash_params *params;
unsigned int i;
- if (idcode[0] == 0xff) {
- i = spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4);
- if (i)
- return -1;
- if ((idcode[3] & 0xf0) == 0x10) {
- idcode[0] = 0x20;
- idcode[1] = 0x20;
- idcode[2] = idcode[3] + 1;
- } else
- return -1;
- }
-
for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
params = &stmicro_spi_flash_table[i];
if (params->device_id == (idcode[1] << 8 | idcode[2])) {