summaryrefslogtreecommitdiff
path: root/chip/stm32/flash-f.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/stm32/flash-f.c')
-rw-r--r--chip/stm32/flash-f.c833
1 files changed, 0 insertions, 833 deletions
diff --git a/chip/stm32/flash-f.c b/chip/stm32/flash-f.c
deleted file mode 100644
index 9e35a2c689..0000000000
--- a/chip/stm32/flash-f.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/* Copyright 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* Common flash memory module for STM32F and STM32F0 */
-
-#include <stdbool.h>
-#include "battery.h"
-#include "console.h"
-#include "clock.h"
-#include "flash.h"
-#include "flash-f.h"
-#include "hooks.h"
-#include "registers.h"
-#include "panic.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "watchdog.h"
-
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-
-/*
- * Approximate number of CPU cycles per iteration of the loop when polling
- * the flash status
- */
-#define CYCLE_PER_FLASH_LOOP 10
-
-/*
- * While flash write / erase is in progress, the stm32 CPU core is mostly
- * non-functional, due to the inability to fetch instructions from flash.
- * This may greatly increase interrupt latency.
- */
-
-/* Flash page programming timeout. This is 2x the datasheet max. */
-#define FLASH_WRITE_TIMEOUT_US 16000
-/* 20ms < tERASE < 40ms on F0/F3, for 1K / 2K sector size. */
-#define FLASH_ERASE_TIMEOUT_US 40000
-
-#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
-#if !defined(CHIP_FAMILY_STM32F4)
-#error "CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE should work with all STM32F "
-"series chips, but has not been tested"
-#endif /* !CHIP_FAMILY_STM32F4 */
-#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
-
-/* Forward declarations */
-#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
-static enum flash_rdp_level flash_physical_get_rdp_level(void);
-static int flash_physical_set_rdp_level(enum flash_rdp_level level);
-#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
-
-static inline int calculate_flash_timeout(void)
-{
- return (FLASH_WRITE_TIMEOUT_US *
- (clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP);
-}
-
-static int wait_busy(void)
-{
- int timeout = calculate_flash_timeout();
- while ((STM32_FLASH_SR & FLASH_SR_BUSY) && timeout-- > 0)
- udelay(CYCLE_PER_FLASH_LOOP);
- return (timeout > 0) ? EC_SUCCESS : EC_ERROR_TIMEOUT;
-}
-
-
-void unlock_flash_control_register(void)
-{
- STM32_FLASH_KEYR = FLASH_KEYR_KEY1;
- STM32_FLASH_KEYR = FLASH_KEYR_KEY2;
-}
-
-void unlock_flash_option_bytes(void)
-{
- STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1;
- STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY2;
-}
-
-void disable_flash_option_bytes(void)
-{
- ignore_bus_fault(1);
- /*
- * Writing anything other than the pre-defined keys to the option key
- * register results in a bus fault and the register being locked until
- * reboot (even with a further correct key write).
- */
- STM32_FLASH_OPTKEYR = 0xffffffff;
- ignore_bus_fault(0);
-}
-
-void disable_flash_control_register(void)
-{
- ignore_bus_fault(1);
- /*
- * Writing anything other than the pre-defined keys to the key
- * register results in a bus fault and the register being locked until
- * reboot (even with a further correct key write).
- */
- STM32_FLASH_KEYR = 0xffffffff;
- ignore_bus_fault(0);
-}
-
-void lock_flash_control_register(void)
-{
-#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
- /* FLASH_CR_OPTWRE was set by writing the keys in unlock(). */
- STM32_FLASH_CR &= ~FLASH_CR_OPTWRE;
-#endif
- STM32_FLASH_CR |= FLASH_CR_LOCK;
-}
-
-void lock_flash_option_bytes(void)
-{
-#if !(defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3))
- STM32_FLASH_OPTCR |= FLASH_OPTLOCK;
-#endif
-}
-
-bool flash_option_bytes_locked(void)
-{
- return !!STM32_FLASH_OPT_LOCKED;
-}
-
-bool flash_control_register_locked(void)
-{
- return !!(STM32_FLASH_CR & FLASH_CR_LOCK);
-}
-
-/*
- * We at least unlock the control register lock.
- * We may also unlock other locks.
- */
-enum extra_lock_type {
- NO_EXTRA_LOCK = 0,
- OPT_LOCK = 1,
-};
-
-static int unlock(int locks)
-{
- /*
- * We may have already locked the flash module and get a bus fault
- * in the attempt to unlock. Need to disable bus fault handler now.
- */
- ignore_bus_fault(1);
-
- /* Always unlock CR if needed */
- if (flash_control_register_locked())
- unlock_flash_control_register();
-
- /* unlock option memory if required */
- if ((locks & OPT_LOCK) && flash_option_bytes_locked())
- unlock_flash_option_bytes();
-
- /* Re-enable bus fault handler */
- ignore_bus_fault(0);
-
- if ((locks & OPT_LOCK) && flash_option_bytes_locked())
- return EC_ERROR_UNKNOWN;
- if (STM32_FLASH_CR & FLASH_CR_LOCK)
- return EC_ERROR_UNKNOWN;
- return EC_SUCCESS;
-}
-
-static void lock(void)
-{
- lock_flash_control_register();
-}
-
-#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
- *
- * [31:24] [23:16] [15:8] [7:0]
- *
- * 0x1FFF_F800 nUSER USER nRDP RDP
- *
- * 0x1FFF_F804 nData1 Data1 nData0 Data0
- *
- * 0x1FFF_F808 nWRP1 WRP1 nWRP0 WRP0
- *
- * 0x1FFF_F80C nWRP3 WRP2 nWRP2 WRP2
- *
- * Note that the variable with n prefix means the complement.
- */
-static uint8_t read_optb(int byte)
-{
- return *(uint8_t *)(STM32_OPTB_BASE + byte);
-}
-
-static int erase_optb(void)
-{
- int rv;
-
- rv = wait_busy();
- if (rv)
- return rv;
-
- rv = unlock(OPT_LOCK);
- if (rv)
- return rv;
-
- /* Must be set in 2 separate lines. */
- STM32_FLASH_CR |= FLASH_CR_OPTER;
- STM32_FLASH_CR |= FLASH_CR_STRT;
-
- rv = wait_busy();
-
- STM32_FLASH_CR &= ~FLASH_CR_OPTER;
-
- if (rv)
- return rv;
- lock();
-
- return EC_SUCCESS;
-}
-
-static int write_optb(int byte, uint8_t value);
-/*
- * Since the option byte erase is WHOLE erase, this function is to keep
- * rest of bytes, but make this byte 0xff.
- * Note that this could make a recursive call to write_optb().
- */
-static int preserve_optb(int byte)
-{
- int i, rv;
- uint8_t optb[8];
-
- /* The byte has been reset, no need to run preserve. */
- if (*(uint16_t *)(STM32_OPTB_BASE + byte) == 0xffff)
- return EC_SUCCESS;
-
- for (i = 0; i < ARRAY_SIZE(optb); ++i)
- optb[i] = read_optb(i * 2);
-
- optb[byte / 2] = 0xff;
-
- rv = erase_optb();
- if (rv)
- return rv;
- for (i = 0; i < ARRAY_SIZE(optb); ++i) {
- rv = write_optb(i * 2, optb[i]);
- if (rv)
- return rv;
- }
-
- return EC_SUCCESS;
-}
-
-static int write_optb(int byte, uint8_t value)
-{
- volatile int16_t *hword = (uint16_t *)(STM32_OPTB_BASE + byte);
- int rv;
-
- rv = wait_busy();
- if (rv)
- return rv;
-
- /* The target byte is the value we want to write. */
- if (*(uint8_t *)hword == value)
- return EC_SUCCESS;
-
- /* Try to erase that byte back to 0xff. */
- rv = preserve_optb(byte);
- if (rv)
- return rv;
-
- /* The value is 0xff after erase. No need to write 0xff again. */
- if (value == 0xff)
- return EC_SUCCESS;
-
- rv = unlock(OPT_LOCK);
- if (rv)
- return rv;
-
- /* set OPTPG bit */
- STM32_FLASH_CR |= FLASH_CR_OPTPG;
-
- *hword = ((~value) << STM32_OPTB_COMPL_SHIFT) | value;
-
- /* reset OPTPG bit */
- STM32_FLASH_CR &= ~FLASH_CR_OPTPG;
-
- rv = wait_busy();
- if (rv)
- return rv;
- lock();
-
- return EC_SUCCESS;
-}
-#endif
-
-#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
-/**
- * @return true if RDP (read protection) Level 1 or 2 enabled, false otherwise
- */
-bool is_flash_rdp_enabled(void)
-{
- enum flash_rdp_level level = flash_physical_get_rdp_level();
-
- if (level == FLASH_RDP_LEVEL_INVALID) {
- CPRINTS("ERROR: unable to read RDP level");
- return false;
- }
-
- return level != FLASH_RDP_LEVEL_0;
-}
-#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
-
-/*****************************************************************************/
-/* Physical layer APIs */
-
-int crec_flash_physical_write(int offset, int size, const char *data)
-{
-#if CONFIG_FLASH_WRITE_SIZE == 1
- uint8_t *address = (uint8_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
- uint8_t quantum = 0;
-#elif CONFIG_FLASH_WRITE_SIZE == 2
- uint16_t *address = (uint16_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
- uint16_t quantum = 0;
-#elif CONFIG_FLASH_WRITE_SIZE == 4
- uint32_t *address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
- uint32_t quantum = 0;
-#else
-#error "CONFIG_FLASH_WRITE_SIZE not supported."
-#endif
- int res = EC_SUCCESS;
- int timeout = calculate_flash_timeout();
-
- if (unlock(NO_EXTRA_LOCK) != EC_SUCCESS) {
- res = EC_ERROR_UNKNOWN;
- goto exit_wr;
- }
-
- /* Clear previous error status */
- STM32_FLASH_SR = FLASH_SR_ALL_ERR | FLASH_SR_EOP;
-
- /* set PG bit */
- STM32_FLASH_CR |= FLASH_CR_PG;
-
- for (; size > 0; size -= CONFIG_FLASH_WRITE_SIZE) {
- int i;
-
- for (i = CONFIG_FLASH_WRITE_SIZE - 1, quantum = 0; i >= 0; i--)
- quantum = (quantum << 8) + data[i];
- data += CONFIG_FLASH_WRITE_SIZE;
- /*
- * Reload the watchdog timer to avoid watchdog reset when doing
- * long writing with interrupt disabled.
- */
- watchdog_reload();
-
- /* wait to be ready */
- for (i = 0;
- (STM32_FLASH_SR & FLASH_SR_BUSY) &&
- (i < timeout);
- i++)
- ;
-
- /* write the data */
- *address++ = quantum;
-
- /* Wait for writes to complete */
- for (i = 0;
- (STM32_FLASH_SR & FLASH_SR_BUSY) &&
- (i < timeout);
- i++)
- ;
-
- if (STM32_FLASH_SR & FLASH_SR_BUSY) {
- res = EC_ERROR_TIMEOUT;
- goto exit_wr;
- }
-
- /* Check for error conditions - erase failed, voltage error,
- * protection error */
- if (STM32_FLASH_SR & FLASH_SR_ALL_ERR) {
- res = EC_ERROR_UNKNOWN;
- goto exit_wr;
- }
- }
-
-exit_wr:
- /* Disable PG bit */
- STM32_FLASH_CR &= ~FLASH_CR_PG;
-
- lock();
-
- return res;
-}
-
-int crec_flash_physical_erase(int offset, int size)
-{
- int res = EC_SUCCESS;
- int sector_size;
- int timeout_us;
-#ifdef CHIP_FAMILY_STM32F4
- int sector = crec_flash_bank_index(offset);
- /* we take advantage of sector_size == erase_size */
- if ((sector < 0) || (crec_flash_bank_index(offset + size) < 0))
- return EC_ERROR_INVAL; /* Invalid range */
-#endif
-
- if (unlock(NO_EXTRA_LOCK) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
-
- /* Clear previous error status */
- STM32_FLASH_SR = FLASH_SR_ALL_ERR | FLASH_SR_EOP;
-
- /* set SER/PER bit */
- STM32_FLASH_CR |= FLASH_CR_PER;
-
- while (size > 0) {
- timestamp_t deadline;
-#ifdef CHIP_FAMILY_STM32F4
- sector_size = crec_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_ERASE_TIMEOUT_US;
-#endif
- /* Do nothing if already erased */
- if (crec_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;
-
- deadline.val = get_time().val + timeout_us;
- /* Wait for erase to complete */
- watchdog_reload();
- while ((STM32_FLASH_SR & FLASH_SR_BUSY) &&
- (get_time().val < deadline.val)) {
- usleep(timeout_us/100);
- }
- if (STM32_FLASH_SR & FLASH_SR_BUSY) {
- res = EC_ERROR_TIMEOUT;
- goto exit_er;
- }
-
- /*
- * Check for error conditions - erase failed, voltage error,
- * protection error
- */
- if (STM32_FLASH_SR & FLASH_SR_ALL_ERR) {
- res = EC_ERROR_UNKNOWN;
- goto exit_er;
- }
-next_sector:
- size -= sector_size;
- offset += sector_size;
-#ifdef CHIP_FAMILY_STM32F4
- sector++;
-#endif
- }
-
-exit_er:
- /* reset SER/PER bit */
- STM32_FLASH_CR &= ~FLASH_CR_PER;
-
- lock();
-
- 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));
-}
-
-static int flash_physical_protect_at_boot_update_rdp_pstate(uint32_t new_flags)
-{
-#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
- int rv = EC_SUCCESS;
-
- bool rdp_enable = (new_flags & EC_FLASH_PROTECT_RO_AT_BOOT) != 0;
-
- /*
- * This is intentionally a one-way latch. Once we have enabled RDP
- * Level 1, we will only allow going back to Level 0 using the
- * bootloader (e.g., "stm32mon -U") since transitioning from Level 1 to
- * Level 0 triggers a mass erase.
- */
- if (rdp_enable)
- rv = flash_physical_set_rdp_level(FLASH_RDP_LEVEL_1);
-
- return rv;
-#else
- return EC_SUCCESS;
-#endif
-}
-
-int crec_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 &= ~BIT(block);
- else
- val |= 1 << block;
- }
- if (original_val != val) {
- int rv = write_optb(STM32_FLASH_nWRP_ALL,
- val << STM32_FLASH_nWRP_OFFSET);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- return flash_physical_protect_at_boot_update_rdp_pstate(new_flags);
-}
-
-static void unprotect_all_blocks(void)
-{
- write_optb(STM32_FLASH_nWRP_ALL, STM32_FLASH_nWRP_ALL);
-}
-
-#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));
- return (!(val & (1 << (block % 8)))) ? 1 : 0;
-}
-
-int crec_flash_physical_protect_at_boot(uint32_t new_flags)
-{
- int block;
- int i;
- int original_val[4], val[4];
-
- for (i = 0; i < 4; ++i)
- original_val[i] = val[i] = read_optb(i * 2 + 8);
-
- for (block = WP_BANK_OFFSET;
- block < WP_BANK_OFFSET + PHYSICAL_BANKS;
- block++) {
- int protect = new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT;
- int byte_off = STM32_OPTB_WRP_OFF(block/8) / 2 - 4;
-
- if (block >= WP_BANK_OFFSET &&
- block < WP_BANK_OFFSET + WP_BANK_COUNT)
- protect |= new_flags & EC_FLASH_PROTECT_RO_AT_BOOT;
-#ifdef CONFIG_ROLLBACK
- else if (block >= ROLLBACK_BANK_OFFSET &&
- block < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT)
- protect |= new_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT;
-#endif
-#ifdef CONFIG_FLASH_PROTECT_RW
- else
- protect |= new_flags & EC_FLASH_PROTECT_RW_AT_BOOT;
-#endif
-
- if (protect)
- val[byte_off] = val[byte_off] & (~(1 << (block % 8)));
- else
- val[byte_off] = val[byte_off] | (1 << (block % 8));
- }
-
- for (i = 0; i < 4; ++i)
- if (original_val[i] != val[i])
- write_optb(i * 2 + 8, val[i]);
-
-#ifdef CONFIG_FLASH_READOUT_PROTECTION
- /*
- * Set a permanent protection by increasing RDP to level 1,
- * trying to unprotected the flash will trigger a full erase.
- */
- write_optb(0, 0x11);
-#endif
-
- 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.
- *
- * @return zero if consistent, non-zero if inconsistent.
- */
-static int registers_need_reset(void)
-{
- uint32_t flags = crec_flash_get_protect();
- int i;
- int ro_at_boot = (flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? 1 : 0;
- int ro_wp_region_start = WP_BANK_OFFSET;
- int ro_wp_region_end = WP_BANK_OFFSET + WP_BANK_COUNT;
-
- for (i = ro_wp_region_start; i < ro_wp_region_end; i++)
- if (flash_physical_get_protect_at_boot(i) != ro_at_boot)
- return 1;
- return 0;
-}
-
-#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
-/**
- * Set Flash RDP (read protection) level.
- *
- * @note Does not take effect until reset.
- *
- * @param level new RDP (read protection) level to set
- * @return EC_SUCCESS on success, other on failure
- */
-int flash_physical_set_rdp_level(enum flash_rdp_level level)
-{
- uint32_t reg_level;
-
- switch (level) {
- case FLASH_RDP_LEVEL_0:
- /*
- * Asserting by default since we don't want to inadvertently
- * go from Level 1 to Level 0, which triggers a mass erase.
- * Remove assert if you want to use it.
- */
- ASSERT(false);
- reg_level = FLASH_OPTCR_RDP_LEVEL_0;
- break;
- case FLASH_RDP_LEVEL_1:
- reg_level = FLASH_OPTCR_RDP_LEVEL_1;
- break;
- case FLASH_RDP_LEVEL_2:
- /*
- * Asserting by default since it's permanent (there is no
- * way to reverse). Remove assert if you want to use it.
- */
- ASSERT(false);
- reg_level = FLASH_OPTCR_RDP_LEVEL_2;
- break;
- default:
- return EC_ERROR_INVAL;
- }
-
- return write_optb(FLASH_OPTCR_RDP_MASK, reg_level);
-}
-
-/**
- * @return On success, current flash read protection level.
- * On failure, FLASH_RDP_LEVEL_INVALID
- */
-enum flash_rdp_level flash_physical_get_rdp_level(void)
-{
- uint32_t level = (STM32_FLASH_OPTCR & FLASH_OPTCR_RDP_MASK);
-
- switch (level) {
- case FLASH_OPTCR_RDP_LEVEL_0:
- return FLASH_RDP_LEVEL_0;
- case FLASH_OPTCR_RDP_LEVEL_1:
- return FLASH_RDP_LEVEL_1;
- case FLASH_OPTCR_RDP_LEVEL_2:
- return FLASH_RDP_LEVEL_2;
- default:
- return FLASH_RDP_LEVEL_INVALID;
- }
-}
-#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
-
-/*****************************************************************************/
-/* High-level APIs */
-
-int crec_flash_pre_init(void)
-{
- uint32_t reset_flags = system_get_reset_flags();
- uint32_t prot_flags = crec_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 (crec_flash_physical_restore_state())
- return EC_SUCCESS;
-
- /*
- * If we have already jumped between images, an earlier image could
- * have applied write protection. Nothing additional needs to be done.
- */
- if (reset_flags & EC_RESET_FLAG_SYSJUMP)
- return EC_SUCCESS;
-
- if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) {
- if (prot_flags & EC_FLASH_PROTECT_RO_NOW) {
- /* Enable physical protection for RO (0 means RO). */
- crec_flash_physical_protect_now(0);
- }
-
- if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) &&
- !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) {
- /*
- * Pstate wants RO protected at boot, but the write
- * protect register wasn't set to protect it. Force an
- * update to the write protect register and reboot so
- * it takes effect.
- */
- crec_flash_physical_protect_at_boot(
- EC_FLASH_PROTECT_RO_AT_BOOT);
- need_reset = 1;
- }
-
- if (registers_need_reset()) {
- /*
- * Write protect register was in an inconsistent state.
- * Set it back to a good state and reboot.
- *
- * TODO(crosbug.com/p/23798): this seems really similar
- * to the check above. One of them should be able to
- * go away.
- */
- crec_flash_protect_at_boot(
- prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT);
- need_reset = 1;
- }
- } else {
- if (prot_flags & EC_FLASH_PROTECT_RO_NOW) {
- /*
- * Write protect pin unasserted but some section is
- * protected. Drop it and reboot.
- */
- unprotect_all_blocks();
- need_reset = 1;
- }
- }
-
- if ((crec_flash_physical_get_valid_flags() &
- EC_FLASH_PROTECT_ALL_AT_BOOT) &&
- (!!(prot_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) !=
- !!(prot_flags & EC_FLASH_PROTECT_ALL_NOW))) {
- /*
- * ALL_AT_BOOT and ALL_NOW should be both set or both unset
- * at boot. If they are not, it must be that the chip requires
- * OBL_LAUNCH to be set to reload option bytes. Let's reset
- * the system with OBL_LAUNCH set.
- * This assumes OBL_LAUNCH is used for hard reset in
- * chip/stm32/system.c.
- */
- need_reset = 1;
- }
-
-#ifdef CONFIG_FLASH_PROTECT_RW
- if ((crec_flash_physical_get_valid_flags() &
- EC_FLASH_PROTECT_RW_AT_BOOT) &&
- (!!(prot_flags & EC_FLASH_PROTECT_RW_AT_BOOT) !=
- !!(prot_flags & EC_FLASH_PROTECT_RW_NOW))) {
- /* RW_AT_BOOT and RW_NOW do not match. */
- need_reset = 1;
- }
-#endif
-
-#ifdef CONFIG_ROLLBACK
- if ((crec_flash_physical_get_valid_flags() &
- EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) &&
- (!!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) !=
- !!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_NOW))) {
- /* ROLLBACK_AT_BOOT and ROLLBACK_NOW do not match. */
- need_reset = 1;
- }
-#endif
-
- if (need_reset)
- system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS);
-
- return EC_SUCCESS;
-}