diff options
author | Randall Spangler <rspangler@chromium.org> | 2015-02-25 10:53:07 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-26 20:31:58 +0000 |
commit | 3ff0be248c0d3b36dccd47599fd311f2204389af (patch) | |
tree | 4809db25771cfd7c07497d753c073fc534528821 | |
parent | 6aebf13a6b9a88f5c15ef2e7a8d14126add9f66a (diff) | |
download | chrome-ec-3ff0be248c0d3b36dccd47599fd311f2204389af.tar.gz |
npcx: Use SPI status register instead of pstate
The npcx chip and evb use a SPI flash chip to hold the EC image. They
don't need pstate, and should use the SPI flash status register
directly.
1. Remove CONFIG_FLASH_PSTATE from npcx_evb.
2. Remap WP_L GPIO to GPIO 93 (this should be the same as the write protect
line to the SPI flash chip).
3. Change the npcx flash driver so that it directly reads/writes the SPI
status register instead of mucking with pstate.
BUG=chrome-os-partner:34346
BRANCH=none
TEST=manual
Add a switch or jumper to the EVB so R1 can be closed.
Toggle the switch and see that WP_L state changes. Leave enabled.
flashinfo -> nothing is protected, WP_L is enabled (=0)
(also do this after each flashwp command to check the protection status)
flashwp enable -> RO is protected now and at boot.
reboot
flashwp enable -> RO is still protected.
flashwp disable -> RO is still protected. (because WP switch is enabled).
Toggle the switch so WP_L is disabled (=1)
flashwp disable -> Succeeds, flash is not protected
Change-Id: Ifa959bce69f8eb4724057ecaa6a6c5075783c19d
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/253633
Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r-- | board/npcx_evb/gpio.inc | 2 | ||||
-rw-r--r-- | chip/npcx/config_chip.h | 38 | ||||
-rw-r--r-- | chip/npcx/flash.c | 99 |
3 files changed, 50 insertions, 89 deletions
diff --git a/board/npcx_evb/gpio.inc b/board/npcx_evb/gpio.inc index be8f5838ad..8457aff4ae 100644 --- a/board/npcx_evb/gpio.inc +++ b/board/npcx_evb/gpio.inc @@ -7,7 +7,7 @@ /* TODO: Redefine debug 2 inputs */ GPIO(RECOVERY_L, 0, 0, GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */ -GPIO(WP_L, 0, 1, GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */ +GPIO(WP_L, 9, 3, GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */ /* For testing 8042 commands, we need the following GPIOs */ /* TODO: Redefine 4 inputs */ diff --git a/chip/npcx/config_chip.h b/chip/npcx/config_chip.h index 611112aa63..b6fc1d1f3a 100644 --- a/chip/npcx/config_chip.h +++ b/chip/npcx/config_chip.h @@ -8,7 +8,6 @@ /* CPU core BFD configuration */ #include "core/cortex-m/config_core.h" -#define CONFIG_PSTATE_AT_END /* 32k hz internal oscillator frequency (FRCLK) */ #define INT_32K_CLOCK 32768 @@ -65,6 +64,9 @@ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */ #define CONFIG_FLASH_PHYSICAL_SIZE 0x00040000 /* 256KB Flash used for EC */ +/* No PSTATE; uses a real SPI flash */ +#undef CONFIG_FLASH_PSTATE + /****************************************************************************/ /* Define our flash layout. */ /* Size of one firmware image in flash */ @@ -74,30 +76,10 @@ /* RO firmware offset of flash */ #define CONFIG_FW_RO_OFF 0 - -/* - * The EC uses the one bank of flash to emulate a SPI-like write protect - * register with persistent state. - */ -#define CONFIG_FW_PSTATE_SIZE CONFIG_FLASH_BANK_SIZE - -#ifdef CONFIG_PSTATE_AT_END -/* PSTATE is at end of flash */ #define CONFIG_FW_RO_SIZE CONFIG_FW_IMAGE_SIZE -#define CONFIG_FW_PSTATE_OFF (CONFIG_FLASH_PHYSICAL_SIZE \ - - CONFIG_FW_PSTATE_SIZE) -/* Don't claim PSTATE is part of flash */ -#define CONFIG_FLASH_SIZE CONFIG_FW_PSTATE_OFF - -#else -/* PSTATE immediately follows RO, in the first half of flash */ -#define CONFIG_FW_RO_SIZE (CONFIG_FW_IMAGE_SIZE \ - - CONFIG_FW_PSTATE_SIZE) -#define CONFIG_FW_PSTATE_OFF CONFIG_FW_RO_SIZE #define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE -#endif -/* Either way, RW firmware is one firmware image offset from the start */ +/* RW firmware is one firmware image offset from the start */ #define CONFIG_FW_RW_OFF CONFIG_FW_IMAGE_SIZE #define CONFIG_FW_RW_SIZE CONFIG_FW_IMAGE_SIZE @@ -112,17 +94,6 @@ #define CONFIG_LFW_OFFSET 0x1000 /****************************************************************************/ -/* Lock the boot configuration to prevent brickage. */ - -/* - * No GPIO trigger for ROM bootloader. - * Keep JTAG debugging enabled. - * Use 0xA442 flash write key. - * Lock it this way. - */ -#define CONFIG_BOOTCFG_VALUE 0x7ffffffe - -/****************************************************************************/ /* Customize the build */ /* Optional features present on this chip */ @@ -135,7 +106,6 @@ #define CONFIG_MPU #define CONFIG_SPI - /* Compile for running from RAM instead of flash */ /* #define COMPILE_FOR_RAM */ diff --git a/chip/npcx/flash.c b/chip/npcx/flash.c index 04122896b1..e551b0c977 100644 --- a/chip/npcx/flash.c +++ b/chip/npcx/flash.c @@ -179,6 +179,15 @@ static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start, if (sec && bp == 6) return EC_ERROR_INVAL; + /* + * If SRP0 is not set, flash is not protected because status register + * can be rewritten. + */ + if (!(sr1 & SPI_FLASH_SR1_SRP0)) { + *start = *len = 0; + return EC_SUCCESS; + } + /* Determine granularity (4kb sector or 64kb block) */ /* Computation using 2 * 1024 is correct */ size = sec ? (2 * 1024) : (64 * 1024); @@ -274,6 +283,9 @@ static int protect_to_reg(unsigned int start, unsigned int len, | (bp << 2); *sr2 |= (cmp ? SPI_FLASH_SR2_CMP : 0); + /* Set SRP0 so status register can't be changed */ + *sr1 |= SPI_FLASH_SR1_SRP0; + return EC_SUCCESS; } @@ -372,8 +384,10 @@ void flash_burst_write(unsigned int dest_addr, unsigned int bytes, /* Chip Select up */ flash_cs_level(1); } + /*****************************************************************************/ /* Physical layer APIs */ + int flash_physical_read(int offset, int size, char *data) { int dest_addr = offset; @@ -588,6 +602,16 @@ uint32_t flash_physical_get_protect_flags(void) { uint32_t flags = 0; + /* Check if RO section is protected in status register */ + if (flash_check_prot_reg(RO_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE, + RO_BANK_COUNT*CONFIG_FLASH_BANK_SIZE)) + flags |= EC_FLASH_PROTECT_RO_AT_BOOT; + + /* + * TODO: If status register protects a range, but SRP0 is not set, + * flags should indicate EC_FLASH_PROTECT_ERROR_INCONSISTENT. + */ + /* Read all-protected state from our shadow copy */ if (all_protected) flags |= EC_FLASH_PROTECT_ALL_NOW; @@ -597,19 +621,32 @@ uint32_t flash_physical_get_protect_flags(void) int flash_physical_protect_now(int all) { - if (all) { - /* Protect the entire flash */ + if (all) all_protected = 1; - flash_write_prot_reg(0, CONFIG_FLASH_PHYSICAL_SIZE); - } else { - /* Protect the read-only section */ - flash_write_prot_reg(RO_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE, - RO_BANK_COUNT*CONFIG_FLASH_BANK_SIZE); - } + + /* TODO: if all, disable SPI interface */ return EC_SUCCESS; } + +int flash_physical_protect_at_boot(enum flash_wp_range range) +{ + switch (range) { + case FLASH_WP_NONE: + /* Clear protection bits in status register */ + return flash_set_status_for_prot(0, 0); + case FLASH_WP_RO: + /* Protect read-only */ + return flash_write_prot_reg( + RO_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE, + RO_BANK_COUNT*CONFIG_FLASH_BANK_SIZE); + case FLASH_WP_ALL: + default: + return EC_ERROR_INVAL; + } +} + uint32_t flash_physical_get_valid_flags(void) { return EC_FLASH_PROTECT_RO_AT_BOOT | @@ -641,8 +678,6 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) int flash_pre_init(void) { - uint32_t reset_flags, prot_flags, unwanted_prot_flags; - /* Enable FIU interface */ flash_pinmux(1); @@ -651,49 +686,5 @@ int flash_pre_init(void) CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS); #endif - reset_flags = system_get_reset_flags(); - prot_flags = flash_get_protect(); - 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 & RESET_FLAG_SYSJUMP) - return EC_SUCCESS; - - /* Handle flash write-protection */ - 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 = flash_set_protect(EC_FLASH_PROTECT_RO_NOW, - EC_FLASH_PROTECT_RO_NOW); - if (rv) - return rv; - - /* Re-read flags */ - prot_flags = 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; - - /* Otherwise, clear the flash protection bits of status registers */ - flash_set_status_for_prot(0, 0); - return EC_SUCCESS; } |