aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Huber <nico.h@gmx.de>2017-11-10 21:10:20 +0100
committerNico Huber <nico.h@gmx.de>2018-01-02 20:15:30 +0000
commitfe34d2af28bd81aaa1e23ba38febaa98ec4bb90c (patch)
tree53bda4d3445a94505455ffb12a96da602ba97af6
parent1cf407b4f8d56035816efaf936a40553441eca46 (diff)
downloadflashrom-fe34d2af28bd81aaa1e23ba38febaa98ec4bb90c.tar.gz
flashrom-fe34d2af28bd81aaa1e23ba38febaa98ec4bb90c.tar.bz2
flashrom-fe34d2af28bd81aaa1e23ba38febaa98ec4bb90c.zip
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 (the chip might be in 4BA mode after reset). If we can't assure the state of 4BA mode, we bail out to simplify the code (we'd have to ensure that we don't run any instructions that can usually be switched to 4BA mode otherwise). Two new feature flags are introduced: * 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 is dropped, it's completely implicit now. Also, draw the with/without WREN distinction into the enter/exit functions to reduce code redundancy. Change-Id: I877fe817f801fc54bd0ee2ce4e3ead324cbb3673 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/22422 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com>
-rw-r--r--chipdrivers.h6
-rw-r--r--flash.h10
-rw-r--r--flashchips.c15
-rw-r--r--flashrom.c12
-rw-r--r--spi25.c39
5 files changed, 35 insertions, 47 deletions
diff --git a/chipdrivers.h b/chipdrivers.h
index d7a4aa94..8405220d 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -61,10 +61,8 @@ int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int st
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 a14c3029..6e86c354 100644
--- a/flash.h
+++ b/flash.h
@@ -119,11 +119,12 @@ enum write_granularity {
#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
significant 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 @@ struct flashchip {
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 c8ea5eb9..0e16a48c 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -8134,7 +8134,7 @@ const struct flashchip flashchips[] = {
.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,
@@ -8162,7 +8162,6 @@ const struct flashchip flashchips[] = {
.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},
},
@@ -8175,7 +8174,7 @@ const struct flashchip flashchips[] = {
.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,
@@ -8203,7 +8202,6 @@ const struct flashchip flashchips[] = {
.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},
},
@@ -9916,7 +9914,8 @@ const struct flashchip flashchips[] = {
.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,
@@ -9949,7 +9948,8 @@ const struct flashchip flashchips[] = {
.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,
@@ -14827,7 +14827,7 @@ const struct flashchip flashchips[] = {
/* 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,
@@ -14854,7 +14854,6 @@ const struct flashchip flashchips[] = {
.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 9cc1be66..ac987fd9 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -42,6 +42,7 @@
#include "flashchips.h"
#include "programmer.h"
#include "hwaccess.h"
+#include "chipdrivers.h"
const char flashrom_version[] = FLASHROM_VERSION;
const char *chip_to_probe = NULL;
@@ -2219,9 +2220,14 @@ int prepare_flash_access(struct flashctx *const flash,
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");
+ if (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN)) {
+ int ret;
+ if (spi_master_4ba(flash))
+ ret = spi_enter_4ba(flash);
+ else
+ ret = spi_exit_4ba(flash);
+ if (ret) {
+ msg_cerr("Failed to set correct 4BA mode! Aborting.\n");
return 1;
}
}
diff --git a/spi25.c b/spi25.c
index 787f62e3..00e0992c 100644
--- a/spi25.c
+++ b/spi25.c
@@ -843,42 +843,27 @@ bailout:
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 (!ret)
- flash->in_4ba_mode = true;
- return ret;
-}
+ 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);
-/* Enter 4-bytes addressing mode with sending WREN before */
-int spi_enter_4ba_b7_we(struct flashctx *flash)
-{
- const int ret = spi_simple_write_cmd(flash, JEDEC_ENTER_4_BYTE_ADDR_MODE, 0);
if (!ret)
- flash->in_4ba_mode = true;
+ flash->in_4ba_mode = enter;
return ret;
}
-/* Exit 4-bytes addressing mode (without sending WREN before) */
-int spi_exit_4ba_e9(struct flashctx *flash)
+int spi_enter_4ba(struct flashctx *const 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;
+ return spi_enter_exit_4ba(flash, true);
}
-/* Exit 4-bytes addressing mode with sending WREN before */
-int spi_exit_4ba_e9_we(struct flashctx *flash)
+int spi_exit_4ba(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);
}