summaryrefslogtreecommitdiff
path: root/chip/npcx/flash.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2015-02-25 10:53:07 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-26 20:31:58 +0000
commit3ff0be248c0d3b36dccd47599fd311f2204389af (patch)
tree4809db25771cfd7c07497d753c073fc534528821 /chip/npcx/flash.c
parent6aebf13a6b9a88f5c15ef2e7a8d14126add9f66a (diff)
downloadchrome-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>
Diffstat (limited to 'chip/npcx/flash.c')
-rw-r--r--chip/npcx/flash.c99
1 files changed, 45 insertions, 54 deletions
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;
}