Author: hailfinger Date: 2008-11-03 01:02:11 +0100 (Mon, 03 Nov 2008) New Revision: 3722
Modified: trunk/util/flashrom/flash.h trunk/util/flashrom/ichspi.c trunk/util/flashrom/spi.c Log: Add additional SPI sector erase and chip erase command functions to flashrom. 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.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: trunk/util/flashrom/flash.h =================================================================== --- trunk/util/flashrom/flash.h 2008-11-02 19:51:50 UTC (rev 3721) +++ trunk/util/flashrom/flash.h 2008-11-03 00:02:11 UTC (rev 3722) @@ -424,8 +424,11 @@ 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();
Modified: trunk/util/flashrom/ichspi.c =================================================================== --- trunk/util/flashrom/ichspi.c 2008-11-02 19:51:50 UTC (rev 3721) +++ trunk/util/flashrom/ichspi.c 2008-11-03 00:02:11 UTC (rev 3722) @@ -154,7 +154,6 @@ 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 @@ 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 @@ 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;
Modified: trunk/util/flashrom/spi.c =================================================================== --- trunk/util/flashrom/spi.c 2008-11-02 19:51:50 UTC (rev 3721) +++ trunk/util/flashrom/spi.c 2008-11-03 00:02:11 UTC (rev 3722) @@ -271,6 +271,22 @@ } }
+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 @@ 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