summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2016-09-15 18:47:02 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-16 21:59:11 -0700
commit7cb5f24596af261a46f0fab9f3f6106cb8d33b99 (patch)
treec93e6964d1e6564d41247f1033b19abf3dbd51d0
parentdef0a47cee00d403e5fed89c08da2c3d715df610 (diff)
downloadchrome-ec-7cb5f24596af261a46f0fab9f3f6106cb8d33b99.tar.gz
npcx: flash: Lock mutex during flash operations
Lock mutex during mapped flash read and when issuing flash commands to ensure no conflict between tasks. BUG=chrome-os-partner:55781 BRANCH=Gru TEST=Stress test flashrom, verify no verify failure occurs for 100 flashes. Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Change-Id: I6036754dd4d84c45cd689ce5033d68c655431b14 Reviewed-on: https://chromium-review.googlesource.com/386419 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> (cherry picked from commit 9123cc86c9fb15d8b9fbdcd4a93a785b37381fbe) Reviewed-on: https://chromium-review.googlesource.com/386448 Commit-Ready: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--chip/npcx/flash.c161
1 files changed, 59 insertions, 102 deletions
diff --git a/chip/npcx/flash.c b/chip/npcx/flash.c
index ac1a06078d..2387a3a958 100644
--- a/chip/npcx/flash.c
+++ b/chip/npcx/flash.c
@@ -28,9 +28,13 @@ uint8_t flag_prot_inconsistent;
#else
#define TRISTATE_FLASH(x) flash_tristate(x)
#endif
+
+/* Ensure only one task is accessing flash at a time. */
+static struct mutex flash_lock;
+
/*****************************************************************************/
/* flash internal functions */
-void flash_pinmux(int enable)
+static void flash_pinmux(int enable)
{
/* Select pin-mux for FIU*/
UPDATE_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI, !enable);
@@ -48,13 +52,13 @@ void flash_pinmux(int enable)
}
}
-void flash_tristate(int enable)
+static void flash_tristate(int enable)
{
/* Enable/Disable FIU pins to tri-state */
UPDATE_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS, enable);
}
-void flash_execute_cmd(uint8_t code, uint8_t cts)
+static void flash_execute_cmd(uint8_t code, uint8_t cts)
{
/* set UMA_CODE */
NPCX_UMA_CODE = code;
@@ -64,7 +68,7 @@ void flash_execute_cmd(uint8_t code, uint8_t cts)
;
}
-void flash_cs_level(int level)
+static void flash_cs_level(int level)
{
/* Set chip select to high/low level */
UPDATE_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1, level);
@@ -102,7 +106,7 @@ static int flash_wait_ready(int timeout)
return EC_SUCCESS;
}
-int flash_write_enable(void)
+static int flash_write_enable(void)
{
uint8_t mask = SPI_FLASH_SR1_WEL;
int rv;
@@ -125,7 +129,7 @@ int flash_write_enable(void)
return EC_ERROR_BUSY;
}
-void flash_set_address(uint32_t dest_addr)
+static void flash_set_address(uint32_t dest_addr)
{
uint8_t *addr = (uint8_t *)&dest_addr;
/* Write address */
@@ -309,8 +313,11 @@ static int protect_to_reg(unsigned int start, unsigned int len,
return EC_SUCCESS;
}
-int flash_set_status_for_prot(int reg1, int reg2)
+static int flash_set_status_for_prot(int reg1, int reg2)
{
+ /* Lock physical flash operations */
+ flash_lock_mapped_storage(1);
+
/* Disable tri-state */
TRISTATE_FLASH(0);
/* Enable write */
@@ -324,12 +331,15 @@ int flash_set_status_for_prot(int reg1, int reg2)
/* Enable tri-state */
TRISTATE_FLASH(1);
+ /* Unlock physical flash operations */
+ flash_lock_mapped_storage(0);
+
reg_to_protect(reg1, reg2, &addr_prot_start, &addr_prot_length);
return EC_SUCCESS;
}
-int flash_check_prot_range(unsigned int offset, unsigned int bytes)
+static int flash_check_prot_range(unsigned int offset, unsigned int bytes)
{
/* Invalid value */
if (offset + bytes > CONFIG_FLASH_SIZE)
@@ -342,7 +352,7 @@ int flash_check_prot_range(unsigned int offset, unsigned int bytes)
return EC_SUCCESS;
}
-int flash_check_prot_reg(unsigned int offset, unsigned int bytes)
+static int flash_check_prot_reg(unsigned int offset, unsigned int bytes)
{
unsigned int start;
unsigned int len;
@@ -369,7 +379,7 @@ int flash_check_prot_reg(unsigned int offset, unsigned int bytes)
}
-int flash_write_prot_reg(unsigned int offset, unsigned int bytes)
+static int flash_write_prot_reg(unsigned int offset, unsigned int bytes)
{
int rv;
uint8_t sr1 = flash_get_status1();
@@ -387,7 +397,7 @@ int flash_write_prot_reg(unsigned int offset, unsigned int bytes)
return flash_set_status_for_prot(sr1, sr2);
}
-void flash_burst_write(unsigned int dest_addr, unsigned int bytes,
+static void flash_burst_write(unsigned int dest_addr, unsigned int bytes,
const char *data)
{
unsigned int i;
@@ -437,13 +447,13 @@ static int flash_program_bytes(uint32_t offset, uint32_t bytes,
return rv;
}
-int flash_uma_lock(int enable)
+static int flash_uma_lock(int enable)
{
UPDATE_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK, enable);
return EC_SUCCESS;
}
-int flash_spi_sel_lock(int enable)
+static int flash_spi_sel_lock(int enable)
{
/*
* F_SPI_QUAD, F_SPI_CS1_1/2, F_SPI_TRIS become read-only
@@ -454,13 +464,15 @@ int flash_spi_sel_lock(int enable)
}
/*****************************************************************************/
-/* Physical layer APIs */
int flash_physical_read(int offset, int size, char *data)
{
int dest_addr = offset;
uint32_t idx;
+ /* Lock physical flash operations */
+ flash_lock_mapped_storage(1);
+
/* Disable tri-state */
TRISTATE_FLASH(0);
/* Chip Select down. */
@@ -486,80 +498,11 @@ int flash_physical_read(int offset, int size, char *data)
flash_cs_level(1);
/* Enable tri-state */
TRISTATE_FLASH(1);
- return EC_SUCCESS;
-}
-
-int flash_physical_read_image_size(int offset, int size)
-{
- int dest_addr = offset;
- uint8_t temp;
- uint32_t idx;
- uint32_t image_size = 0;
-
- /* Disable tri-state */
- TRISTATE_FLASH(0);
- /* Chip Select down. */
- flash_cs_level(0);
-
- /* Set read address */
- flash_set_address(dest_addr);
- /* Start fast read - 1110 1001 - EXEC, WR, CMD, ADDR */
- flash_execute_cmd(CMD_FAST_READ, MASK_CMD_ADR_WR);
-
- /* Burst read transaction */
- for (idx = 0; idx < size; idx++) {
- /* 1101 0101 - EXEC, RD, NO CMD, NO ADDR, 4 bytes */
- NPCX_UMA_CTS = MASK_RD_1BYTE;
- /* wait for UMA to complete */
- while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE))
- ;
- /* Find eof of image */
- temp = NPCX_UMA_DB0;
- if (temp == 0xea)
- image_size = idx;
- }
-
- /* Chip Select up */
- flash_cs_level(1);
- /* Enable tri-state */
- TRISTATE_FLASH(1);
- return image_size;
-}
-int flash_physical_is_erased(uint32_t offset, int size)
-{
- int dest_addr = offset;
- uint32_t idx;
- uint8_t temp;
+ /* Unlock physical flash operations */
+ flash_lock_mapped_storage(0);
- /* Chip Select down. */
- flash_cs_level(0);
-
- /* Set read address */
- flash_set_address(dest_addr);
- /* Start fast read -1110 1001 - EXEC, WR, CMD, ADDR */
- flash_execute_cmd(CMD_FAST_READ, MASK_CMD_ADR_WR);
-
- /* Burst read transaction */
- for (idx = 0; idx < size; idx++) {
- /* 1101 0101 - EXEC, RD, NO CMD, NO ADDR, 4 bytes */
- NPCX_UMA_CTS = MASK_RD_1BYTE;
- /* Wait for UMA to complete */
- while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE))
- ;
- /* Get read transaction results */
- temp = NPCX_UMA_DB0;
- if (temp != 0xFF)
- break;
- }
-
- /* Chip Select up */
- flash_cs_level(1);
-
- if (idx == size)
- return 1;
- else
- return 0;
+ return EC_SUCCESS;
}
int flash_physical_write(int offset, int size, const char *data)
@@ -577,6 +520,9 @@ int flash_physical_write(int offset, int size, const char *data)
if (all_protected)
return EC_ERROR_ACCESS_DENIED;
+ /* Lock physical flash operations */
+ flash_lock_mapped_storage(1);
+
/* Disable tri-state */
TRISTATE_FLASH(0);
@@ -586,12 +532,14 @@ int flash_physical_write(int offset, int size, const char *data)
size : CONFIG_FLASH_WRITE_IDEAL_SIZE;
/* check protection */
- if (flash_check_prot_range(dest_addr, write_len))
- return EC_ERROR_ACCESS_DENIED;
+ if (flash_check_prot_range(dest_addr, write_len)) {
+ rv = EC_ERROR_ACCESS_DENIED;
+ break;
+ }
rv = flash_program_bytes(dest_addr, write_len, data);
if (rv)
- return rv;
+ break;
data += write_len;
dest_addr += write_len;
@@ -600,6 +548,10 @@ int flash_physical_write(int offset, int size, const char *data)
/* Enable tri-state */
TRISTATE_FLASH(1);
+
+ /* Unlock physical flash operations */
+ flash_lock_mapped_storage(0);
+
return rv;
}
@@ -610,20 +562,20 @@ int flash_physical_erase(int offset, int size)
if (all_protected)
return EC_ERROR_ACCESS_DENIED;
+ /* Lock physical flash operations */
+ flash_lock_mapped_storage(1);
+
/* Disable tri-state */
TRISTATE_FLASH(0);
/* Alignment has been checked in upper layer */
for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
offset += CONFIG_FLASH_ERASE_SIZE) {
-
- /* Do nothing if already erased */
- if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
- continue;
-
/* check protection */
- if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE))
- return EC_ERROR_ACCESS_DENIED;
+ if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE)) {
+ rv = EC_ERROR_ACCESS_DENIED;
+ break;
+ }
/*
* Reload the watchdog timer, so that erasing many flash pages
@@ -635,7 +587,7 @@ int flash_physical_erase(int offset, int size)
/* Enable write */
rv = flash_write_enable();
if (rv)
- return rv;
+ break;
/* Set erase address */
flash_set_address(offset);
@@ -645,11 +597,15 @@ int flash_physical_erase(int offset, int size)
/* Wait erase completed */
rv = flash_wait_ready(FLASH_ABORT_TIMEOUT);
if (rv)
- return rv;
+ break;
}
/* Enable tri-state */
TRISTATE_FLASH(1);
+
+ /* Unlock physical flash operations */
+ flash_lock_mapped_storage(0);
+
return rv;
}
@@ -779,11 +735,12 @@ int flash_pre_init(void)
void flash_lock_mapped_storage(int lock)
{
- /*
- * TODO(crosbug.com/p/55781): Add mutex to ensure no conflict between
- * mapped read and regular flash ops.
- */
+ if (lock)
+ mutex_lock(&flash_lock);
+ else
+ mutex_unlock(&flash_lock);
}
+
/*****************************************************************************/
/* Console commands */