diff options
author | Simon Glass <sjg@chromium.org> | 2013-06-13 15:41:48 -0700 |
---|---|---|
committer | Katie Roberts-Hoffman <katierh@chromium.org> | 2013-06-19 11:04:40 -0700 |
commit | 7a17b9830054429d9e864289ff3a4760369690a3 (patch) | |
tree | 79d4e796c077b23ec54e16a189687aa282a8da93 | |
parent | aaac3935d2e82b281979045a390f0b7d2c79b281 (diff) | |
download | chrome-ec-7a17b9830054429d9e864289ff3a4760369690a3.tar.gz |
Revert "Remove 64-byte workaround from STM32L flash writing"
This reverts commit b144a584af63891b134c3f789fdd00ac232a9577.
Temporary work-around for EC flash_write problems. Do not submit.
BUG=chromium:249186
BRANCH=none
TEST=manual
Run 'cros_test swsync rw' in U-Boot and see that it works again.
Change-Id: Ib1b7415c0aedc462c4dd782ee1d3c1ce20b40afa
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/59267
Commit-Queue: Katie Roberts-Hoffman <katierh@chromium.org>
Reviewed-by: Katie Roberts-Hoffman <katierh@chromium.org>
Tested-by: Katie Roberts-Hoffman <katierh@chromium.org>
-rw-r--r-- | chip/stm32/config-stm32l15x.h | 9 | ||||
-rw-r--r-- | chip/stm32/flash-stm32l15x.c | 80 |
2 files changed, 54 insertions, 35 deletions
diff --git a/chip/stm32/config-stm32l15x.h b/chip/stm32/config-stm32l15x.h index eac9347ecb..b752636c5a 100644 --- a/chip/stm32/config-stm32l15x.h +++ b/chip/stm32/config-stm32l15x.h @@ -9,7 +9,16 @@ #define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE #define CONFIG_FLASH_BANK_SIZE 0x1000 #define CONFIG_FLASH_ERASE_SIZE 0x0100 /* erase bank size */ + +/* crosbug.comb/p/9811 workaround 64-byte payload limitation */ +#define CONFIG_64B_WORKAROUND + +#ifdef CONFIG_64B_WORKAROUND +#define CONFIG_FLASH_WRITE_SIZE 0x0040 /* claimed minimum write size */ +#define CONFIG_FLASH_REAL_WRITE_SIZE 0x0080 /* actual minimum write size */ +#else #define CONFIG_FLASH_WRITE_SIZE 0x0080 +#endif #define CONFIG_RAM_BASE 0x20000000 #define CONFIG_RAM_SIZE 0x00004000 diff --git a/chip/stm32/flash-stm32l15x.c b/chip/stm32/flash-stm32l15x.c index a5394497d1..4e20ba4db8 100644 --- a/chip/stm32/flash-stm32l15x.c +++ b/chip/stm32/flash-stm32l15x.c @@ -25,6 +25,19 @@ #define FLASH_TIMEOUT_LOOP \ (FLASH_TIMEOUT_US * (CPU_CLOCK / SECOND) / CYCLE_PER_FLASH_LOOP) +#ifdef CONFIG_64B_WORKAROUND +/* + * Use the real write buffer size inside the driver. We only lie to the + * outside world so it'll feed data to us in smaller pieces. + */ +#undef CONFIG_FLASH_WRITE_SIZE +#define CONFIG_FLASH_WRITE_SIZE CONFIG_FLASH_REAL_WRITE_SIZE + +/* Used to buffer the write payload smaller than the half page size */ +static uint32_t write_buffer[CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t)]; +static int buffered_off = -1; +#endif + /** * Lock all the locks. */ @@ -164,15 +177,35 @@ void __attribute__((section(".iram.text"))) int flash_physical_write(int offset, int size, const char *data) { + /* + * TODO: (crosbug.com/p/9526) Enforce alignment instead of blindly + * casting data to uint32_t *. + */ uint32_t *data32 = (uint32_t *)data; - uint32_t *address = (uint32_t *)(CONFIG_FLASH_BASE + offset); + uint32_t *address; int res = EC_SUCCESS; - int word_mode = 0; - int i; - /* Fail if offset, size, and data aren't at least word-aligned */ - if ((offset | size | (uint32_t)(uintptr_t)data) & 3) - return EC_ERROR_INVAL; +#ifdef CONFIG_64B_WORKAROUND + if ((size < CONFIG_FLASH_WRITE_SIZE) || (offset & 64)) { + if ((size != 64) || + ((offset & 64) && (buffered_off != offset - 64))) { + res = EC_ERROR_UNKNOWN; + goto exit_wr; + } + if (offset & 64) { + /* second 64B packet : flash ! */ + memcpy(write_buffer + 16, data32, 64); + offset -= 64; + size += 64; + data32 = write_buffer; + } else { + /* first 64B packet : just store it */ + buffered_off = offset; + memcpy(write_buffer, data32, 64); + return EC_SUCCESS; + } + } +#endif /* Unlock program area */ res = unlock(STM32_FLASH_PECR_PRG_LOCK); @@ -182,40 +215,17 @@ int flash_physical_write(int offset, int size, const char *data) /* Clear previous error status */ STM32_FLASH_SR = 0xf00; - /* - * If offset and size aren't on word boundaries, do word writes. This - * is slower, but since we claim to the outside world that writes must - * be half-page size, the only code which hits this path is writing - * pstate (which is just writing one word). - */ - if ((offset | size) & (CONFIG_FLASH_WRITE_SIZE - 1)) - word_mode = 1; - - while (size > 0) { + for (address = (uint32_t *)(CONFIG_FLASH_BASE + offset) ; + size > 0; size -= CONFIG_FLASH_WRITE_SIZE) { /* * Reload the watchdog timer to avoid watchdog reset when doing * long writing with interrupt disabled. */ watchdog_reload(); + iram_flash_write(address, data32); - if (word_mode) { - /* Word write */ - *address++ = *data32++; - - /* Wait for writes to complete */ - for (i = 0; ((STM32_FLASH_SR & 9) != 8) && - (i < FLASH_TIMEOUT_LOOP) ; i++) - ; - - size -= sizeof(uint32_t); - } else { - /* Half page write */ - iram_flash_write(address, data32); - address += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t); - data32 += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t); - size -= CONFIG_FLASH_WRITE_SIZE; - } - + address += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t); + data32 += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t); if (STM32_FLASH_SR & 1) { res = EC_ERROR_TIMEOUT; goto exit_wr; @@ -225,7 +235,7 @@ int flash_physical_write(int offset, int size, const char *data) * Check for error conditions: erase failed, voltage error, * protection error */ - if (STM32_FLASH_SR & 0xf00) { + if (STM32_FLASH_SR & 0xF00) { res = EC_ERROR_UNKNOWN; goto exit_wr; } |