diff options
Diffstat (limited to 'spi25.c')
-rw-r--r-- | spi25.c | 131 |
1 files changed, 75 insertions, 56 deletions
@@ -37,7 +37,7 @@ enum id_type { }; static struct { - int is_cached; + bool is_cached; unsigned char bytes[4]; /* enough to hold largest ID type */ } id_cache[NUM_ID_TYPES]; @@ -141,7 +141,7 @@ static int compare_id(const struct flashctx *flash, uint32_t id1, uint32_t id2) { const struct flashchip *chip = flash->chip; - msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%02"PRIx32", id2 0x%02"PRIx32"\n", __func__, id1, id2); if (id1 == chip->manufacture_id && id2 == chip->model_id) return 1; @@ -167,7 +167,7 @@ static int probe_spi_rdid_generic(struct flashctx *flash, int bytes) msg_cinfo("%d byte RDID not supported on this SPI controller\n", bytes); if (ret) return 0; - id_cache[idty].is_cached = 1; + id_cache[idty].is_cached = true; } rdid_get_ids(id_cache[idty].bytes, bytes, &id1, &id2); @@ -191,7 +191,7 @@ int probe_spi_rems(struct flashctx *flash) if (!id_cache[REMS].is_cached) { if (spi_rems(flash, id_cache[REMS].bytes)) return 0; - id_cache[REMS].is_cached = 1; + id_cache[REMS].is_cached = true; } id1 = id_cache[REMS].bytes[0]; @@ -232,7 +232,7 @@ int probe_spi_res1(struct flashctx *flash) id2 = readarr[0]; - msg_cdbg("%s: id 0x%x\n", __func__, id2); + msg_cdbg("%s: id 0x%"PRIx32"\n", __func__, id2); if (id2 != flash->chip->model_id) return 0; @@ -247,12 +247,12 @@ int probe_spi_res2(struct flashctx *flash) if (!id_cache[RES2].is_cached) { if (spi_res(flash, id_cache[RES2].bytes, 2)) return 0; - id_cache[RES2].is_cached = 1; + id_cache[RES2].is_cached = true; } id1 = id_cache[RES2].bytes[0]; id2 = id_cache[RES2].bytes[1]; - msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%"PRIx32", id2 0x%"PRIx32"\n", __func__, id1, id2); if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) return 0; @@ -267,12 +267,12 @@ int probe_spi_res3(struct flashctx *flash) if (!id_cache[RES3].is_cached) { if (spi_res(flash, id_cache[RES3].bytes, 3)) return 0; - id_cache[RES3].is_cached = 1; + id_cache[RES3].is_cached = true; } id1 = (id_cache[RES3].bytes[0] << 8) | id_cache[RES3].bytes[1]; id2 = id_cache[RES3].bytes[3]; - msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%"PRIx32", id2 0x%"PRIx32"\n", __func__, id1, id2); if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) return 0; @@ -294,7 +294,7 @@ int probe_spi_at25f(struct flashctx *flash) id1 = readarr[0]; id2 = readarr[1]; - msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%02"PRIx32", id2 0x%02"PRIx32"\n", __func__, id1, id2); if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) return 1; @@ -304,12 +304,17 @@ int probe_spi_at25f(struct flashctx *flash) static int spi_poll_wip(struct flashctx *const flash, const unsigned int poll_delay) { - /* FIXME: We can't tell if spi_read_status_register() failed. */ /* FIXME: We don't time out. */ - while (spi_read_status_register(flash) & SPI_SR_WIP) - programmer_delay(poll_delay); - /* FIXME: Check the status register for errors. */ - return 0; + while (true) { + uint8_t status; + int ret = spi_read_register(flash, STATUS1, &status); + if (ret) + return ret; + if (!(status & SPI_SR_WIP)) + return 0; + + programmer_delay(flash, poll_delay); + } } /** @@ -346,7 +351,16 @@ static int spi_simple_write_cmd(struct flashctx *const flash, const uint8_t op, static int spi_write_extended_address_register(struct flashctx *const flash, const uint8_t regdata) { - const uint8_t op = flash->chip->wrea_override ? : JEDEC_WRITE_EXT_ADDR_REG; + uint8_t op; + if (flash->chip->feature_bits & FEATURE_4BA_EAR_C5C8) { + op = JEDEC_WRITE_EXT_ADDR_REG; + } else if (flash->chip->feature_bits & FEATURE_4BA_EAR_1716) { + op = ALT_WRITE_EXT_ADDR_REG_17; + } else { + msg_cerr("Flash misses feature flag for extended-address register.\n"); + return -1; + } + struct spi_command cmds[] = { { .readarr = 0, @@ -389,7 +403,7 @@ static int spi_prepare_address(struct flashctx *const flash, uint8_t cmd_buf[], cmd_buf[4] = (addr >> 0) & 0xff; return 4; } else { - if (flash->chip->feature_bits & FEATURE_4BA_EXT_ADDR) { + if (flash->chip->feature_bits & FEATURE_4BA_EAR_ANY) { if (spi_set_extended_address(flash, addr >> 24)) return -1; } else if (addr >> 24) { @@ -584,6 +598,13 @@ int spi_block_erase_21(struct flashctx *flash, unsigned int addr, unsigned int b } /* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */ +int spi_block_erase_53(struct flashctx *flash, unsigned int addr, unsigned int blocklen) +{ + /* This usually takes 100-4000ms, so wait in 100ms steps. */ + return spi_write_cmd(flash, 0x53, true, addr, NULL, 0, 100 * 1000); +} + +/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */ int spi_block_erase_5c(struct flashctx *flash, unsigned int addr, unsigned int blocklen) { /* This usually takes 100-4000ms, so wait in 100ms steps. */ @@ -597,46 +618,37 @@ int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int b return spi_write_cmd(flash, 0xdc, true, addr, NULL, 0, 100 * 1000); } -erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) -{ - switch(opcode){ - case 0xff: - case 0x00: - /* Not specified, assuming "not supported". */ - return NULL; - case 0x20: - return &spi_block_erase_20; - case 0x21: - return &spi_block_erase_21; - case 0x50: - return &spi_block_erase_50; - case 0x52: - return &spi_block_erase_52; - case 0x5c: - return &spi_block_erase_5c; - case 0x60: - return &spi_block_erase_60; - case 0x62: - return &spi_block_erase_62; - case 0x81: - return &spi_block_erase_81; - case 0xc4: - return &spi_block_erase_c4; - case 0xc7: - return &spi_block_erase_c7; - case 0xd7: - return &spi_block_erase_d7; - case 0xd8: - return &spi_block_erase_d8; - case 0xdb: - return &spi_block_erase_db; - case 0xdc: - return &spi_block_erase_dc; - default: - msg_cinfo("%s: unknown erase opcode (0x%02x). Please report " - "this at flashrom@flashrom.org\n", __func__, opcode); - return NULL; +static const struct { + enum block_erase_func func; + uint8_t opcode; +} spi25_function_opcode_list[] = { + {SPI_BLOCK_ERASE_20, 0x20}, + {SPI_BLOCK_ERASE_21, 0x21}, + {SPI_BLOCK_ERASE_50, 0x50}, + {SPI_BLOCK_ERASE_52, 0x52}, + {SPI_BLOCK_ERASE_53, 0x53}, + {SPI_BLOCK_ERASE_5C, 0x5c}, + {SPI_BLOCK_ERASE_60, 0x60}, + {SPI_BLOCK_ERASE_62, 0x62}, + {SPI_BLOCK_ERASE_81, 0x81}, + {SPI_BLOCK_ERASE_C4, 0xc4}, + {SPI_BLOCK_ERASE_C7, 0xc7}, + {SPI_BLOCK_ERASE_D7, 0xd7}, + {SPI_BLOCK_ERASE_D8, 0xd8}, + {SPI_BLOCK_ERASE_DB, 0xdb}, + {SPI_BLOCK_ERASE_DC, 0xdc}, +}; + +enum block_erase_func spi25_get_erasefn_from_opcode(uint8_t opcode) +{ + size_t i; + for (i = 0; i < ARRAY_SIZE(spi25_function_opcode_list); i++) { + if (spi25_function_opcode_list[i].opcode == opcode) + return spi25_function_opcode_list[i].func; } + msg_cinfo("%s: unknown erase opcode (0x%02x). Please report " + "this at flashrom@flashrom.org\n", __func__, opcode); + return NO_BLOCK_ERASE_FUNC; } static int spi_nbyte_program(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len) @@ -669,11 +681,14 @@ int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, { int ret; size_t to_read; + size_t start_address = start; + size_t end_address = len - start; for (; len; len -= to_read, buf += to_read, start += to_read) { to_read = min(chunksize, len); ret = spi_nbyte_read(flash, start, buf, to_read); if (ret) return ret; + update_progress(flash, FLASHROM_PROGRESS_READ, start - start_address + to_read, end_address); } return 0; } @@ -693,6 +708,8 @@ int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int s * we're OK for now. */ unsigned int page_size = flash->chip->page_size; + size_t start_address = start; + size_t end_address = len - start; /* Warning: This loop has a very unusual condition and body. * The loop needs to go through each page with at least one affected @@ -717,6 +734,7 @@ int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int s if (rc) return rc; } + update_progress(flash, FLASHROM_PROGRESS_WRITE, start - start_address + lenhere, end_address); } return 0; @@ -736,6 +754,7 @@ int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int st for (i = start; i < start + len; i++) { if (spi_nbyte_program(flash, i, buf + i - start, 1)) return 1; + update_progress(flash, FLASHROM_PROGRESS_WRITE, i - start, len - start); } return 0; } |