summaryrefslogtreecommitdiff
path: root/util/ec_flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/ec_flash.c')
-rw-r--r--util/ec_flash.c39
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;
+}