summaryrefslogtreecommitdiff
path: root/util/flashrom
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/flashrom
parentd22ef49783c60297f775f3c0136ad0d3e36ab495 (diff)
downloadcoreboot-6287e2e7aa2c0459a9fcb0af8a5fb1f4d5bca4f8.tar.xz
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/flashrom')
-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