summaryrefslogtreecommitdiff
path: root/common/spi_flash.c
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2015-03-11 18:09:30 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-03-17 01:42:30 +0000
commit746debdf20a647fbe0e197f8a6c7b0597bc6a27f (patch)
tree11f04a0d74e583f71d0e7cab4c6007db52384fbc /common/spi_flash.c
parentfa671e65917b6673250af23e58372bcec272ca0e (diff)
downloadchrome-ec-746debdf20a647fbe0e197f8a6c7b0597bc6a27f.tar.gz
spi_flash: Rework protection translation functions
Previously we defined separate functions to map registers to protect ranges for each supported SPI ROM. This change instead adds a protect range table + flags for each supported SPI ROM and adds common functions for translation between ranges + registers. This makes supporting new parts easier. Since we will never use most supported protection ranges, we can even simplfy the tables. The implementation is now similar to flashrom. BUG=chrome-os-partner:37688 TEST=Manual on Glower. flashwp disable + spi_flash_rsr --> 0 flashinfo --> shows no protection spi_flash_prot 0 0x10000 + spi_flash_rsr --> 0x24 flashinfo --> shows 64KB protected spi_flash_prot 0 0x20000 + spi_flash_rsr --> 0x28 flashinfo --> shows all 96KB protected spi_flash_prot 0 0x40000 + spi_flash_rsr --> 0x2c spi_flash_prot 0 0x80000 + spi_flash_rsr --> 0x10 spi_flash_prot 0 0 + spi_flash_rsr --> 0x00 spi_flash_prot 0 0x1000 --> error spi_flash_prot 0x10000 0x10000 --> error BRANCH=None Change-Id: Ie5908ce687b7ff207b09794c7b001a4fbd9e0f5a Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/259310 Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/spi_flash.c')
-rw-r--r--common/spi_flash.c241
1 files changed, 5 insertions, 236 deletions
diff --git a/common/spi_flash.c b/common/spi_flash.c
index 53a480daab..23ac520059 100644
--- a/common/spi_flash.c
+++ b/common/spi_flash.c
@@ -11,6 +11,7 @@
#include "shared_mem.h"
#include "spi.h"
#include "spi_flash.h"
+#include "spi_flash_reg.h"
#include "timer.h"
#include "util.h"
#include "watchdog.h"
@@ -25,242 +26,10 @@
*/
#define SPI_FLASH_TIMEOUT_USEC (800*MSEC)
-/*
- * Common registers for SPI flash. All registers may not be valid for
- * all parts.
- */
-#define SPI_FLASH_SR2_SUS (1 << 7)
-#define SPI_FLASH_SR2_CMP (1 << 6)
-#define SPI_FLASH_SR2_LB3 (1 << 5)
-#define SPI_FLASH_SR2_LB2 (1 << 4)
-#define SPI_FLASH_SR2_LB1 (1 << 3)
-#define SPI_FLASH_SR2_QE (1 << 1)
-#define SPI_FLASH_SR2_SRP1 (1 << 0)
-#define SPI_FLASH_SR1_SRP0 (1 << 7)
-#define SPI_FLASH_SR1_SEC (1 << 6)
-#define SPI_FLASH_SR1_TB (1 << 5)
-#define SPI_FLASH_SR1_BP2 (1 << 4)
-#define SPI_FLASH_SR1_BP1 (1 << 3)
-#define SPI_FLASH_SR1_BP0 (1 << 2)
-#define SPI_FLASH_SR1_WEL (1 << 1)
-#define SPI_FLASH_SR1_BUSY (1 << 0)
-
/* Internal buffer used by SPI flash driver */
static uint8_t buf[SPI_FLASH_MAX_MESSAGE_SIZE];
/**
- * Computes block write protection range from registers
- * Returns start == len == 0 for no protection
- *
- * @param sr1 Status register 1
- * @param sr2 Status register 2
- * @param start Output pointer for protection start offset
- * @param len Output pointer for protection length
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-#ifdef CONFIG_SPI_FLASH_W25Q64
-static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
- unsigned int *len)
-{
- int blocks;
- int size;
- uint8_t cmp;
- uint8_t sec;
- uint8_t tb;
- uint8_t bp;
-
- /* Determine flags */
- cmp = (sr2 & SPI_FLASH_SR2_CMP) ? 1 : 0;
- sec = (sr1 & SPI_FLASH_SR1_SEC) ? 1 : 0;
- tb = (sr1 & SPI_FLASH_SR1_TB) ? 1 : 0;
- bp = (sr1 & (SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 | SPI_FLASH_SR1_BP0))
- >> 2;
-
- /* Bad pointers or invalid data */
- if (!start || !len || sr1 == -1 || sr2 == -1)
- return EC_ERROR_INVAL;
-
- /* Not defined by datasheet */
- if (sec && bp == 6)
- return EC_ERROR_INVAL;
-
- /* Determine granularity (4kb sector or 64kb block) */
- /* Computation using 2 * 1024 is correct */
- size = sec ? (2 * 1024) : (64 * 1024);
-
- /* Determine number of blocks */
- /* Equivalent to pow(2, bp) with pow(2, 0) = 0 */
- blocks = bp ? (1 << bp) : 0;
- /* Datasheet specifies don't care for BP == 4, BP == 5 */
- if (sec && bp == 5)
- blocks = (1 << 4);
-
- /* Determine number of bytes */
- *len = size * blocks;
-
- /* Determine bottom/top of memory to protect */
- *start = tb ? 0 :
- (CONFIG_SPI_FLASH_SIZE - *len) % CONFIG_SPI_FLASH_SIZE;
-
- /* Reverse computations if complement set */
- if (cmp) {
- *start = (*start + *len) % CONFIG_SPI_FLASH_SIZE;
- *len = CONFIG_SPI_FLASH_SIZE - *len;
- }
-
- return EC_SUCCESS;
-}
-#elif defined(CONFIG_SPI_FLASH_W25X40) /* CONFIG_SPI_FLASH_W25Q64 */
-static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
- unsigned int *len)
-{
- int blocks;
- int size;
- uint8_t tb;
- uint8_t bp;
-
- tb = (sr1 & SPI_FLASH_SR1_TB) ? 1 : 0;
- bp = (sr1 & (SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 | SPI_FLASH_SR1_BP0))
- >> 2;
-
- /* Bad pointers or invalid data */
- if (!start || !len || sr1 == -1 || sr2 == -1)
- return EC_ERROR_INVAL;
-
- /* 64kb block protection granularity */
- size = 32 * 1024;
-
- /* Determine number of blocks */
- /* Equivalent to pow(2, bp) with pow(2, 0) = 0 */
- /* BP2 set indicates entire 512kb flash protected */
- if (!bp)
- blocks = 0;
- else
- blocks = MIN((1 << 4), (1 << bp));
- *len = size * blocks;
- *start = tb ? 0 :
- (CONFIG_SPI_FLASH_SIZE - *len) % CONFIG_SPI_FLASH_SIZE;
-
- return EC_SUCCESS;
-}
-#endif /* CONFIG_SPI_FLASH_W25X40 */
-
-/**
- * Computes block write protection registers from range
- *
- * @param start Desired protection start offset
- * @param len Desired protection length
- * @param sr1 Output pointer for status register 1
- * @param sr2 Output pointer for status register 2
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-#ifdef CONFIG_SPI_FLASH_W25Q64
-static int protect_to_reg(unsigned int start, unsigned int len,
- uint8_t *sr1, uint8_t *sr2)
-{
- char cmp = 0;
- char sec = 0;
- char tb = 0;
- char bp = 0;
- int blocks;
- int size;
-
- /* Bad pointers */
- if (!sr1 || !sr2 || *sr1 == -1 || *sr2 == -1)
- return EC_ERROR_INVAL;
-
- /* Invalid data */
- if ((start && !len) || start + len > CONFIG_SPI_FLASH_SIZE)
- return EC_ERROR_INVAL;
-
- /* Set complement bit based on whether length is power of 2 */
- if ((len & (len - 1)) != 0) {
- cmp = 1;
- start = (start + len) % CONFIG_SPI_FLASH_SIZE;
- len = CONFIG_SPI_FLASH_SIZE - len;
- }
-
- /* Set bottom/top bit based on start address */
- /* Do not set if len == 0 or len == CONFIG_SPI_FLASH_SIZE */
- if (!start && (len % CONFIG_SPI_FLASH_SIZE))
- tb = 1;
-
- /* Set sector bit and determine block length based on protect length */
- if (len == 0 || len >= 128 * 1024) {
- sec = 0;
- size = 64 * 1024;
- } else if (len >= 4 * 1024 && len <= 32 * 1024) {
- sec = 1;
- size = 2 * 1024;
- } else
- return EC_ERROR_INVAL;
-
- /* Determine number of blocks */
- if (len % size != 0)
- return EC_ERROR_INVAL;
- blocks = len / size;
-
- /* Determine bp = log2(blocks) with log2(0) = 0 */
- bp = blocks ? (31 - __builtin_clz(blocks)) : 0;
-
- /* Clear bits */
- *sr1 &= ~(SPI_FLASH_SR1_SEC | SPI_FLASH_SR1_TB |
- SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 | SPI_FLASH_SR1_BP0);
- *sr2 &= ~SPI_FLASH_SR2_CMP;
-
- /* Set bits */
- *sr1 |= (sec ? SPI_FLASH_SR1_SEC : 0) | (tb ? SPI_FLASH_SR1_TB : 0)
- | (bp << 2);
- *sr2 |= (cmp ? SPI_FLASH_SR2_CMP : 0);
-
- return EC_SUCCESS;
-}
-#elif defined(CONFIG_SPI_FLASH_W25X40) /* CONFIG_SPI_FLASH_W25Q64 */
-static int protect_to_reg(unsigned int start, unsigned int len,
- uint8_t *sr1, uint8_t *sr2)
-{
- char tb = 0;
- char bp = 0;
- int blocks;
- int size;
-
- /* Bad pointers */
- if (!sr1 || !sr2 || *sr1 == -1 || *sr2 == -1)
- return EC_ERROR_INVAL;
-
- /* Invalid data */
- if ((start && !len) || start + len > CONFIG_SPI_FLASH_SIZE)
- return EC_ERROR_INVAL;
-
- /* Set bottom/top bit based on start address */
- if (!start && (len % CONFIG_SPI_FLASH_SIZE))
- tb = 1;
-
- /* 64kb block protection granularity */
- size = 32 * 1024;
-
- /* Determine number of blocks */
- if (len % size != 0)
- return EC_ERROR_INVAL;
- blocks = len / size;
-
- /* Determine bp = log2(blocks) with log2(0) = 0 */
- bp = blocks ? (31 - __builtin_clz(blocks)) : 0;
-
- /* Clear bits */
- *sr1 &= ~(SPI_FLASH_SR1_TB | SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 |
- SPI_FLASH_SR1_BP0);
-
- /* Set bits */
- *sr1 |= (tb ? SPI_FLASH_SR1_TB : 0) | (bp << 2);
-
- return EC_SUCCESS;
-}
-#endif /* CONFIG_SPI_FLASH_W25X40 */
-
-/**
* Waits for chip to finish current operation. Must be called after
* erase/write operations to ensure successive commands are executed.
*
@@ -315,8 +84,8 @@ uint8_t spi_flash_get_status2(void)
uint8_t cmd = SPI_FLASH_READ_SR2;
uint8_t resp;
-#ifdef CONFIG_SPI_FLASH_W25X40
/* Second status register not present */
+#ifndef CONFIG_SPI_FLASH_HAS_SR2
return 0;
#endif
@@ -349,8 +118,8 @@ int spi_flash_set_status(int reg1, int reg2)
if (rv)
return rv;
-#ifdef CONFIG_SPI_FLASH_W25X40
/* Second status register not present */
+#ifndef CONFIG_SPI_FLASH_HAS_SR2
reg2 = -1;
#endif
@@ -621,7 +390,7 @@ int spi_flash_check_protect(unsigned int offset, unsigned int bytes)
return EC_ERROR_INVAL;
/* Compute current protect range */
- rv = reg_to_protect(sr1, sr2, &start, &len);
+ rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len);
if (rv)
return rv;
@@ -652,7 +421,7 @@ int spi_flash_set_protect(unsigned int offset, unsigned int bytes)
return EC_ERROR_INVAL;
/* Compute desired protect range */
- rv = protect_to_reg(offset, bytes, &sr1, &sr2);
+ rv = spi_flash_protect_to_reg(offset, bytes, &sr1, &sr2);
if (rv)
return rv;