summaryrefslogtreecommitdiffstats
path: root/src/drivers
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2020-01-03 15:58:11 -0700
committerAaron Durbin <adurbin@chromium.org>2020-01-10 04:55:09 +0000
commit1c3086a6036f9908c8c09c823c5ad1718eac7ce0 (patch)
tree185d0795575f7329d9b552a3605e5139979f086d /src/drivers
parent73451fdea266e24a3ce99e1bf41f49735dc62d28 (diff)
downloadcoreboot-1c3086a6036f9908c8c09c823c5ad1718eac7ce0.tar.gz
coreboot-1c3086a6036f9908c8c09c823c5ad1718eac7ce0.tar.bz2
coreboot-1c3086a6036f9908c8c09c823c5ad1718eac7ce0.zip
drivers/spi/spi_flash: explicitly handle STMicro deep power state
In order to provide more consistent probing in future refactorings, pull out the release from deep sleep path in STMicro's SPI flash probing function. Call that function explicitly when RDID doesn't return anything at all. The old STMicro parts, even if supporting RDID, won't decode that instruction while in a deep power down state. Instead of re-issuing RDID after the successful wake assume the id fixup is valid. Change-Id: I46c47abcfb1376c1c3ce772f6f232857b8c54202 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/38167 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com>
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 ff69a9a1c1c9..4a86146503b5 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 f99c90ed36c2..58172ce929f8 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 57bd3ddbb52a..83d074931124 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])) {