Nico Huber has uploaded this change for review.

View Change

spi25: Revise decision when to enter/exit 4BA mode

Instead of arbitrarily deciding whether to enter 4BA mode in the flash
chip's declaration, advertise that entering 4BA mode is supported and
only enter it if the SPI master supports 4-byte addresses. If not, exit
4BA mode (as we don't know if the chip is in its reset state). Two new
feature flags are introduced for that:

* FEATURE_4BA_ENTER:
Can enter/exit 4BA mode with instructions 0xb7/0xe9 w/o WREN.
* FEATURE_4BA_ENTER_WREN
Can enter/exit 4BA mode with instructions 0xb7/0xe9 after WREN.

FEATURE_4BA_SUPPORT was dropped, it's completely implicit now.

Change-Id: I877fe817f801fc54bd0ee2ce4e3ead324cbb3673
Signed-off-by: Nico Huber <nico.h@gmx.de>
---
M chipdrivers.h
M flash.h
M flashchips.c
M flashrom.c
M spi25.c
5 files changed, 36 insertions(+), 50 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/22/22422/1
diff --git a/chipdrivers.h b/chipdrivers.h
index d7a4aa9..8405220 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -61,10 +61,8 @@
int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
-int spi_enter_4ba_b7(struct flashctx *flash);
-int spi_enter_4ba_b7_we(struct flashctx *flash);
-int spi_exit_4ba_e9(struct flashctx *flash);
-int spi_exit_4ba_e9_we(struct flashctx *flash);
+int spi_enter_4ba(struct flashctx *flash);
+int spi_exit_4ba(struct flashctx *flash);


/* spi25_statusreg.c */
diff --git a/flash.h b/flash.h
index bab4873..bf7ebd0 100644
--- a/flash.h
+++ b/flash.h
@@ -119,11 +119,12 @@
#define FEATURE_WRSR_EITHER (FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
#define FEATURE_OTP (1 << 8)
#define FEATURE_QPI (1 << 9)
-#define FEATURE_4BA_SUPPORT (1 << 10)
-#define FEATURE_4BA_EXT_ADDR (1 << 11) /**< Regular 3-byte operations can be used by writing the most
+#define FEATURE_4BA_ENTER (1 << 10) /**< Can enter/exit 4BA mode with instructions 0xb7/0xe9 w/o WREN */
+#define FEATURE_4BA_ENTER_WREN (1 << 11) /**< Can enter/exit 4BA mode with instructions 0xb7/0xe9 after WREN */
+#define FEATURE_4BA_EXT_ADDR (1 << 12) /**< Regular 3-byte operations can be used by writing the most
signifcant address byte into an extended address register. */
-#define FEATURE_4BA_READ (1 << 12) /**< Native 4BA read instruction (0x13) is supported. */
-#define FEATURE_4BA_WRITE (1 << 13) /**< Native 4BA byte program (0x12) is supported. */
+#define FEATURE_4BA_READ (1 << 13) /**< Native 4BA read instruction (0x13) is supported. */
+#define FEATURE_4BA_WRITE (1 << 14) /**< Native 4BA byte program (0x12) is supported. */

enum test_state {
OK = 0,
@@ -205,7 +206,6 @@
int (*unlock) (struct flashctx *flash);
int (*write) (struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
- int (*set_4ba) (struct flashctx *flash);
struct voltage {
uint16_t min;
uint16_t max;
diff --git a/flashchips.c b/flashchips.c
index 06e659d..0da048a 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -8052,7 +8052,7 @@
.total_size = 32768,
.page_size = 256,
/* OTP: 512B total; enter 0xB1, exit 0xC1 */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_SUPPORT,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -8080,7 +8080,6 @@
.unlock = spi_disable_blockprotect_bp3_srwd,
.write = spi_chip_write_256,
.read = spi_chip_read, /* Fast read (0x0B) supported */
- .set_4ba = spi_enter_4ba_b7,
.voltage = {2700, 3600},
},

@@ -8093,7 +8092,7 @@
.total_size = 65536,
.page_size = 256,
/* OTP: 512B total; enter 0xB1, exit 0xC1 */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_SUPPORT,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -8121,7 +8120,6 @@
.unlock = spi_disable_blockprotect_bp3_srwd,
.write = spi_chip_write_256,
.read = spi_chip_read, /* Fast read (0x0B) supported */
- .set_4ba = spi_enter_4ba_b7,
.voltage = {2700, 3600},
},

@@ -9834,7 +9832,8 @@
.page_size = 256,
/* supports SFDP */
/* OTP: 64B total; read 0x4B, write 0x42 */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_SUPPORT | FEATURE_4BA_READ | FEATURE_4BA_WRITE,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP
+ | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_READ | FEATURE_4BA_WRITE,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -9867,7 +9866,8 @@
.page_size = 256,
/* supports SFDP */
/* OTP: 64B total; read 0x4B, write 0x42 */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_SUPPORT | FEATURE_4BA_READ | FEATURE_4BA_WRITE,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP
+ | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_READ | FEATURE_4BA_WRITE,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -14745,7 +14745,7 @@
/* supports SFDP */
/* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */
/* FOUR_BYTE_ADDR: supports 4-bytes addressing mode */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_SUPPORT | FEATURE_4BA_READ,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_READ,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -14772,7 +14772,6 @@
.unlock = spi_disable_blockprotect,
.write = spi_chip_write_256,
.read = spi_chip_read,
- .set_4ba = spi_enter_4ba_b7_we,
.voltage = {2700, 3600},
},

diff --git a/flashrom.c b/flashrom.c
index 6944907..9522f25 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -2219,11 +2219,15 @@
flash->in_4ba_mode = false;

/* Enable/disable 4-byte addressing mode if flash chip supports it */
- if ((flash->chip->feature_bits & FEATURE_4BA_SUPPORT) && flash->chip->set_4ba) {
- if (flash->chip->set_4ba(flash)) {
- msg_cerr("Enabling/disabling 4-byte addressing mode failed!\n");
- return 1;
- }
+ if (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN)) {
+ int ret;
+ if (flash->mst->buses_supported & BUS_SPI && flash->mst->spi.features & SPI_MASTER_4BA)
+ ret = spi_enter_4ba(flash);
+ else
+ ret = spi_exit_4ba(flash);
+ if (ret)
+ msg_cwarn("Enabling/disabling 4-byte addressing mode failed!\n"
+ "Assuming chip is in 3-byte addressing mode.\n");
}

return 0;
diff --git a/spi25.c b/spi25.c
index 4671907..196d9f5 100644
--- a/spi25.c
+++ b/spi25.c
@@ -839,42 +839,27 @@
return SPI_GENERIC_ERROR;
}

