summaryrefslogtreecommitdiff
path: root/chip/lm4/flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/lm4/flash.c')
-rw-r--r--chip/lm4/flash.c293
1 files changed, 0 insertions, 293 deletions
diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c
deleted file mode 100644
index 5b61874984..0000000000
--- a/chip/lm4/flash.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* Flash memory module for Chrome EC */
-
-#include "flash.h"
-#include "registers.h"
-#include "switch.h"
-#include "system.h"
-#include "timer.h"
-#include "util.h"
-#include "watchdog.h"
-
-#define FLASH_FWB_WORDS 32
-#define FLASH_FWB_BYTES (FLASH_FWB_WORDS * 4)
-
-#define BANK_SHIFT 5 /* bank registers have 32bits each, 2^32 */
-#define BANK_MASK (BIT(BANK_SHIFT) - 1) /* 5 bits */
-#define F_BANK(b) ((b) >> BANK_SHIFT)
-#define F_BIT(b) (1 << ((b) & BANK_MASK))
-
-/* Flash timeouts. These are 2x the spec sheet max. */
-#define ERASE_TIMEOUT_MS 200
-#define WRITE_TIMEOUT_US 300
-
-int stuck_locked; /* Is physical flash stuck protected? */
-int all_protected; /* Has all-flash protection been requested? */
-
-/**
- * Protect flash banks until reboot.
- *
- * @param start_bank Start bank to protect
- * @param bank_count Number of banks to protect
- */
-static void protect_banks(int start_bank, int bank_count)
-{
- int bank;
- for (bank = start_bank; bank < start_bank + bank_count; bank++)
- LM4_FLASH_FMPPE[F_BANK(bank)] &= ~F_BIT(bank);
-}
-
-/**
- * Perform a write-buffer operation. Buffer (FWB) and address (FMA) must be
- * pre-loaded.
- *
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int write_buffer(void)
-{
- int t;
-
- if (all_protected)
- return EC_ERROR_ACCESS_DENIED;
-
- if (!LM4_FLASH_FWBVAL)
- return EC_SUCCESS; /* Nothing to do */
-
- /* Clear previous error status */
- LM4_FLASH_FCMISC = LM4_FLASH_FCRIS;
-
- /* Start write operation at page boundary */
- LM4_FLASH_FMC2 = 0xa4420001;
-
- /*
- * Reload the watchdog timer, so that writing a large amount of flash
- * doesn't cause a watchdog reset.
- */
- watchdog_reload();
-
- /* Wait for write to complete */
- for (t = 0; LM4_FLASH_FMC2 & 0x01; t += 10) {
- if (t > WRITE_TIMEOUT_US)
- return EC_ERROR_TIMEOUT;
- udelay(10);
- }
-
- /* Check for error conditions - program failed, erase needed,
- * voltage error. */
- if (LM4_FLASH_FCRIS & 0x2e01)
- return EC_ERROR_UNKNOWN;
-
- return EC_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Physical layer APIs */
-
-int crec_flash_physical_write(int offset, int size, const char *data)
-{
- const uint32_t *data32 = (const uint32_t *)data;
- int rv;
- int i;
-
- if (all_protected)
- return EC_ERROR_ACCESS_DENIED;
-
- /* 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;
-
- /* Get initial write buffer index and page */
- LM4_FLASH_FMA = offset & ~(FLASH_FWB_BYTES - 1);
- i = (offset >> 2) & (FLASH_FWB_WORDS - 1);
-
- /* Copy words into buffer */
- for (; size > 0; size -= 4) {
- LM4_FLASH_FWB[i++] = *data32++;
- if (i == FLASH_FWB_WORDS) {
- rv = write_buffer();
- if (rv != EC_SUCCESS)
- return rv;
-
- /* Advance to next page */
- i = 0;
- LM4_FLASH_FMA += FLASH_FWB_BYTES;
- }
- }
-
- /* Handle final partial page, if any */
- if (i > 0)
- return write_buffer();
-
- return EC_SUCCESS;
-}
-
-int crec_flash_physical_erase(int offset, int size)
-{
- if (all_protected)
- return EC_ERROR_ACCESS_DENIED;
-
- LM4_FLASH_FCMISC = LM4_FLASH_FCRIS; /* Clear previous error status */
-
- for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
- offset += CONFIG_FLASH_ERASE_SIZE) {
- int t;
-
- /* Do nothing if already erased */
- if (crec_flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
- continue;
-
- LM4_FLASH_FMA = offset;
-
- /*
- * Reload the watchdog timer, so that erasing many flash pages
- * doesn't cause a watchdog reset. May not need this now that
- * we're using msleep() below.
- */
- watchdog_reload();
-
- /* Start erase */
- LM4_FLASH_FMC = 0xa4420002;
-
- /* Wait for erase to complete */
- for (t = 0; LM4_FLASH_FMC & 0x02; t++) {
- if (t > ERASE_TIMEOUT_MS)
- return EC_ERROR_TIMEOUT;
- msleep(1);
- }
-
- /* Check for error conditions - erase failed, voltage error,
- * protection error */
- if (LM4_FLASH_FCRIS & 0x0a01)
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_SUCCESS;
-}
-
-int crec_flash_physical_get_protect(int bank)
-{
- return (LM4_FLASH_FMPPE[F_BANK(bank)] & F_BIT(bank)) ? 0 : 1;
-}
-
-uint32_t crec_flash_physical_get_protect_flags(void)
-{
- uint32_t flags = 0;
-
- /* Read all-protected state from our shadow copy */
- if (all_protected)
- flags |= EC_FLASH_PROTECT_ALL_NOW;
-
- /* Check if blocks were stuck locked at pre-init */
- if (stuck_locked)
- flags |= EC_FLASH_PROTECT_ERROR_STUCK;
-
- return flags;
-}
-
-int crec_flash_physical_protect_now(int all)
-{
- if (all) {
- /* Protect the entire flash */
- all_protected = 1;
- protect_banks(0, CONFIG_FLASH_SIZE_BYTES /
- CONFIG_FLASH_BANK_SIZE);
- } else
- /* Protect the WP region (read-only section and pstate) */
- protect_banks(WP_BANK_OFFSET, WP_BANK_COUNT);
-
- return EC_SUCCESS;
-}
-
-uint32_t crec_flash_physical_get_valid_flags(void)
-{
- return EC_FLASH_PROTECT_RO_AT_BOOT |
- EC_FLASH_PROTECT_RO_NOW |
- EC_FLASH_PROTECT_ALL_NOW;
-}
-
-uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags)
-{
- uint32_t ret = 0;
-
- /* If RO protection isn't enabled, its at-boot state can be changed. */
- if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW))
- ret |= EC_FLASH_PROTECT_RO_AT_BOOT;
-
- /*
- * If entire flash isn't protected at this boot, it can be enabled if
- * the WP GPIO is asserted.
- */
- if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) &&
- (cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))
- ret |= EC_FLASH_PROTECT_ALL_NOW;
-
- return ret;
-}
-
-
-/*****************************************************************************/
-/* 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();
- uint32_t unwanted_prot_flags = EC_FLASH_PROTECT_ALL_NOW |
- EC_FLASH_PROTECT_ERROR_INCONSISTENT;
-
- /*
- * 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) {
- /*
- * Write protect is asserted. If we want RO flash protected,
- * protect it now.
- */
- if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) &&
- !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) {
- int rv = crec_flash_set_protect(EC_FLASH_PROTECT_RO_NOW,
- EC_FLASH_PROTECT_RO_NOW);
- if (rv)
- return rv;
-
- /* Re-read flags */
- prot_flags = crec_flash_get_protect();
- }
-
- /* Update all-now flag if all flash is protected */
- if (prot_flags & EC_FLASH_PROTECT_ALL_NOW)
- all_protected = 1;
-
- } else {
- /* Don't want RO flash protected */
- unwanted_prot_flags |= EC_FLASH_PROTECT_RO_NOW;
- }
-
- /* If there are no unwanted flags, done */
- if (!(prot_flags & unwanted_prot_flags))
- return EC_SUCCESS;
-
- /*
- * If the last reboot was a power-on reset, it should have cleared
- * write-protect. If it didn't, then the flash write protect registers
- * have been permanently committed and we can't fix that.
- */
- if (reset_flags & EC_RESET_FLAG_POWER_ON) {
- stuck_locked = 1;
- return EC_ERROR_ACCESS_DENIED;
- }
-
- /* Otherwise, do a hard boot to clear the flash protection registers */
- system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS);
-
- /* That doesn't return, so if we're still here that's an error */
- return EC_ERROR_UNKNOWN;
-}