diff options
Diffstat (limited to 'util/ec_flash.c')
-rw-r--r-- | util/ec_flash.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/util/ec_flash.c b/util/ec_flash.c index 93705694e3..c61720a1c2 100644 --- a/util/ec_flash.c +++ b/util/ec_flash.c @@ -11,6 +11,11 @@ #include "comm-host.h" #include "misc_util.h" +#include "timer.h" + +static const uint32_t ERASE_ASYNC_TIMEOUT = 10 * SECOND; +static const uint32_t ERASE_ASYNC_WAIT = 500 * MSEC; +static const int FLASH_ERASE_BUSY_RV = -EECRESULT - EC_RES_BUSY; int ec_flash_read(uint8_t *buf, int offset, int size) { @@ -125,3 +130,37 @@ int ec_flash_erase(int offset, int size) return ec_command(EC_CMD_FLASH_ERASE, 0, &p, sizeof(p), NULL, 0); } + +int ec_flash_erase_async(int offset, int size) +{ + struct ec_params_flash_erase_v1 p = { 0 }; + uint32_t timeout = 0; + int rv = FLASH_ERASE_BUSY_RV; + + p.cmd = FLASH_ERASE_SECTOR_ASYNC; + p.params.offset = offset; + p.params.size = size; + + rv = ec_command(EC_CMD_FLASH_ERASE, 1, &p, sizeof(p), NULL, 0); + + if (rv < 0) + return rv; + + rv = FLASH_ERASE_BUSY_RV; + + while (rv < 0 && timeout < ERASE_ASYNC_TIMEOUT) { + /* + * The erase is not complete until FLASH_ERASE_GET_RESULT + * returns success. It's important that we retry even when the + * underlying ioctl returns an error (not just + * FLASH_ERASE_BUSY_RV). + * + * See https://crrev.com/c/511805 for details. + */ + usleep(ERASE_ASYNC_WAIT); + timeout += ERASE_ASYNC_WAIT; + p.cmd = FLASH_ERASE_GET_RESULT; + rv = ec_command(EC_CMD_FLASH_ERASE, 1, &p, sizeof(p), NULL, 0); + } + return rv; +} |