Used for page erase on some chips (e.g. Numonyx M45PE and Sanyo LF25FW series).
Signed-off-by: Nikolay Nikolaev evrinoma@gmail.com Reviewed-by: Steven Zakulec spzakulec@gmail.com Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at Acked-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- chipdrivers.h | 1 + spi.h | 5 +++++ spi25.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+)
diff --git a/chipdrivers.h b/chipdrivers.h index c64de79..4bb356a 100644 --- a/chipdrivers.h +++ b/chipdrivers.h @@ -51,6 +51,7 @@ int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int b int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen); +int spi_block_erase_db(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); int spi_byte_program(struct flashctx *flash, unsigned int addr, uint8_t databyte); diff --git a/spi.h b/spi.h index 297125e..9e38e74 100644 --- a/spi.h +++ b/spi.h @@ -106,6 +106,11 @@ #define JEDEC_SE_OUTSIZE 0x04 #define JEDEC_SE_INSIZE 0x00
+/* Page Erase 0xDB */ +#define JEDEC_PE 0xDB +#define JEDEC_PE_OUTSIZE 0x04 +#define JEDEC_PE_INSIZE 0x00 + /* Read Status Register */ #define JEDEC_RDSR 0x05 #define JEDEC_RDSR_OUTSIZE 0x01 diff --git a/spi25.c b/spi25.c index 4f1452e..26da13d 100644 --- a/spi25.c +++ b/spi25.c @@ -565,6 +565,47 @@ int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, return 0; }
+/* Page erase (usually 256B blocks) */ +int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen) +{ + int result; + struct spi_command cmds[] = { + { + .writecnt = JEDEC_WREN_OUTSIZE, + .writearr = (const unsigned char[]){ JEDEC_WREN }, + .readcnt = 0, + .readarr = NULL, + }, { + .writecnt = JEDEC_PE_OUTSIZE, + .writearr = (const unsigned char[]){ + JEDEC_PE, + (addr >> 16) & 0xff, + (addr >> 8) & 0xff, + (addr & 0xff) + }, + .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 at address 0x%x\n", __func__, addr); + return result; + } + + /* Wait until the Write-In-Progress bit is cleared. + * This takes up to 20 ms usually (on worn out devices up to the 0.5s range), so wait in 1 ms steps. */ + while (spi_read_status_register(flash) & SPI_SR_WIP) + programmer_delay(1 * 1000); + /* FIXME: Check the status register for errors. */ + return 0; +} + /* Sector size is usually 4k, though Macronix eliteflash has 64k */ int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen) @@ -745,6 +786,8 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) return &spi_block_erase_d7; case 0xd8: return &spi_block_erase_d8; + case 0xdb: + return &spi_block_erase_db; default: msg_cinfo("%s: unknown erase opcode (0x%02x). Please report " "this at flashrom@flashrom.org\n", __func__, opcode);