This can dramatically reduce the wait time on failures in some cases: 1. issue erase command that never succeeds but times out eventually 2. whole flash gets reread due to the erase not erasing as expected 3. next eraser is issued and flashrom waits for it to finish, although the transaction is not even considered by the chip because it is still busy 4. whole chip gets reread...
we also can not really be sure which erase opcode succeed (if it does eventuall) in this situation.
this patch shows said pedantry for the at45db family (which has not been merged to svn as of this writing). if we want such a feature (which costs some performance in non-error cases!) i would suggest creating a is_ready function pointer in the struct flashchip to be called in the generic code path and note like in this patch. this might actually be a good idea anyway. i cant tell a useful use case off the top of my head, do you?
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- at45db.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/at45db.c b/at45db.c index 4ff25be..b41ec73 100644 --- a/at45db.c +++ b/at45db.c @@ -324,6 +324,12 @@ static int at45db_wait_ready (struct flashctx *flash, unsigned int us, unsigned
static int at45db_erase(struct flashctx *flash, uint8_t opcode, unsigned int at45db_addr, unsigned int stepsize, unsigned int retries) { + int ret = at45db_wait_ready(flash, 0, 0); + if (ret != 0) { + msg_cerr("%s: chip not ready before sending erase command!\n", __func__); + return ret; + } + const uint8_t cmd[] = { opcode, (at45db_addr >> 16) & 0xff, @@ -332,7 +338,7 @@ static int at45db_erase(struct flashctx *flash, uint8_t opcode, unsigned int at4 };
/* Send erase command. */ - int ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); + ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); if (ret != 0) { msg_cerr("%s: error sending erase command!\n", __func__); return ret; @@ -496,6 +502,12 @@ static int at45db_fill_buffer1(struct flashctx *flash, uint8_t *bytes, unsigned
static int at45db_commit_buffer1(struct flashctx *flash, unsigned int at45db_addr) { + int ret = at45db_wait_ready(flash, 0, 0); + if (ret != 0) { + msg_cerr("%s: chip not ready before sending (write) commit command!\n", __func__); + return ret; + } + const uint8_t cmd[] = { AT45DB_BUFFER1_PAGE_PROGRAM, (at45db_addr >> 16) & 0xff, @@ -504,7 +516,7 @@ static int at45db_commit_buffer1(struct flashctx *flash, unsigned int at45db_add };
/* Send buffer to device. */ - int ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); + ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); if (ret != 0) { msg_cerr("%s: error sending buffer to main memory command!\n", __func__); return ret;