summaryrefslogtreecommitdiff
path: root/chip/stm32/flash-f.c
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2015-04-03 16:02:16 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-06-03 02:02:42 -0700
commit35f4d8acaa40050f10158459a04e0bf9b24149c6 (patch)
tree2fd1c6127874023ca44be4f3022704fdb29aa2f4 /chip/stm32/flash-f.c
parent5c9118b311ed1d4059b9e51c3defcf5bce62de04 (diff)
downloadchrome-ec-35f4d8acaa40050f10158459a04e0bf9b24149c6.tar.gz
Add flash command support to boards with STM32F4
Add support to write and erase all flash with flashrom. Add support to use all the memory. Note that PSTATE must not used its own page, as the STM32F4 use big pages. BUG=b:38018926 BRANCH=none TEST=With flashrom, write all, RO, RW regions. Use flash command on the console, including flashwp Change-Id: I4f0aee1b3a4f342bdf4ca97bf5d8e8bcc153fd9c Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/264032 Commit-Ready: Wei-Ning Huang <wnhuang@chromium.org> Tested-by: Wei-Ning Huang <wnhuang@chromium.org> Reviewed-by: Alexandru M Stan <amstan@chromium.org>
Diffstat (limited to 'chip/stm32/flash-f.c')
-rw-r--r--chip/stm32/flash-f.c142
1 files changed, 128 insertions, 14 deletions
diff --git a/chip/stm32/flash-f.c b/chip/stm32/flash-f.c
index 15be87beeb..9f7da82914 100644
--- a/chip/stm32/flash-f.c
+++ b/chip/stm32/flash-f.c
@@ -85,6 +85,35 @@ static void lock(void)
STM32_FLASH_CR |= FLASH_CR_LOCK;
}
+#ifdef CHIP_FAMILY_STM32F4
+static int write_optb(uint32_t mask, uint32_t value)
+{
+ int rv;
+
+ rv = wait_busy();
+ if (rv)
+ return rv;
+
+ /* The target byte is the value we want to write. */
+ if ((STM32_FLASH_OPTCR & mask) == value)
+ return EC_SUCCESS;
+
+ rv = unlock(OPT_LOCK);
+ if (rv)
+ return rv;
+
+ STM32_FLASH_OPTCR = (STM32_FLASH_OPTCR & ~mask) | value;
+ STM32_FLASH_OPTCR |= FLASH_OPTSTRT;
+
+ rv = wait_busy();
+ if (rv)
+ return rv;
+ lock();
+
+ return EC_SUCCESS;
+}
+#else
+static int write_optb(int byte, uint8_t value);
/*
* Option byte organization
*
@@ -202,6 +231,7 @@ static int write_optb(int byte, uint8_t value)
return EC_SUCCESS;
}
+#endif
/*****************************************************************************/
/* Physical layer APIs */
@@ -290,6 +320,12 @@ int flash_physical_erase(int offset, int size)
int res = EC_SUCCESS;
int sector_size;
int timeout_us;
+#ifdef CHIP_FAMILY_STM32F4
+ int sector = flash_bank_index(offset);
+ /* we take advantage of sector_size == erase_size */
+ if ((sector < 0) || (flash_bank_index(offset + size) < 0))
+ return EC_ERROR_INVAL; /* Invalid range */
+#endif
if (unlock(NO_EXTRA_LOCK) != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
@@ -302,23 +338,30 @@ int flash_physical_erase(int offset, int size)
while (size > 0) {
timestamp_t deadline;
+#ifdef CHIP_FAMILY_STM32F4
+ sector_size = flash_bank_size(sector);
+ /* Timeout: from spec, proportional to the size
+ * inversely proportional to the write size.
+ */
+ timeout_us = sector_size * 4 / CONFIG_FLASH_WRITE_SIZE;
+#else
sector_size = CONFIG_FLASH_ERASE_SIZE;
timeout_us = FLASH_TIMEOUT_US;
+#endif
/* Do nothing if already erased */
if (flash_is_erased(offset, sector_size))
goto next_sector;
+#ifdef CHIP_FAMILY_STM32F4
+ /* select page to erase */
+ STM32_FLASH_CR = (STM32_FLASH_CR & ~STM32_FLASH_CR_SNB_MASK) |
+ (sector << STM32_FLASH_CR_SNB_OFFSET);
+#else
/* select page to erase */
STM32_FLASH_AR = CONFIG_PROGRAM_MEMORY_BASE + offset;
-
+#endif
/* set STRT bit : start erase */
STM32_FLASH_CR |= FLASH_CR_STRT;
- /*
- * Reload the watchdog timer to avoid watchdog reset during a
- * long erase operation.
- */
- watchdog_reload();
-
deadline.val = get_time().val + timeout_us;
/* Wait for erase to complete */
watchdog_reload();
@@ -342,6 +385,9 @@ int flash_physical_erase(int offset, int size)
next_sector:
size -= sector_size;
offset += sector_size;
+#ifdef CHIP_FAMILY_STM32F4
+ sector++;
+#endif
}
exit_er:
@@ -353,6 +399,63 @@ exit_er:
return res;
}
+#ifdef CHIP_FAMILY_STM32F4
+static int flash_physical_get_protect_at_boot(int block)
+{
+ /* 0: Write protection active on sector i. */
+ return !(STM32_OPTB_WP & STM32_OPTB_nWRP(block));
+}
+
+int flash_physical_protect_at_boot(uint32_t new_flags)
+{
+ int block;
+ int original_val, val;
+
+ original_val = val = STM32_OPTB_WP & STM32_OPTB_nWRP_ALL;
+
+ for (block = WP_BANK_OFFSET;
+ block < WP_BANK_OFFSET + PHYSICAL_BANKS;
+ block++) {
+ int protect = new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT;
+
+ if (block >= WP_BANK_OFFSET &&
+ block < WP_BANK_OFFSET + WP_BANK_COUNT)
+ protect |= new_flags & EC_FLASH_PROTECT_RO_AT_BOOT;
+#ifdef CONFIG_FLASH_PROTECT_RW
+ else
+ protect |= new_flags & EC_FLASH_PROTECT_RW_AT_BOOT;
+#endif
+
+ if (protect)
+ val &= ~(1 << block);
+ else
+ val |= 1 << block;
+ }
+ if (original_val != val) {
+ write_optb(STM32_FLASH_nWRP_ALL,
+ val << STM32_FLASH_nWRP_OFFSET);
+ }
+
+
+ return EC_SUCCESS;
+}
+
+static void unprotect_all_blocks(void)
+{
+ write_optb(STM32_FLASH_nWRP_ALL, STM32_FLASH_nWRP_ALL);
+}
+
+int flash_physical_protect_now(int all)
+{
+ if (all) {
+ write_optb(STM32_FLASH_nWRP_ALL, 0);
+ return EC_SUCCESS;
+ }
+ /* No way to protect just the RO flash until next boot */
+ return EC_ERROR_INVAL;
+}
+
+#else /* CHIP_FAMILY_STM32F4 */
static int flash_physical_get_protect_at_boot(int block)
{
uint8_t val = read_optb(STM32_OPTB_WRP_OFF(block/8));
@@ -408,6 +511,15 @@ int flash_physical_protect_at_boot(uint32_t new_flags)
return EC_SUCCESS;
}
+static void unprotect_all_blocks(void)
+{
+ int i;
+
+ for (i = 4; i < 8; ++i)
+ write_optb(i * 2, 0xff);
+}
+#endif
+
/**
* Check if write protect register state is inconsistent with RO_AT_BOOT and
* ALL_AT_BOOT state.
@@ -431,13 +543,6 @@ static int registers_need_reset(void)
return 0;
}
-static void unprotect_all_blocks(void)
-{
- int i;
- for (i = 4; i < 8; ++i)
- write_optb(i * 2, 0xff);
-}
-
/*****************************************************************************/
/* High-level APIs */
@@ -447,6 +552,15 @@ int flash_pre_init(void)
uint32_t prot_flags = flash_get_protect();
int need_reset = 0;
+
+#ifdef CHIP_FAMILY_STM32F4
+ unlock(NO_EXTRA_LOCK);
+ /* Set the proper write size */
+ STM32_FLASH_CR = (STM32_FLASH_CR & ~STM32_FLASH_CR_PSIZE_MASK) |
+ (31 - __builtin_clz(CONFIG_FLASH_WRITE_SIZE)) <<
+ STM32_FLASH_CR_PSIZE_OFFSET;
+ lock();
+#endif
if (flash_physical_restore_state())
return EC_SUCCESS;