summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2008-11-03 00:02:11 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2008-11-03 00:02:11 +0000
commit6287e2e7aa2c0459a9fcb0af8a5fb1f4d5bca4f8 (patch)
treea212ab6e8e24258847c9316d5251ec172531a9da /util
parentd22ef49783c60297f775f3c0136ad0d3e36ab495 (diff)
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
Diffstat (limited to 'util')
-rw-r--r--util/flashrom/flash.h3
-rw-r--r--util/flashrom/ichspi.c21
-rw-r--r--util/flashrom/spi.c34
3 files changed, 42 insertions, 16 deletions
diff --git a/util/flashrom/flash.h b/util/flashrom/flash.h
index 769b8d0ee9..5010837fe1 100644
--- a/util/flashrom/flash.h
+++ b/util/flashrom/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/util/flashrom/ichspi.c b/util/flashrom/ichspi.c
index 74ce3f0c24..28ee578ee3 100644
--- a/util/flashrom/ichspi.c
+++ b/util/flashrom/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/util/flashrom/spi.c b/util/flashrom/spi.c
index 83624fa381..3bd29b0910 100644
--- a/util/flashrom/spi.c
+++ b/util/flashrom/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