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> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3722 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
d22ef49783
commit
6287e2e7aa
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue