From 6afb613fefbd4b484babafa9680b9570aadb255d Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Mon, 3 Nov 2008 00:02:11 +0000 Subject: Add additional SPI sector erase and chip erase command functions Not all chips support all commands, so allow the implementer to select the matching function. Fix a layering violation in ICH SPI code to be less bad. Still not perfect, but the new code is shorter, more generic and architecturally more sound. TODO (in a separate patch): - move the generic sector erase code to spi.c - decide which erase command to use based on info about the chip - create a generic spi_erase_all_sectors function which calls the generic sector erase function Thanks to Stefan for reviewing and commenting. Corresponding to flashrom svn r337 and coreboot v2 svn r3722. Signed-off-by: Carl-Daniel Hailfinger Acked-by: Stefan Reinauer --- flash.h | 3 +++ ichspi.c | 21 +++++---------------- spi.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/flash.h b/flash.h index 769b8d0e..5010837f 100644 --- a/flash.h +++ b/flash.h @@ -424,8 +424,11 @@ int spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); void spi_write_enable(); void spi_write_disable(); +int spi_chip_erase_60(struct flashchip *flash); int spi_chip_erase_c7(struct flashchip *flash); int spi_chip_erase_d8(struct flashchip *flash); +int spi_block_erase_52(const struct flashchip *flash, unsigned long addr); +int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr); int spi_chip_write(struct flashchip *flash, uint8_t *buf); int spi_chip_read(struct flashchip *flash, uint8_t *buf); uint8_t spi_read_status_register(); diff --git a/ichspi.c b/ichspi.c index 74ce3f0c..28ee578e 100644 --- a/ichspi.c +++ b/ichspi.c @@ -154,7 +154,6 @@ static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset, int maxdata); static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, int offset, int maxdata); -static int ich_spi_erase_block(struct flashchip *flash, int offset); OPCODES O_ST_M25P = { { @@ -479,20 +478,6 @@ static int run_opcode(OPCODE op, uint32_t offset, return -1; } -static int ich_spi_erase_block(struct flashchip *flash, int offset) -{ - printf_debug("ich_spi_erase_block: offset=%d, sectors=%d\n", offset, 1); - - if (run_opcode(curopcodes->opcode[2], offset, 0, NULL) != 0) { - printf_debug("Error erasing sector at 0x%x", offset); - return -1; - } - - printf("DONE BLOCK 0x%x\n", offset); - - return 0; -} - static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset, int maxdata) { @@ -596,7 +581,11 @@ int ich_spi_write(struct flashchip *flash, uint8_t * buf) printf("Programming page: \n"); for (i = 0; i < total_size / erase_size; i++) { - rc = ich_spi_erase_block(flash, i * erase_size); + /* FIMXE: call the chip-specific spi_block_erase_XX instead. + * For this, we need to add a block erase function to + * struct flashchip. + */ + rc = spi_block_erase_d8(flash, i * erase_size); if (rc) { printf("Error erasing block at 0x%x\n", i); break; diff --git a/spi.c b/spi.c index 83624fa3..3bd29b09 100644 --- a/spi.c +++ b/spi.c @@ -271,6 +271,22 @@ void spi_prettyprint_status_register(struct flashchip *flash) } } +int spi_chip_erase_60(struct flashchip *flash) +{ + const unsigned char cmd[JEDEC_CE_60_OUTSIZE] = {JEDEC_CE_60}; + + spi_disable_blockprotect(); + spi_write_enable(); + /* Send CE (Chip Erase) */ + spi_command(sizeof(cmd), 0, cmd, NULL); + /* Wait until the Write-In-Progress bit is cleared. + * This usually takes 1-85 s, so wait in 1 s steps. + */ + while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) + sleep(1); + return 0; +} + int spi_chip_erase_c7(struct flashchip *flash) { const unsigned char cmd[JEDEC_CE_C7_OUTSIZE] = { JEDEC_CE_C7 }; @@ -287,6 +303,24 @@ int spi_chip_erase_c7(struct flashchip *flash) return 0; } +int spi_block_erase_52(const struct flashchip *flash, unsigned long addr) +{ + unsigned char cmd[JEDEC_BE_52_OUTSIZE] = {JEDEC_BE_52}; + + cmd[1] = (addr & 0x00ff0000) >> 16; + cmd[2] = (addr & 0x0000ff00) >> 8; + cmd[3] = (addr & 0x000000ff); + spi_write_enable(); + /* Send BE (Block Erase) */ + spi_command(sizeof(cmd), 0, cmd, NULL); + /* Wait until the Write-In-Progress bit is cleared. + * This usually takes 100-4000 ms, so wait in 100 ms steps. + */ + while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) + usleep(100 * 1000); + return 0; +} + /* Block size is usually * 64k for Macronix * 32k for SST -- cgit v1.2.3