spi25: Try to set volatile quad-enable (QE) automatically
Some chips have a volatile QE bit. Setting this won't wear the status/
configuration register, so we'll try to do so automatically.
Change-Id: I6a4b864d7af1f3ecedd95524f127b5486f999933
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/191
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/include/flash.h b/include/flash.h
index fb64304..9743e3e 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -461,6 +461,7 @@
int address_high_byte;
bool in_4ba_mode;
bool in_qpi_mode;
+ bool volatile_qe_enabled;
/* For SPI flash chips, we dynamically select the fast-read operation. */
struct spi_read_op *spi_fast_read;
diff --git a/spi25_prepare.c b/spi25_prepare.c
index 6ad1f7f..3efc83b 100644
--- a/spi25_prepare.c
+++ b/spi25_prepare.c
@@ -110,15 +110,27 @@
return 0;
/* Check QE bit if present */
+ flash->volatile_qe_enabled = false;
if (flash->chip->reg_bits.qe.reg != INVALID_REG) {
const struct reg_bit_info qe = flash->chip->reg_bits.qe;
+ const uint8_t mask = 1 << qe.bit_index;
uint8_t reg_val;
if (spi_read_register(flash, qe.reg, ®_val)) {
- msg_cwarn("Failed read chip register!\n");
reg_val = 0;
+ } else if (!(reg_val & mask) &&
+ (flash->chip->feature_bits & FEATURE_WRSR_EWSR)) {
+ msg_pdbg("Trying to set volatile quad-enable (QE).\n");
+ reg_val |= mask;
+ if (spi_write_register(flash, qe.reg, reg_val, WRSR_VOLATILE_BITS) ||
+ spi_read_register(flash, qe.reg, ®_val)) {
+ reg_val = 0;
+ } else if (reg_val & mask) {
+ flash->volatile_qe_enabled = true;
+ }
}
- if (!(reg_val & 1 << qe.bit_index)) {
+
+ if (!(reg_val & mask)) {
msg_cinfo("Quad-enable (QE) bit is unknown or unset, disabling quad i/o.\n");
flash->chip->feature_bits &= ~FEATURE_ANY_QUAD;
} else {
@@ -267,5 +279,15 @@
if (spi_exit_qpi(flash))
msg_cwarn("Failed to exit QPI mode!\n");
}
+ if (flash->volatile_qe_enabled) {
+ msg_pdbg("Trying to restore volatile quad-enable (QE) state.\n");
+ const struct reg_bit_info qe = flash->chip->reg_bits.qe;
+ uint8_t reg_val;
+
+ if (!spi_read_register(flash, qe.reg, ®_val)) {
+ reg_val &= ~(1 << qe.bit_index);
+ spi_write_register(flash, qe.reg, reg_val, WRSR_VOLATILE_BITS);
+ }
+ }
free(flash->spi_fast_read);
}