- Move all functions related to SPI status registers to a new file spi25_status_register.c. This includes the generic as well as the SST-specificfunctions from spi25.c and the chip-specific functions from a25.c and at25.c. - introduce * spi_prettyprint_status_register_hex() * spi_prettyprint_status_register_bpl() * spi_prettyprint_status_register_plain() Use the latter on every compatible flash chip that has no better printlock function set and get rid of the implicit pretty printing in the SPI probing functions. - remove * spi_prettyprint_status_register_common() * spi_prettyprint_status_register_amic_a25lq032() because it can be fully substituted with spi_prettyprint_status_register_amic_a25l032(). * spi_prettyprint_status_register() (old switch, no longer needed) - promote and export spi_prettyprint_status_register_st_m25p() as spi_prettyprint_status_register_default_bp3(). - add #define TEST_BAD_REW and use it for a number of Atmel chips which had only TEST_BAD_READ set even though they dont have erasers or a write function set.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- Makefile | 4 +- a25.c | 100 --------- at25.c | 281 -------------------------- chipdrivers.h | 41 ++-- flash.h | 1 + flashchips.c | 140 +++++++++++-- spi25.c | 294 +-------------------------- spi25_statusreg.c | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 733 insertions(+), 712 deletions(-) delete mode 100644 a25.c delete mode 100644 at25.c create mode 100644 spi25_statusreg.c
diff --git a/Makefile b/Makefile index 9309ce5..de7ad84 100644 --- a/Makefile +++ b/Makefile @@ -284,8 +284,8 @@ endif
CHIP_OBJS = jedec.o stm50flw0x0x.o w39.o w29ee011.o \ sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \ - sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o \ - a25.o at25.o opaque.o sfdp.o en29lv640b.o + sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \ + opaque.o sfdp.o en29lv640b.o
############################################################################### # Library code. diff --git a/a25.c b/a25.c deleted file mode 100644 index 2264157..0000000 --- a/a25.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2010 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "flash.h" -#include "chipdrivers.h" -#include "spi.h" - -/* Prettyprint the status register. Works for AMIC A25L series. */ - -int spi_prettyprint_status_register_amic_a25l05p(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_srwd(status); - spi_prettyprint_status_register_bit(status, 6); - spi_prettyprint_status_register_bit(status, 5); - spi_prettyprint_status_register_bit(status, 4); - spi_prettyprint_status_register_bp(status, 1); - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_prettyprint_status_register_amic_a25l40p(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_srwd(status); - spi_prettyprint_status_register_bit(status, 6); - spi_prettyprint_status_register_bit(status, 5); - spi_prettyprint_status_register_bp(status, 2); - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_srwd(status); - msg_cdbg("Chip status register: Sector Protect Size (SEC) " - "is %i KB\n", (status & (1 << 6)) ? 4 : 64); - msg_cdbg("Chip status register: Top/Bottom (TB) " - "is %s\n", (status & (1 << 5)) ? "bottom" : "top"); - spi_prettyprint_status_register_bp(status, 2); - spi_prettyprint_status_register_welwip(status); - msg_cdbg("Chip status register 2 is NOT decoded!\n"); - return 0; -} - -int spi_prettyprint_status_register_amic_a25lq032(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_srwd(status); - msg_cdbg("Chip status register: Sector Protect Size (SEC) " - "is %i KB\n", (status & (1 << 6)) ? 4 : 64); - msg_cdbg("Chip status register: Top/Bottom (TB) " - "is %s\n", (status & (1 << 5)) ? "bottom" : "top"); - spi_prettyprint_status_register_bp(status, 2); - spi_prettyprint_status_register_welwip(status); - msg_cdbg("Chip status register 2 is NOT decoded!\n"); - return 0; -} - -/* FIXME: spi_disable_blockprotect is incorrect but works fine for chips using - * spi_prettyprint_status_register_amic_a25l05p or - * spi_prettyprint_status_register_amic_a25l40p. - * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using - * spi_prettyprint_status_register_amic_a25l032 or - * spi_prettyprint_status_register_amic_a25lq032 if those have locks controlled - * by the second status register. - */ diff --git a/at25.c b/at25.c deleted file mode 100644 index 803e7e4..0000000 --- a/at25.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2010 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "flash.h" -#include "chipdrivers.h" -#include "spi.h" - -/* Prettyprint the status register. Works for Atmel A25/A26 series. */ - -static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status) -{ - msg_cdbg("Chip status register: Write Protect Enable (WPEN) " - "is %sset\n", (status & (1 << 7)) ? "" : "not "); -} - -static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status) -{ - msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) " - "is %sset\n", (status & (1 << 7)) ? "" : "not "); -} - -static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status) -{ - msg_cdbg("Chip status register: Erase/Program Error (EPE) " - "is %sset\n", (status & (1 << 5)) ? "" : "not "); - msg_cdbg("Chip status register: WP# pin (WPP) " - "is %sasserted\n", (status & (1 << 4)) ? "not " : ""); -} - -static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status) -{ - msg_cdbg("Chip status register: Software Protection Status (SWP): "); - switch (status & (3 << 2)) { - case 0x0 << 2: - msg_cdbg("no sectors are protected\n"); - break; - case 0x1 << 2: - msg_cdbg("some sectors are protected\n"); - /* FIXME: Read individual Sector Protection Registers. */ - break; - case 0x3 << 2: - msg_cdbg("all sectors are protected\n"); - break; - default: - msg_cdbg("reserved for future use\n"); - break; - } -} - -int spi_prettyprint_status_register_at25df(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_atmel_at25_srpl(status); - spi_prettyprint_status_register_bit(status, 6); - spi_prettyprint_status_register_atmel_at25_epewpp(status); - spi_prettyprint_status_register_atmel_at25_swp(status); - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash) -{ - /* FIXME: We should check the security lockdown. */ - msg_cdbg("Ignoring security lockdown (if present)\n"); - msg_cdbg("Ignoring status register byte 2\n"); - return spi_prettyprint_status_register_at25df(flash); -} - -int spi_prettyprint_status_register_at25f512b(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_atmel_at25_srpl(status); - spi_prettyprint_status_register_bit(status, 6); - spi_prettyprint_status_register_atmel_at25_epewpp(status); - spi_prettyprint_status_register_bit(status, 3); - spi_prettyprint_status_register_bp(status, 0); - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_prettyprint_status_register_at25fs010(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_atmel_at25_wpen(status); - msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is " - "%sset\n", (status & (1 << 6)) ? "" : "not "); - msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is " - "%sset\n", (status & (1 << 5)) ? "" : "not "); - spi_prettyprint_status_register_bit(status, 4); - msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is " - "%sset\n", (status & (1 << 3)) ? "" : "not "); - msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is " - "%sset\n", (status & (1 << 2)) ? "" : "not "); - /* FIXME: Pretty-print detailed sector protection status. */ - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_prettyprint_status_register_at25fs040(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_atmel_at25_wpen(status); - spi_prettyprint_status_register_bp(status, 4); - /* FIXME: Pretty-print detailed sector protection status. */ - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_prettyprint_status_register_atmel_at26df081a(struct flashctx *flash) -{ - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - - spi_prettyprint_status_register_atmel_at25_srpl(status); - msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) " - "is %sset\n", (status & (1 << 6)) ? "" : "not "); - spi_prettyprint_status_register_atmel_at25_epewpp(status); - spi_prettyprint_status_register_atmel_at25_swp(status); - spi_prettyprint_status_register_welwip(status); - return 0; -} - -int spi_disable_blockprotect_at25df(struct flashctx *flash) -{ - uint8_t status; - int result; - - status = spi_read_status_register(flash); - /* If block protection is disabled, stop here. */ - if ((status & (3 << 2)) == 0) - return 0; - - msg_cdbg("Some block protection in effect, disabling... "); - if (status & (1 << 7)) { - msg_cdbg("Need to disable Sector Protection Register Lock\n"); - if ((status & (1 << 4)) == 0) { - msg_cerr("WP# pin is active, disabling " - "write protection is impossible.\n"); - return 1; - } - /* All bits except bit 7 (SPRL) are readonly. */ - result = spi_write_status_register(flash, status & ~(1 << 7)); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - - } - /* Global unprotect. Make sure to mask SPRL as well. */ - result = spi_write_status_register(flash, status & ~0xbc); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - status = spi_read_status_register(flash); - if ((status & (3 << 2)) != 0) { - msg_cerr("Block protection could not be disabled!\n"); - return 1; - } - msg_cdbg("done.\n"); - return 0; -} - -int spi_disable_blockprotect_at25df_sec(struct flashctx *flash) -{ - /* FIXME: We should check the security lockdown. */ - msg_cinfo("Ignoring security lockdown (if present)\n"); - return spi_disable_blockprotect_at25df(flash); -} - -int spi_disable_blockprotect_at25f512b(struct flashctx *flash) -{ - /* spi_disable_blockprotect_at25df is not really the right way to do - * this, but the side effects of said function work here as well. - */ - return spi_disable_blockprotect_at25df(flash); -} - -int spi_disable_blockprotect_at25fs010(struct flashctx *flash) -{ - uint8_t status; - int result; - - status = spi_read_status_register(flash); - /* If block protection is disabled, stop here. */ - if ((status & 0x6c) == 0) - return 0; - - msg_cdbg("Some block protection in effect, disabling... "); - if (status & (1 << 7)) { - msg_cdbg("Need to disable Status Register Write Protect\n"); - /* Clear bit 7 (WPEN). */ - result = spi_write_status_register(flash, status & ~(1 << 7)); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - } - /* Global unprotect. Make sure to mask WPEN as well. */ - result = spi_write_status_register(flash, status & ~0xec); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - status = spi_read_status_register(flash); - if ((status & 0x6c) != 0) { - msg_cerr("Block protection could not be disabled!\n"); - return 1; - } - msg_cdbg("done.\n"); - return 0; -} - -int spi_disable_blockprotect_at25fs040(struct flashctx *flash) -{ - uint8_t status; - int result; - - status = spi_read_status_register(flash); - /* If block protection is disabled, stop here. */ - if ((status & 0x7c) == 0) - return 0; - - msg_cdbg("Some block protection in effect, disabling... "); - if (status & (1 << 7)) { - msg_cdbg("Need to disable Status Register Write Protect\n"); - /* Clear bit 7 (WPEN). */ - result = spi_write_status_register(flash, status & ~(1 << 7)); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - } - /* Global unprotect. Make sure to mask WPEN as well. */ - result = spi_write_status_register(flash, status & ~0xfc); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - status = spi_read_status_register(flash); - if ((status & 0x7c) != 0) { - msg_cerr("Block protection could not be disabled!\n"); - return 1; - } - msg_cdbg("done.\n"); - return 0; -} diff --git a/chipdrivers.h b/chipdrivers.h index 1ef4959..d5cd2ea 100644 --- a/chipdrivers.h +++ b/chipdrivers.h @@ -49,47 +49,44 @@ int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int b int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int blocklen); erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode); int spi_chip_write_1(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); -uint8_t spi_read_status_register(struct flashctx *flash); -int spi_write_status_register(struct flashctx *flash, int status); -void spi_prettyprint_status_register_bit(uint8_t status, int bit); -void spi_prettyprint_status_register_bp(uint8_t status, int bp); -void spi_prettyprint_status_register_srwd(uint8_t status); -void spi_prettyprint_status_register_welwip(uint8_t status); -int spi_prettyprint_status_register(struct flashctx *flash); -int spi_disable_blockprotect(struct flashctx *flash); int spi_byte_program(struct flashctx *flash, unsigned int addr, uint8_t databyte); int spi_nbyte_program(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len); 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, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
-/* sfdp.c */ -int probe_spi_sfdp(struct flashctx *flash); - -/* opaque.c */ -int probe_opaque(struct flashctx *flash); -int read_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); -int write_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); -int erase_opaque(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen); - -/* a25.c */ +/* spi25_sr.c */ +uint8_t spi_read_status_register(struct flashctx *flash); +int spi_write_status_register(struct flashctx *flash, int status); +int spi_prettyprint_status_register_plain(struct flashctx *flash); +int spi_prettyprint_status_register_default_bp3(struct flashctx *flash); +int spi_disable_blockprotect(struct flashctx *flash); int spi_prettyprint_status_register_amic_a25l05p(struct flashctx *flash); int spi_prettyprint_status_register_amic_a25l40p(struct flashctx *flash); int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash); -int spi_prettyprint_status_register_amic_a25lq032(struct flashctx *flash); - -/* at25.c */ int spi_prettyprint_status_register_at25df(struct flashctx *flash); int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash); int spi_prettyprint_status_register_at25f512b(struct flashctx *flash); int spi_prettyprint_status_register_at25fs010(struct flashctx *flash); int spi_prettyprint_status_register_at25fs040(struct flashctx *flash); -int spi_prettyprint_status_register_atmel_at26df081a(struct flashctx *flash); +int spi_prettyprint_status_register_at26df081a(struct flashctx *flash); int spi_disable_blockprotect_at25df(struct flashctx *flash); int spi_disable_blockprotect_at25df_sec(struct flashctx *flash); int spi_disable_blockprotect_at25f512b(struct flashctx *flash); int spi_disable_blockprotect_at25fs010(struct flashctx *flash); int spi_disable_blockprotect_at25fs040(struct flashctx *flash); +int spi_prettyprint_status_register_sst25(struct flashctx *flash); +int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash); +int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash); + +/* sfdp.c */ +int probe_spi_sfdp(struct flashctx *flash); + +/* opaque.c */ +int probe_opaque(struct flashctx *flash); +int read_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); +int write_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); +int erase_opaque(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
/* 82802ab.c */ uint8_t wait_82802ab(struct flashctx *flash); diff --git a/flash.h b/flash.h index 4913536..baa6251 100644 --- a/flash.h +++ b/flash.h @@ -188,6 +188,7 @@ struct flashctx { #define TEST_BAD_READ (1 << 5) #define TEST_BAD_ERASE (1 << 6) #define TEST_BAD_WRITE (1 << 7) +#define TEST_BAD_REW (TEST_BAD_READ | TEST_BAD_ERASE | TEST_BAD_WRITE) #define TEST_BAD_PREW (TEST_BAD_PROBE | TEST_BAD_READ | TEST_BAD_ERASE | TEST_BAD_WRITE) #define TEST_BAD_MASK 0xf0
diff --git a/flashchips.c b/flashchips.c index a6c2004..c28a6c2 100644 --- a/flashchips.c +++ b/flashchips.c @@ -1194,7 +1194,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, - .printlock = spi_prettyprint_status_register_amic_a25lq032, + .printlock = spi_prettyprint_status_register_amic_a25l032, .unlock = NULL, /* Two status reg bytes (read with 0x35 and 0x05) */ .write = spi_chip_write_256, .read = spi_chip_read, @@ -1795,7 +1795,7 @@ const struct flashchip flashchips[] = { .total_size = 512, .page_size = 256, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_UNTESTED, + .tested = TEST_BAD_WRITE, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .block_erasers = @@ -1805,6 +1805,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_20, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .write = NULL /* Incompatible Page write */, .read = spi_chip_read, .voltage = {2700, 3600}, /* 3.0-3.6V for higher speed, 2.7-3.6V normal */ @@ -1841,7 +1842,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, - .printlock = spi_prettyprint_status_register_atmel_at26df081a, + .printlock = spi_prettyprint_status_register_at26df081a, .unlock = spi_disable_blockprotect_at25df, .write = spi_chip_write_256, .read = spi_chip_read, @@ -1917,7 +1918,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, - .printlock = spi_prettyprint_status_register_atmel_at26df081a, + .printlock = spi_prettyprint_status_register_at26df081a, .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -1937,7 +1938,7 @@ const struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .printlock = spi_prettyprint_status_register_atmel_at26df081a, + .printlock = spi_prettyprint_status_register_at26df081a, .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -1951,7 +1952,7 @@ const struct flashchip flashchips[] = { .model_id = ATMEL_AT26F004, .total_size = 512, .page_size = 256, - .tested = TEST_UNTESTED, + .tested = TEST_BAD_WRITE, .feature_bits = FEATURE_WRSR_WREN, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, @@ -1974,6 +1975,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .write = NULL /* Incompatible Page write */, .read = spi_chip_read, .voltage = {2700, 3600}, @@ -2084,7 +2086,7 @@ const struct flashchip flashchips[] = { .total_size = 16896 /* No power of two sizes */, .page_size = 1056 /* No power of two sizes */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL /* Incompatible Page write */, @@ -2101,7 +2103,7 @@ const struct flashchip flashchips[] = { .total_size = 128 /* Size can only be determined from status register */, .page_size = 256 /* Size can only be determined from status register */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2118,7 +2120,7 @@ const struct flashchip flashchips[] = { .total_size = 256 /* Size can only be determined from status register */, .page_size = 256 /* Size can only be determined from status register */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2135,7 +2137,7 @@ const struct flashchip flashchips[] = { .total_size = 512 /* Size can only be determined from status register */, .page_size = 256 /* Size can only be determined from status register */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2152,7 +2154,7 @@ const struct flashchip flashchips[] = { .total_size = 1024 /* Size can only be determined from status register */, .page_size = 256 /* Size can only be determined from status register */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2169,7 +2171,7 @@ const struct flashchip flashchips[] = { .total_size = 2048 /* Size can only be determined from status register */, .page_size = 512 /* Size can only be determined from status register */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2186,7 +2188,7 @@ const struct flashchip flashchips[] = { .total_size = 4224 /* No power of two sizes */, .page_size = 528 /* No power of two sizes */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2205,7 +2207,7 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ .feature_bits = FEATURE_OTP, - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2222,7 +2224,7 @@ const struct flashchip flashchips[] = { .total_size = 8192 /* Size can only be determined from status register */, .page_size = 1024 /* Size can only be determined from status register */, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ - .tested = TEST_BAD_READ, + .tested = TEST_BAD_REW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, .write = NULL, @@ -2615,6 +2617,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, .read = spi_chip_read, @@ -2648,6 +2651,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2681,6 +2685,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2714,6 +2719,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2747,6 +2753,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2781,6 +2788,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2815,6 +2823,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2849,6 +2858,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2883,6 +2893,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2917,6 +2928,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2951,6 +2963,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -2985,6 +2998,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3019,6 +3033,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3053,6 +3068,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3087,6 +3103,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3121,6 +3138,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3155,6 +3173,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3192,6 +3211,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3229,6 +3249,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3266,6 +3287,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3300,6 +3322,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3334,6 +3357,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3368,6 +3392,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3402,6 +3427,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3436,6 +3462,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3471,6 +3498,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3506,6 +3534,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3547,6 +3576,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3582,6 +3612,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3617,6 +3648,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3652,6 +3684,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3687,6 +3720,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -3723,6 +3757,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4011,6 +4046,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4048,6 +4084,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4086,6 +4123,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4124,6 +4162,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4162,6 +4201,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4200,6 +4240,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4237,6 +4278,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4273,6 +4315,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4665,6 +4708,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4699,6 +4743,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4736,6 +4781,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4773,6 +4819,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4810,6 +4857,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4847,6 +4895,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4881,6 +4930,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4915,6 +4965,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4949,6 +5000,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -4983,6 +5035,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5017,6 +5070,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5051,6 +5105,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5455,6 +5510,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5486,6 +5542,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5517,6 +5574,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5548,6 +5606,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5579,6 +5638,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5609,6 +5669,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5639,6 +5700,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5676,6 +5738,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5707,6 +5770,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5738,6 +5802,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5775,6 +5840,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -5806,6 +5872,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6079,6 +6146,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6169,6 +6237,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6197,6 +6266,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6225,6 +6295,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6253,6 +6324,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6281,6 +6353,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6312,6 +6385,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_60, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ .read = spi_chip_read, @@ -6343,6 +6417,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_60, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ .read = spi_chip_read, @@ -6374,6 +6449,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_60, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, .read = spi_chip_read, @@ -6411,6 +6487,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_sst25vf016, .unlock = spi_disable_blockprotect, .write = spi_aai_write, .read = spi_chip_read, @@ -6448,6 +6525,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_aai_write, .read = spi_chip_read, @@ -6485,6 +6563,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -6516,6 +6595,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_60, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ .read = spi_chip_read, @@ -6553,6 +6633,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_sst25vf040b, .unlock = spi_disable_blockprotect, .write = spi_aai_write, .read = spi_chip_read, @@ -6590,6 +6671,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_sst25vf040b, .unlock = spi_disable_blockprotect, .write = spi_aai_write, .read = spi_chip_read, @@ -6627,6 +6709,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, }, }, + .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_aai_write, .read = spi_chip_read, @@ -7439,6 +7522,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7472,6 +7556,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, /* 128 */ .read = spi_chip_read, @@ -7500,6 +7585,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7529,6 +7615,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_1, /* 128 */ .read = spi_chip_read, @@ -7557,6 +7644,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7585,6 +7673,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7613,6 +7702,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7640,6 +7730,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7668,6 +7759,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7696,6 +7788,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7724,6 +7817,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7752,6 +7846,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_default_bp3, /* TODO: check */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7784,6 +7879,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7814,6 +7910,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -7845,6 +7942,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8662,6 +8760,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8700,6 +8799,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8738,6 +8838,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8776,6 +8877,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8813,6 +8915,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8843,6 +8946,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8874,6 +8978,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8905,6 +9010,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8936,6 +9042,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -8973,6 +9080,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -9010,6 +9118,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, @@ -9047,6 +9156,7 @@ const struct flashchip flashchips[] = { .block_erase = spi_block_erase_c7, } }, + .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ .unlock = spi_disable_blockprotect, .write = spi_chip_write_256, .read = spi_chip_read, diff --git a/spi25.c b/spi25.c index a65f548..38f9b2b 100644 --- a/spi25.c +++ b/spi25.c @@ -148,14 +148,8 @@ static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
- if (id1 == chip->manufacture_id && id2 == chip->model_id) { - /* Print the status register to tell the - * user about possible write protection. - */ - spi_prettyprint_status_register(flash); - + if (id1 == chip->manufacture_id && id2 == chip->model_id) return 1; - }
/* Test if this is a pure vendor match. */ if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id) @@ -210,14 +204,8 @@ int probe_spi_rems(struct flashctx *flash)
msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
- if (id1 == chip->manufacture_id && id2 == chip->model_id) { - /* Print the status register to tell the - * user about possible write protection. - */ - spi_prettyprint_status_register(flash); - + if (id1 == chip->manufacture_id && id2 == chip->model_id) return 1; - }
/* Test if this is a pure vendor match. */ if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id) @@ -268,10 +256,6 @@ int probe_spi_res1(struct flashctx *flash) if (id2 != flash->chip->model_id) return 0;
- /* Print the status register to tell the - * user about possible write protection. - */ - spi_prettyprint_status_register(flash); return 1; }
@@ -292,168 +276,9 @@ int probe_spi_res2(struct flashctx *flash) if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) return 0;
- /* Print the status register to tell the - * user about possible write protection. - */ - spi_prettyprint_status_register(flash); return 1; }
-uint8_t spi_read_status_register(struct flashctx *flash) -{ - static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR }; - /* FIXME: No workarounds for driver/hardware bugs in generic code. */ - unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */ - int ret; - - /* Read Status Register */ - ret = spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, - readarr); - if (ret) - msg_cerr("RDSR failed!\n"); - - return readarr[0]; -} - -/* Common highest bit: Status Register Write Disable (SRWD). */ -void spi_prettyprint_status_register_srwd(uint8_t status) -{ - msg_cdbg("Chip status register: Status Register Write Disable (SRWD) is %sset\n", - (status & (1 << 7)) ? "" : "not "); -} - -void spi_prettyprint_status_register_welwip(uint8_t status) -{ - msg_cdbg("Chip status register: Write Enable Latch (WEL) is " - "%sset\n", (status & (1 << 1)) ? "" : "not "); - msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is " - "%sset\n", (status & (1 << 0)) ? "" : "not "); -} - -/* Prettyprint the status register. Common definitions. */ -void spi_prettyprint_status_register_bp(uint8_t status, int bp) -{ - switch (bp) { - /* Fall through. */ - case 4: - msg_cdbg("Chip status register: Block Protect 4 (BP4) " - "is %sset\n", (status & (1 << 5)) ? "" : "not "); - case 3: - msg_cdbg("Chip status register: Block Protect 3 (BP3) " - "is %sset\n", (status & (1 << 5)) ? "" : "not "); - case 2: - msg_cdbg("Chip status register: Block Protect 2 (BP2) " - "is %sset\n", (status & (1 << 4)) ? "" : "not "); - case 1: - msg_cdbg("Chip status register: Block Protect 1 (BP1) " - "is %sset\n", (status & (1 << 3)) ? "" : "not "); - case 0: - msg_cdbg("Chip status register: Block Protect 0 (BP0) " - "is %sset\n", (status & (1 << 2)) ? "" : "not "); - } -} - -/* Prettyprint the status register. Unnamed bits. */ -void spi_prettyprint_status_register_bit(uint8_t status, int bit) -{ - msg_cdbg("Chip status register: Bit %i " - "is %sset\n", bit, (status & (1 << bit)) ? "" : "not "); -} - -static void spi_prettyprint_status_register_common(uint8_t status) -{ - spi_prettyprint_status_register_bp(status, 3); - spi_prettyprint_status_register_welwip(status); -} - -/* Prettyprint the status register. Works for - * ST M25P series - * MX MX25L series - */ -void spi_prettyprint_status_register_st_m25p(uint8_t status) -{ - spi_prettyprint_status_register_srwd(status); - spi_prettyprint_status_register_bit(status, 6); - spi_prettyprint_status_register_common(status); -} - -void spi_prettyprint_status_register_sst25(uint8_t status) -{ - msg_cdbg("Chip status register: Block Protect Write Disable " - "(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not "); - msg_cdbg("Chip status register: Auto Address Increment Programming " - "(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not "); - spi_prettyprint_status_register_common(status); -} - -/* Prettyprint the status register. Works for - * SST 25VF016 - */ -void spi_prettyprint_status_register_sst25vf016(uint8_t status) -{ - static const char *const bpt[] = { - "none", - "1F0000H-1FFFFFH", - "1E0000H-1FFFFFH", - "1C0000H-1FFFFFH", - "180000H-1FFFFFH", - "100000H-1FFFFFH", - "all", "all" - }; - spi_prettyprint_status_register_sst25(status); - msg_cdbg("Resulting block protection : %s\n", - bpt[(status & 0x1c) >> 2]); -} - -void spi_prettyprint_status_register_sst25vf040b(uint8_t status) -{ - static const char *const bpt[] = { - "none", - "0x70000-0x7ffff", - "0x60000-0x7ffff", - "0x40000-0x7ffff", - "all blocks", "all blocks", "all blocks", "all blocks" - }; - spi_prettyprint_status_register_sst25(status); - msg_cdbg("Resulting block protection : %s\n", - bpt[(status & 0x1c) >> 2]); -} - -int spi_prettyprint_status_register(struct flashctx *flash) -{ - const struct flashchip *chip = flash->chip; - uint8_t status; - - status = spi_read_status_register(flash); - msg_cdbg("Chip status register is %02x\n", status); - switch (chip->manufacture_id) { - case ST_ID: - if (((chip->model_id & 0xff00) == 0x2000) || - ((chip->model_id & 0xff00) == 0x2500)) - spi_prettyprint_status_register_st_m25p(status); - break; - case MACRONIX_ID: - if ((chip->model_id & 0xff00) == 0x2000) - spi_prettyprint_status_register_st_m25p(status); - break; - case SST_ID: - switch (chip->model_id) { - case 0x2541: - spi_prettyprint_status_register_sst25vf016(status); - break; - case 0x8d: - case 0x258d: - spi_prettyprint_status_register_sst25vf040b(status); - break; - default: - spi_prettyprint_status_register_sst25(status); - break; - } - break; - } - return 0; -} - int spi_chip_erase_60(struct flashctx *flash) { int result; @@ -799,92 +624,6 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) } }
-int spi_write_status_enable(struct flashctx *flash) -{ - static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR }; - int result; - - /* Send EWSR (Enable Write Status Register). */ - result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL); - - if (result) - msg_cerr("%s failed\n", __func__); - - return result; -} - -/* - * This is according the SST25VF016 datasheet, who knows it is more - * generic that this... - */ -static int spi_write_status_register_flag(struct flashctx *flash, int status, const unsigned char enable_opcode) -{ - int result; - int i = 0; - /* - * WRSR requires either EWSR or WREN depending on chip type. - * The code below relies on the fact hat EWSR and WREN have the same - * INSIZE and OUTSIZE. - */ - struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ enable_opcode }, - .readcnt = 0, - .readarr = NULL, - }, { - .writecnt = JEDEC_WRSR_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status }, - .readcnt = 0, - .readarr = NULL, - }, { - .writecnt = 0, - .writearr = NULL, - .readcnt = 0, - .readarr = NULL, - }}; - - result = spi_send_multicommand(flash, cmds); - if (result) { - msg_cerr("%s failed during command execution\n", __func__); - /* No point in waiting for the command to complete if execution - * failed. - */ - return result; - } - /* WRSR performs a self-timed erase before the changes take effect. - * This may take 50-85 ms in most cases, and some chips apparently - * allow running RDSR only once. Therefore pick an initial delay of - * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed. - */ - programmer_delay(100 * 1000); - while (spi_read_status_register(flash) & SPI_SR_WIP) { - if (++i > 490) { - msg_cerr("Error: WIP bit after WRSR never cleared\n"); - return TIMEOUT_ERROR; - } - programmer_delay(10 * 1000); - } - return 0; -} - -int spi_write_status_register(struct flashctx *flash, int status) -{ - int feature_bits = flash->chip->feature_bits; - int ret = 1; - - if (!(feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) { - msg_cdbg("Missing status register write definition, assuming " - "EWSR is needed\n"); - feature_bits |= FEATURE_WRSR_EWSR; - } - if (feature_bits & FEATURE_WRSR_WREN) - ret = spi_write_status_register_flag(flash, status, JEDEC_WREN); - if (ret && (feature_bits & FEATURE_WRSR_EWSR)) - ret = spi_write_status_register_flag(flash, status, JEDEC_EWSR); - return ret; -} - int spi_byte_program(struct flashctx *flash, unsigned int addr, uint8_t databyte) { @@ -969,35 +708,6 @@ int spi_nbyte_program(struct flashctx *flash, unsigned int addr, uint8_t *bytes, return result; }
-/* A generic brute-force block protection disable works like this: - * Write 0x00 to the status register. Check if any locks are still set (that - * part is chip specific). Repeat once. - */ -int spi_disable_blockprotect(struct flashctx *flash) -{ - uint8_t status; - int result; - - status = spi_read_status_register(flash); - /* If block protection is disabled, stop here. */ - if ((status & 0x3c) == 0) - return 0; - - msg_cdbg("Some block protection in effect, disabling... "); - result = spi_write_status_register(flash, status & ~0x3c); - if (result) { - msg_cerr("spi_write_status_register failed.\n"); - return result; - } - status = spi_read_status_register(flash); - if ((status & 0x3c) != 0) { - msg_cerr("Block protection could not be disabled!\n"); - return 1; - } - msg_cdbg("done.\n"); - return 0; -} - int spi_nbyte_read(struct flashctx *flash, unsigned int address, uint8_t *bytes, unsigned int len) { diff --git a/spi25_statusreg.c b/spi25_statusreg.c new file mode 100644 index 0000000..ce66c3b --- /dev/null +++ b/spi25_statusreg.c @@ -0,0 +1,584 @@ +/* + * This file is part of the flashrom project. + * It handles everything related to status registers of the JEDEC family 25. + * + * Copyright (C) 2007, 2008, 2009, 2010 Carl-Daniel Hailfinger + * Copyright (C) 2008 coresystems GmbH + * Copyright (C) 2008 Ronald Hoogenboom ronald@zonnet.nl + * Copyright (C) 2012 Stefan Tauner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "flash.h" +#include "chipdrivers.h" +#include "spi.h" + +/* === Generic functions === */ +int spi_write_status_enable(struct flashctx *flash) +{ + static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR }; + int result; + + /* Send EWSR (Enable Write Status Register). */ + result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL); + + if (result) + msg_cerr("%s failed\n", __func__); + + return result; +} + +static int spi_write_status_register_flag(struct flashctx *flash, int status, const unsigned char enable_opcode) +{ + int result; + int i = 0; + /* + * WRSR requires either EWSR or WREN depending on chip type. + * The code below relies on the fact hat EWSR and WREN have the same + * INSIZE and OUTSIZE. + */ + struct spi_command cmds[] = { + { + .writecnt = JEDEC_WREN_OUTSIZE, + .writearr = (const unsigned char[]){ enable_opcode }, + .readcnt = 0, + .readarr = NULL, + }, { + .writecnt = JEDEC_WRSR_OUTSIZE, + .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status }, + .readcnt = 0, + .readarr = NULL, + }, { + .writecnt = 0, + .writearr = NULL, + .readcnt = 0, + .readarr = NULL, + }}; + + result = spi_send_multicommand(flash, cmds); + if (result) { + msg_cerr("%s failed during command execution\n", __func__); + /* No point in waiting for the command to complete if execution + * failed. + */ + return result; + } + /* WRSR performs a self-timed erase before the changes take effect. + * This may take 50-85 ms in most cases, and some chips apparently + * allow running RDSR only once. Therefore pick an initial delay of + * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed. + */ + programmer_delay(100 * 1000); + while (spi_read_status_register(flash) & SPI_SR_WIP) { + if (++i > 490) { + msg_cerr("Error: WIP bit after WRSR never cleared\n"); + return TIMEOUT_ERROR; + } + programmer_delay(10 * 1000); + } + return 0; +} + +int spi_write_status_register(struct flashctx *flash, int status) +{ + int feature_bits = flash->chip->feature_bits; + int ret = 1; + + if (!(feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) { + msg_cdbg("Missing status register write definition, assuming " + "EWSR is needed\n"); + feature_bits |= FEATURE_WRSR_EWSR; + } + if (feature_bits & FEATURE_WRSR_WREN) + ret = spi_write_status_register_flag(flash, status, JEDEC_WREN); + if (ret && (feature_bits & FEATURE_WRSR_EWSR)) + ret = spi_write_status_register_flag(flash, status, JEDEC_EWSR); + return ret; +} + +uint8_t spi_read_status_register(struct flashctx *flash) +{ + static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR }; + /* FIXME: No workarounds for driver/hardware bugs in generic code. */ + unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */ + int ret; + + /* Read Status Register */ + ret = spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr); + if (ret) + msg_cerr("RDSR failed!\n"); + + return readarr[0]; +} + +/* A generic brute-force block protection disable works like this: + * Write 0x00 to the status register. Check if any locks are still set (that + * part is chip specific). Repeat once. + */ +int spi_disable_blockprotect(struct flashctx *flash) +{ + uint8_t status; + int result; + + status = spi_read_status_register(flash); + /* If block protection is disabled, stop here. */ + if ((status & 0x3c) == 0) + return 0; + + msg_cdbg("Some block protection in effect, disabling... "); + result = spi_write_status_register(flash, status & ~0x3c); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + status = spi_read_status_register(flash); + if ((status & 0x3c) != 0) { + msg_cerr("Block protection could not be disabled!\n"); + return 1; + } + msg_cdbg("done.\n"); + return 0; +} + +static void spi_prettyprint_status_register_hex(uint8_t status) +{ + msg_cdbg("Chip status register is 0x%02x.\n", status); +} + +/* Common highest bit: Status Register Write Disable (SRWD). */ +static void spi_prettyprint_status_register_srwd(uint8_t status) +{ + msg_cdbg("Chip status register: Status Register Write Disable (SRWD) is %sset\n", + (status & (1 << 7)) ? "" : "not "); +} + +/* Common highest bit: Block Protect Write Disable (BPL). */ +static void spi_prettyprint_status_register_bpl(uint8_t status) +{ + msg_cdbg("Chip status register: Block Protect Write Disable (BPL) is %sset\n", + (status & (1 << 7)) ? "" : "not "); +} + +/* Common lowest 2 bits: WEL and WIP. */ +static void spi_prettyprint_status_register_welwip(uint8_t status) +{ + msg_cdbg("Chip status register: Write Enable Latch (WEL) is %sset\n", + (status & (1 << 1)) ? "" : "not "); + msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is %sset\n", + (status & (1 << 0)) ? "" : "not "); +} + +/* Common block protection (BP) bits. */ +static void spi_prettyprint_status_register_bp(uint8_t status, int bp) +{ + switch (bp) { + /* Fall through. */ + case 4: + msg_cdbg("Chip status register: Block Protect 4 (BP4) is %sset\n", + (status & (1 << 5)) ? "" : "not "); + case 3: + msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n", + (status & (1 << 5)) ? "" : "not "); + case 2: + msg_cdbg("Chip status register: Block Protect 2 (BP2) is %sset\n", + (status & (1 << 4)) ? "" : "not "); + case 1: + msg_cdbg("Chip status register: Block Protect 1 (BP1) is %sset\n", + (status & (1 << 3)) ? "" : "not "); + case 0: + msg_cdbg("Chip status register: Block Protect 0 (BP0) is %sset\n", + (status & (1 << 2)) ? "" : "not "); + } +} + +/* Unnamed bits. */ +static void spi_prettyprint_status_register_bit(uint8_t status, int bit) +{ + msg_cdbg("Chip status register: Bit %i is %sset\n", bit, (status & (1 << bit)) ? "" : "not "); +} + +int spi_prettyprint_status_register_plain(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + return 0; +} + +/* Works for many chips of the + * ST M25P series + * MX MX25L series + */ +int spi_prettyprint_status_register_default_bp3(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_srwd(status); + spi_prettyprint_status_register_bit(status, 6); + spi_prettyprint_status_register_bp(status, 3); + spi_prettyprint_status_register_welwip(status); + return 0; +} + +/* === Amic === + * FIXME: spi_disable_blockprotect is incorrect but works fine for chips using + * spi_prettyprint_status_register_amic_a25l05p or + * spi_prettyprint_status_register_amic_a25l40p. + * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using + * spi_prettyprint_status_register_amic_a25l032 if those have locks controlled + * by the second status register. + */ + +int spi_prettyprint_status_register_amic_a25l05p(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_srwd(status); + spi_prettyprint_status_register_bit(status, 6); + spi_prettyprint_status_register_bit(status, 5); + spi_prettyprint_status_register_bit(status, 4); + spi_prettyprint_status_register_bp(status, 1); + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_prettyprint_status_register_amic_a25l40p(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_srwd(status); + spi_prettyprint_status_register_bit(status, 6); + spi_prettyprint_status_register_bit(status, 5); + spi_prettyprint_status_register_bp(status, 2); + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_srwd(status); + msg_cdbg("Chip status register: Sector Protect Size (SEC) is %i KB\n", (status & (1 << 6)) ? 4 : 64); + msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top"); + spi_prettyprint_status_register_bp(status, 2); + spi_prettyprint_status_register_welwip(status); + msg_cdbg("Chip status register 2 is NOT decoded!\n"); + return 0; +} + +/* === Atmel === */ + +static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status) +{ + msg_cdbg("Chip status register: Write Protect Enable (WPEN) is %sset\n", + (status & (1 << 7)) ? "" : "not "); +} + +static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status) +{ + msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) is %sset\n", + (status & (1 << 7)) ? "" : "not "); +} + +static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status) +{ + msg_cdbg("Chip status register: Erase/Program Error (EPE) is %sset\n", + (status & (1 << 5)) ? "" : "not "); + msg_cdbg("Chip status register: WP# pin (WPP) is %sasserted\n", + (status & (1 << 4)) ? "not " : ""); +} + +static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status) +{ + msg_cdbg("Chip status register: Software Protection Status (SWP): "); + switch (status & (3 << 2)) { + case 0x0 << 2: + msg_cdbg("no sectors are protected\n"); + break; + case 0x1 << 2: + msg_cdbg("some sectors are protected\n"); + /* FIXME: Read individual Sector Protection Registers. */ + break; + case 0x3 << 2: + msg_cdbg("all sectors are protected\n"); + break; + default: + msg_cdbg("reserved for future use\n"); + break; + } +} + +int spi_prettyprint_status_register_at25df(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_atmel_at25_srpl(status); + spi_prettyprint_status_register_bit(status, 6); + spi_prettyprint_status_register_atmel_at25_epewpp(status); + spi_prettyprint_status_register_atmel_at25_swp(status); + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash) +{ + /* FIXME: We should check the security lockdown. */ + msg_cdbg("Ignoring security lockdown (if present)\n"); + msg_cdbg("Ignoring status register byte 2\n"); + return spi_prettyprint_status_register_at25df(flash); +} + +int spi_prettyprint_status_register_at25f512b(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_atmel_at25_srpl(status); + spi_prettyprint_status_register_bit(status, 6); + spi_prettyprint_status_register_atmel_at25_epewpp(status); + spi_prettyprint_status_register_bit(status, 3); + spi_prettyprint_status_register_bp(status, 0); + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_prettyprint_status_register_at25fs010(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_atmel_at25_wpen(status); + msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is " + "%sset\n", (status & (1 << 6)) ? "" : "not "); + msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is " + "%sset\n", (status & (1 << 5)) ? "" : "not "); + spi_prettyprint_status_register_bit(status, 4); + msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is " + "%sset\n", (status & (1 << 3)) ? "" : "not "); + msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is " + "%sset\n", (status & (1 << 2)) ? "" : "not "); + /* FIXME: Pretty-print detailed sector protection status. */ + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_prettyprint_status_register_at25fs040(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_atmel_at25_wpen(status); + spi_prettyprint_status_register_bp(status, 4); + /* FIXME: Pretty-print detailed sector protection status. */ + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_prettyprint_status_register_at26df081a(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_atmel_at25_srpl(status); + msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) is %sset\n", + (status & (1 << 6)) ? "" : "not "); + spi_prettyprint_status_register_atmel_at25_epewpp(status); + spi_prettyprint_status_register_atmel_at25_swp(status); + spi_prettyprint_status_register_welwip(status); + return 0; +} + +int spi_disable_blockprotect_at25df(struct flashctx *flash) +{ + uint8_t status; + int result; + + status = spi_read_status_register(flash); + /* If block protection is disabled, stop here. */ + if ((status & (3 << 2)) == 0) + return 0; + + msg_cdbg("Some block protection in effect, disabling... "); + if (status & (1 << 7)) { + msg_cdbg("Need to disable Sector Protection Register Lock\n"); + if ((status & (1 << 4)) == 0) { + msg_cerr("WP# pin is active, disabling " + "write protection is impossible.\n"); + return 1; + } + /* All bits except bit 7 (SPRL) are readonly. */ + result = spi_write_status_register(flash, status & ~(1 << 7)); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + + } + /* Global unprotect. Make sure to mask SPRL as well. */ + result = spi_write_status_register(flash, status & ~0xbc); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + status = spi_read_status_register(flash); + if ((status & (3 << 2)) != 0) { + msg_cerr("Block protection could not be disabled!\n"); + return 1; + } + msg_cdbg("done.\n"); + return 0; +} + +int spi_disable_blockprotect_at25df_sec(struct flashctx *flash) +{ + /* FIXME: We should check the security lockdown. */ + msg_cinfo("Ignoring security lockdown (if present)\n"); + return spi_disable_blockprotect_at25df(flash); +} + +int spi_disable_blockprotect_at25f512b(struct flashctx *flash) +{ + /* spi_disable_blockprotect_at25df is not really the right way to do + * this, but the side effects of said function work here as well. + */ + return spi_disable_blockprotect_at25df(flash); +} + +int spi_disable_blockprotect_at25fs010(struct flashctx *flash) +{ + uint8_t status; + int result; + + status = spi_read_status_register(flash); + /* If block protection is disabled, stop here. */ + if ((status & 0x6c) == 0) + return 0; + + msg_cdbg("Some block protection in effect, disabling... "); + if (status & (1 << 7)) { + msg_cdbg("Need to disable Status Register Write Protect\n"); + /* Clear bit 7 (WPEN). */ + result = spi_write_status_register(flash, status & ~(1 << 7)); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + } + /* Global unprotect. Make sure to mask WPEN as well. */ + result = spi_write_status_register(flash, status & ~0xec); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + status = spi_read_status_register(flash); + if ((status & 0x6c) != 0) { + msg_cerr("Block protection could not be disabled!\n"); + return 1; + } + msg_cdbg("done.\n"); + return 0; +} + +int spi_disable_blockprotect_at25fs040(struct flashctx *flash) +{ + uint8_t status; + int result; + + status = spi_read_status_register(flash); + /* If block protection is disabled, stop here. */ + if ((status & 0x7c) == 0) + return 0; + + msg_cdbg("Some block protection in effect, disabling... "); + if (status & (1 << 7)) { + msg_cdbg("Need to disable Status Register Write Protect\n"); + /* Clear bit 7 (WPEN). */ + result = spi_write_status_register(flash, status & ~(1 << 7)); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + } + /* Global unprotect. Make sure to mask WPEN as well. */ + result = spi_write_status_register(flash, status & ~0xfc); + if (result) { + msg_cerr("spi_write_status_register failed.\n"); + return result; + } + status = spi_read_status_register(flash); + if ((status & 0x7c) != 0) { + msg_cerr("Block protection could not be disabled!\n"); + return 1; + } + msg_cdbg("done.\n"); + return 0; +} + +/* === SST === */ + +static void spi_prettyprint_status_register_sst25_common(uint8_t status) +{ + spi_prettyprint_status_register_hex(status); + + spi_prettyprint_status_register_bpl(status); + msg_cdbg("Chip status register: Auto Address Increment Programming (AAI) is %sset\n", + (status & (1 << 6)) ? "" : "not "); + spi_prettyprint_status_register_bp(status, 3); + spi_prettyprint_status_register_welwip(status); +} + +int spi_prettyprint_status_register_sst25(struct flashctx *flash) +{ + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_sst25_common(status); + return 0; +} + +int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash) +{ + static const char *const bpt[] = { + "none", + "1F0000H-1FFFFFH", + "1E0000H-1FFFFFH", + "1C0000H-1FFFFFH", + "180000H-1FFFFFH", + "100000H-1FFFFFH", + "all", "all" + }; + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_sst25_common(status); + msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]); + return 0; +} + +int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash) +{ + static const char *const bpt[] = { + "none", + "0x70000-0x7ffff", + "0x60000-0x7ffff", + "0x40000-0x7ffff", + "all blocks", "all blocks", "all blocks", "all blocks" + }; + uint8_t status = spi_read_status_register(flash); + spi_prettyprint_status_register_sst25_common(status); + msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]); + return 0; +}