diff options
Diffstat (limited to 's25f.c')
-rw-r--r-- | s25f.c | 60 |
1 files changed, 36 insertions, 24 deletions
@@ -17,15 +17,15 @@ /* * s25f.c - Helper functions for Spansion S25FL and S25FS SPI flash chips. * Uses 24 bit addressing for the FS chips and 32 bit addressing for the FL - * chips (which is required by the overlayed sector size devices). + * chips (which is required by the overlaid sector size devices). * TODO: Implement fancy hybrid sector architecture helpers. */ +#include <stdlib.h> #include <string.h> #include "chipdrivers.h" #include "spi.h" -#include "writeprotect.h" /* * RDAR and WRAR are supported on chips which have more than one set of status @@ -94,7 +94,7 @@ static int s25f_legacy_software_reset(const struct flashctx *flash) /* Allow time for reset command to execute. The datasheet specifies * Trph = 35us, double that to be safe. */ - programmer_delay(T_RPH * 2); + programmer_delay(flash, T_RPH * 2); return 0; } @@ -127,16 +127,21 @@ static int s25fs_software_reset(struct flashctx *flash) } /* Allow time for reset command to execute. Double tRPH to be safe. */ - programmer_delay(T_RPH * 2); + programmer_delay(flash, T_RPH * 2); return 0; } static int s25f_poll_status(const struct flashctx *flash) { - uint8_t tmp = spi_read_status_register(flash); + while (true) { + uint8_t tmp; + if (spi_read_register(flash, STATUS1, &tmp)) + return -1; + + if ((tmp & SPI_SR_WIP) == 0) + break; - while (tmp & SPI_SR_WIP) { /* * The WIP bit on S25F chips remains set to 1 if erase or * programming errors occur, so we must check for those @@ -156,8 +161,7 @@ static int s25f_poll_status(const struct flashctx *flash) return -1; } - programmer_delay(1000 * 10); - tmp = spi_read_status_register(flash); + programmer_delay(flash, 1000 * 10); } return 0; @@ -180,7 +184,7 @@ static int s25fs_read_cr(const struct flashctx *flash, uint32_t addr) int result = spi_send_command(flash, sizeof(read_cr_cmd), 1, read_cr_cmd, &cfg); if (result) { - msg_cerr("%s failed during command execution at address 0x%x\n", + msg_cerr("%s failed during command execution at address 0x%"PRIx32"\n", __func__, addr); return -1; } @@ -218,27 +222,29 @@ static int s25fs_write_cr(const struct flashctx *flash, int result = spi_send_multicommand(flash, cmds); if (result) { - msg_cerr("%s failed during command execution at address 0x%x\n", + msg_cerr("%s failed during command execution at address 0x%"PRIx32"\n", __func__, addr); return -1; } - programmer_delay(T_W); + programmer_delay(flash, T_W); return s25f_poll_status(flash); } -static int s25fs_restore_cr3nv(struct flashctx *flash, uint8_t cfg) +static int s25fs_restore_cr3nv(struct flashctx *flash, void *data) { int ret = 0; + uint8_t cfg = *(uint8_t *)data; + free(data); + msg_cdbg("Restoring CR3NV value to 0x%02x\n", cfg); ret |= s25fs_write_cr(flash, CR3NV_ADDR, cfg); ret |= s25fs_software_reset(flash); return ret; } -int s25fs_block_erase_d8(struct flashctx *flash, - uint32_t addr, uint32_t blocklen) +int s25fs_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen) { static int cr3nv_checked = 0; @@ -283,8 +289,15 @@ int s25fs_block_erase_d8(struct flashctx *flash, msg_cdbg("\n%s: CR3NV updated (0x%02x -> 0x%02x)\n", __func__, cfg, s25fs_read_cr(flash, CR3NV_ADDR)); + /* Restore CR3V when flashrom exits */ - register_chip_restore(s25fs_restore_cr3nv, flash, cfg); + uint8_t *data = calloc(sizeof(uint8_t), 1); + if (!data) { + msg_cerr("Out of memory!\n"); + return 1; + } + *data = cfg; + register_chip_restore(s25fs_restore_cr3nv, flash, data); } cr3nv_checked = 1; @@ -297,12 +310,11 @@ int s25fs_block_erase_d8(struct flashctx *flash, return result; } - programmer_delay(S25FS_T_SE); + programmer_delay(flash, S25FS_T_SE); return s25f_poll_status(flash); } -int s25fl_block_erase(struct flashctx *flash, - uint32_t addr, uint32_t blocklen) +int s25fl_block_erase(struct flashctx *flash, unsigned int addr, unsigned int blocklen) { struct spi_command erase_cmds[] = { { @@ -336,7 +348,7 @@ int s25fl_block_erase(struct flashctx *flash, return result; } - programmer_delay(S25FL_T_SE); + programmer_delay(flash, S25FL_T_SE); return s25f_poll_status(flash); } @@ -367,7 +379,7 @@ int probe_spi_big_spansion(struct flashctx *flash) * 04h 00h FS: 256-kB physical sectors * 04h 01h FS: 64-kB physical sectors * 04h 00h FL: 256-kB physical sectors - * 04h 01h FL: Mix of 64-kB and 4KB overlayed sectors + * 04h 01h FL: Mix of 64-kB and 4KB overlaid sectors * 05h 80h FL family * 05h 81h FS family * @@ -379,10 +391,10 @@ int probe_spi_big_spansion(struct flashctx *flash) */ uint32_t model_id = - dev_id[1] << 24 | - dev_id[2] << 16 | - dev_id[4] << 8 | - dev_id[5] << 0; + (uint32_t)dev_id[1] << 24 | + (uint32_t)dev_id[2] << 16 | + (uint32_t)dev_id[4] << 8 | + (uint32_t)dev_id[5] << 0; if (dev_id[0] == flash->chip->manufacture_id && model_id == flash->chip->model_id) return 1; |