summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/lm4/flash.c12
-rw-r--r--chip/stm32/flash-stm32f100.c12
-rw-r--r--chip/stm32/flash-stm32l15x.c6
-rw-r--r--common/flash_common.c17
-rw-r--r--include/flash.h11
5 files changed, 49 insertions, 9 deletions
diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c
index d64c29e6f8..9309fc7c35 100644
--- a/chip/lm4/flash.c
+++ b/chip/lm4/flash.c
@@ -227,11 +227,17 @@ int flash_physical_write(int offset, int size, const char *data)
int flash_physical_erase(int offset, int size)
{
LM4_FLASH_FCMISC = LM4_FLASH_FCRIS; /* Clear previous error status */
- LM4_FLASH_FMA = offset;
- for ( ; size > 0; size -= CONFIG_FLASH_ERASE_SIZE) {
+ for ( ; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
+ offset += CONFIG_FLASH_ERASE_SIZE) {
int t;
+ /* Do nothing if already erased */
+ if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
+ continue;
+
+ LM4_FLASH_FMA = offset;
+
#ifdef CONFIG_TASK_WATCHDOG
/* Reload the watchdog timer, so that erasing many flash pages
* doesn't cause a watchdog reset. May not need this now that
@@ -253,8 +259,6 @@ int flash_physical_erase(int offset, int size)
* protection error */
if (LM4_FLASH_FCRIS & 0x0a01)
return EC_ERROR_UNKNOWN;
-
- LM4_FLASH_FMA += CONFIG_FLASH_ERASE_SIZE;
}
return EC_SUCCESS;
diff --git a/chip/stm32/flash-stm32f100.c b/chip/stm32/flash-stm32f100.c
index ee3d0f7a4b..2d2b3647b3 100644
--- a/chip/stm32/flash-stm32f100.c
+++ b/chip/stm32/flash-stm32f100.c
@@ -357,7 +357,6 @@ exit_wr:
int flash_physical_erase(int offset, int size)
{
- uint32_t address;
int res = EC_SUCCESS;
if (unlock(PRG_LOCK) != EC_SUCCESS)
@@ -369,13 +368,16 @@ int flash_physical_erase(int offset, int size)
/* set PER bit */
STM32_FLASH_CR |= PER;
- for (address = CONFIG_FLASH_BASE + offset ;
- size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
- address += CONFIG_FLASH_ERASE_SIZE) {
+ for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
+ offset += CONFIG_FLASH_ERASE_SIZE) {
timestamp_t deadline;
+ /* Do nothing if already erased */
+ if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
+ continue;
+
/* select page to erase */
- STM32_FLASH_AR = address;
+ STM32_FLASH_AR = CONFIG_FLASH_BASE + offset;
/* set STRT bit : start erase */
STM32_FLASH_CR |= STRT;
diff --git a/chip/stm32/flash-stm32l15x.c b/chip/stm32/flash-stm32l15x.c
index f61f8a0c21..885047a032 100644
--- a/chip/stm32/flash-stm32l15x.c
+++ b/chip/stm32/flash-stm32l15x.c
@@ -235,6 +235,12 @@ int flash_physical_erase(int offset, int size)
address += CONFIG_FLASH_ERASE_SIZE / sizeof(uint32_t)) {
timestamp_t deadline;
+ /*
+ * crosbug.com/p/13066
+ * We can't do the flash_is_erased() trick on stm32l since
+ * bits erase to 0, not 1. Will address later if needed.
+ */
+
/* Start erase */
*address = 0x00000000;
diff --git a/common/flash_common.c b/common/flash_common.c
index c1f0e84ed5..81e6291641 100644
--- a/common/flash_common.c
+++ b/common/flash_common.c
@@ -26,6 +26,23 @@ int flash_dataptr(int offset, int size_req, int align, char **ptrp)
return CONFIG_FLASH_SIZE - offset;
}
+/* crosbug.com/p/13066 - not supported on STM32L */
+#ifndef CHIP_VARIANT_stm32l15x
+int flash_is_erased(uint32_t offset, int size)
+{
+ uint32_t *ptr;
+
+ if (flash_dataptr(offset, size, sizeof(uint32_t), (char **)&ptr) < 0)
+ return 0;
+
+ for (size /= sizeof(uint32_t); size > 0; size -= 4, ptr++)
+ if (*ptr != -1U)
+ return 0;
+
+ return 1;
+}
+#endif
+
int flash_write(int offset, int size, const char *data)
{
if (flash_dataptr(offset, size, CONFIG_FLASH_WRITE_SIZE, NULL) < 0)
diff --git a/include/flash.h b/include/flash.h
index 2e31cf0f22..8bf0264c14 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -32,6 +32,17 @@ static inline char *flash_physical_dataptr(int offset)
}
/**
+ * Check if a region of flash is erased
+ *
+ * It is assumed that an erased region has all bits set to 1.
+ *
+ * @param offset Flash offset to check
+ * @param size Number of bytes to check (word-aligned)
+ * @return 1 if erased, 0 if not erased
+ */
+int flash_is_erased(uint32_t offset, int size);
+
+/**
* Write to physical flash.
*
* Offset and size must be a multiple of CONFIG_FLASH_WRITE_SIZE.