aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolai Artemiev <nartemiev@google.com>2021-10-20 22:32:25 +1100
committerAnastasia Klimchuk <aklm@chromium.org>2022-02-28 07:58:43 +0000
commitb7ea3a9a5d481a09229abba0fe6d2509ef2713a1 (patch)
tree01b5923330cf9ccd39da4c1802bda05d45e937da
parenta0319804a03f69d6e21af2ce42e8fd311e2e6a8f (diff)
downloadflashrom-b7ea3a9a5d481a09229abba0fe6d2509ef2713a1.tar.gz
flashrom-b7ea3a9a5d481a09229abba0fe6d2509ef2713a1.tar.bz2
flashrom-b7ea3a9a5d481a09229abba0fe6d2509ef2713a1.zip
spi25_statusreg,flashchips: add SR2 read/write support
This patch adds support for reading and writing the second status register and enables it on a limited set of flash chips. Chip support for RDSR2/WRSR2/extended WRSR is represented using feature flags to be consistent with how other SPI capabilities are represented. BUG=b:195381327,b:153800563 BRANCH=none TEST=flashrom -{r,w,E} TEST=flashrom --wp-{enable,disable,range,list,status} at end of patch series TEST=logged SR2 read/write values during wp commands Change-Id: I34a503b0958e8f2f22a2a993a6ea529eb46b41db Signed-off-by: Nikolai Artemiev <nartemiev@google.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/58570 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
-rw-r--r--flash.h3
-rw-r--r--flashchips.c7
-rw-r--r--spi.h11
-rw-r--r--spi25_statusreg.c35
4 files changed, 53 insertions, 3 deletions
diff --git a/flash.h b/flash.h
index f1a8b340..cd40fa3f 100644
--- a/flash.h
+++ b/flash.h
@@ -140,6 +140,9 @@ enum write_granularity {
#define FEATURE_ERASED_ZERO (1 << 17)
#define FEATURE_NO_ERASE (1 << 18)
+#define FEATURE_WRSR_EXT (1 << 19)
+#define FEATURE_WRSR2 (1 << 20)
+
#define ERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff)
enum test_state {
diff --git a/flashchips.c b/flashchips.c
index 21eeb395..9e10b5d2 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -6317,7 +6317,7 @@ const struct flashchip flashchips[] = {
.total_size = 16384,
.page_size = 256,
/* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -6706,7 +6706,8 @@ const struct flashchip flashchips[] = {
.model_id = GIGADEVICE_GD25Q256D,
.total_size = 32768,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN |
+ FEATURE_WRSR_EXT | FEATURE_WRSR2,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -6754,7 +6755,7 @@ const struct flashchip flashchips[] = {
.total_size = 4096,
.page_size = 256,
/* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */
- .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
diff --git a/spi.h b/spi.h
index 09da5795..845b6c2a 100644
--- a/spi.h
+++ b/spi.h
@@ -131,6 +131,11 @@
#define JEDEC_RDSR_OUTSIZE 0x01
#define JEDEC_RDSR_INSIZE 0x01
+/* Read Status Register 2 */
+#define JEDEC_RDSR2 0x35
+#define JEDEC_RDSR2_OUTSIZE 0x01
+#define JEDEC_RDSR2_INSIZE 0x01
+
/* Status Register Bits */
#define SPI_SR_WIP (0x01 << 0)
#define SPI_SR_WEL (0x01 << 1)
@@ -146,6 +151,12 @@
#define JEDEC_WRSR 0x01
#define JEDEC_WRSR_OUTSIZE 0x02
#define JEDEC_WRSR_INSIZE 0x00
+#define JEDEC_WRSR_EXT_OUTSIZE 0x03
+
+/* Write Status Register 2 */
+#define JEDEC_WRSR2 0x31
+#define JEDEC_WRSR2_OUTSIZE 0x02
+#define JEDEC_WRSR2_INSIZE 0x00
/* Enter 4-byte Address Mode */
#define JEDEC_ENTER_4_BYTE_ADDR_MODE 0xB7
diff --git a/spi25_statusreg.c b/spi25_statusreg.c
index 0d7bc25b..31d6c769 100644
--- a/spi25_statusreg.c
+++ b/spi25_statusreg.c
@@ -101,6 +101,33 @@ int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t
write_cmd[1] = value;
write_cmd_len = JEDEC_WRSR_OUTSIZE;
break;
+ case STATUS2:
+ if (feature_bits & FEATURE_WRSR2) {
+ write_cmd[0] = JEDEC_WRSR2;
+ write_cmd[1] = value;
+ write_cmd_len = JEDEC_WRSR2_OUTSIZE;
+ break;
+ }
+ if (feature_bits & FEATURE_WRSR_EXT) {
+ /*
+ * Writing SR2 with an extended WRSR command requires
+ * writing SR1 along with SR2, so just read SR1 and
+ * write it back
+ */
+ uint8_t sr1;
+
+ if (spi_read_register(flash, STATUS1, &sr1)) {
+ msg_cerr("Writing SR2 failed: failed to read SR1 for writeback.\n");
+ return 1;
+ }
+ write_cmd[0] = JEDEC_WRSR;
+ write_cmd[1] = sr1;
+ write_cmd[2] = value;
+ write_cmd_len = JEDEC_WRSR_EXT_OUTSIZE;
+ break;
+ }
+ msg_cerr("Cannot write SR2: unsupported by chip\n");
+ return 1;
default:
msg_cerr("Cannot write register: unknown register\n");
return 1;
@@ -122,12 +149,20 @@ int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t
int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value)
{
+ int feature_bits = flash->chip->feature_bits;
uint8_t read_cmd;
switch (reg) {
case STATUS1:
read_cmd = JEDEC_RDSR;
break;
+ case STATUS2:
+ if (feature_bits & (FEATURE_WRSR_EXT | FEATURE_WRSR2)) {
+ read_cmd = JEDEC_RDSR2;
+ break;
+ }
+ msg_cerr("Cannot read SR2: unsupported by chip\n");
+ return 1;
default:
msg_cerr("Cannot read register: unknown register\n");
return 1;