-/* Enter 4-bytes addressing mode (without sending WREN before) */
-int spi_enter_4ba_b7(struct flashctx *flash)
+static int spi_enter_exit_4ba(struct flashctx *const flash, const bool enter)
{
- const unsigned char cmd = JEDEC_ENTER_4_BYTE_ADDR_MODE;
+ const unsigned char cmd = enter ? JEDEC_ENTER_4_BYTE_ADDR_MODE : JEDEC_EXIT_4_BYTE_ADDR_MODE;
+ int ret = 1;

- const int ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
+ if (flash->chip->feature_bits & FEATURE_4BA_ENTER)
+ ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
+ else if (flash->chip->feature_bits & FEATURE_4BA_ENTER_WREN)
+ ret = spi_simple_write_cmd(flash, cmd, 0);
+
if (!ret)
- flash->in_4ba_mode = true;
+ flash->in_4ba_mode = enter;
return ret;
}

-/* Enter 4-bytes addressing mode with sending WREN before */
-int spi_enter_4ba_b7_we(struct flashctx *flash)
+int spi_enter_4ba(struct flashctx *const flash)
{
- const int ret = spi_simple_write_cmd(flash, JEDEC_ENTER_4_BYTE_ADDR_MODE, 0);
- if (!ret)
- flash->in_4ba_mode = true;
- return ret;
+ return spi_enter_exit_4ba(flash, true);
}

-/* Exit 4-bytes addressing mode (without sending WREN before) */
-int spi_exit_4ba_e9(struct flashctx *flash)
+int spi_exit_4ba(struct flashctx *flash)
{
- const unsigned char cmd = JEDEC_EXIT_4_BYTE_ADDR_MODE;
-
- const int ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
- if (!ret)
- flash->in_4ba_mode = false;
- return ret;
-}
-
-/* Exit 4-bytes addressing mode with sending WREN before */
-int spi_exit_4ba_e9_we(struct flashctx *flash)
-{
- const int ret = spi_simple_write_cmd(flash, JEDEC_EXIT_4_BYTE_ADDR_MODE, 0);
- if (!ret)
- flash->in_4ba_mode = false;
- return ret;
+ return spi_enter_exit_4ba(flash, false);
}

To view, visit change 22422. To unsubscribe, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I877fe817f801fc54bd0ee2ce4e3ead324cbb3673
Gerrit-Change-Number: 22422
Gerrit-PatchSet: 1
Gerrit-Owner: Nico Huber <nico.h@gmx.de>