diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-05-24 11:44:27 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-05-24 16:27:48 -0700 |
commit | b144a584af63891b134c3f789fdd00ac232a9577 (patch) | |
tree | e16aea3d30c038cac3e48a55afd54f05280a4d75 | |
parent | 3443478d7659d8222222c073fb8ed2e6164b93d9 (diff) | |
download | chrome-ec-b144a584af63891b134c3f789fdd00ac232a9577.tar.gz |
Remove 64-byte workaround from STM32L flash writing
This was left over from ancient code where host commands only had a
64-byte payload, and page writes need to happen in 128-byte
increments. This is no longer an issue with SPI host interface.
Also added capability for word writes, since that'll be necessary for
writing pstate (in the next CL).
BUG=chrome-os-partner:9526
BRANCH=none
TEST=hack flashwrite command in flash_common.c to allow write size = 4 bytes
flasherase 0x1fc00 0x400
flashwrite 0x1fc00 0x100 -> success; uses fast path
flashwrite 0x1fd00 4 -> success; uses word-write path
Change-Id: I61434d8f714ea46deb65cadd82c45a61ad0ce68b
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/56627
Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | chip/stm32/config-stm32l15x.h | 9 | ||||
-rw-r--r-- | chip/stm32/flash-stm32l15x.c | 80 |
2 files changed, 35 insertions, 54 deletions
diff --git a/chip/stm32/config-stm32l15x.h b/chip/stm32/config-stm32l15x.h index 83af295f9d..dda4ebc90f 100644 --- a/chip/stm32/config-stm32l15x.h +++ b/chip/stm32/config-stm32l15x.h @@ -9,16 +9,7 @@ #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 42c9bc23d0..d1e2822744 100644 --- a/chip/stm32/flash-stm32l15x.c +++ b/chip/stm32/flash-stm32l15x.c @@ -26,19 +26,6 @@ #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. * @@ -185,35 +172,15 @@ 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 *address = (uint32_t *)(CONFIG_FLASH_BASE + offset); int res = EC_SUCCESS; + int word_mode = 0; + int i; -#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 + /* 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; /* Unlock program area */ res = unlock(STM32_FLASH_PECR_PRG_LOCK); @@ -223,8 +190,16 @@ int flash_physical_write(int offset, int size, const char *data) /* Clear previous error status */ STM32_FLASH_SR = 0xf00; - for (address = (uint32_t *)(CONFIG_FLASH_BASE + offset) ; - size > 0; size -= CONFIG_FLASH_WRITE_SIZE) { + /* + * 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) { #ifdef CONFIG_WATCHDOG /* * Reload the watchdog timer to avoid watchdog reset when doing @@ -232,10 +207,25 @@ int flash_physical_write(int offset, int size, const char *data) */ watchdog_reload(); #endif - iram_flash_write(address, data32); - address += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t); - data32 += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t); + 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; + } + if (STM32_FLASH_SR & 1) { res = EC_ERROR_TIMEOUT; goto exit_wr; @@ -245,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; } |