summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-05-24 11:44:27 -0700
committerChromeBot <chrome-bot@google.com>2013-05-24 16:27:48 -0700
commitb144a584af63891b134c3f789fdd00ac232a9577 (patch)
treee16aea3d30c038cac3e48a55afd54f05280a4d75
parent3443478d7659d8222222c073fb8ed2e6164b93d9 (diff)
downloadchrome-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.h9
-rw-r--r--chip/stm32/flash-stm32l15x.c80
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;
}