summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShamile Khan <shamile.khan@intel.com>2015-06-05 17:01:14 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-12 16:37:47 +0000
commita0bec46ef3f7804ad4ae59d5a89b89da636a54a3 (patch)
tree8db4bb611efb0d4589f2c752554c1e3d783a3a8c
parent5b7cfac64e971a7e925d17a8b33e651a01e71707 (diff)
downloadchrome-ec-a0bec46ef3f7804ad4ae59d5a89b89da636a54a3.tar.gz
spi/mec1322: Ensure that SPI Flash write chunks do not cross
Page Boundary. If SPI Flash write is at an offset within the page and the length is greater than remainder of the page, the Flash page gets corrupted as addressing wraps to the beginning of page and previously written data gets overwritten. This change splits SPI Flash writes in such cases into two operations in different pages. BUG=None BRANCH=None TEST=During Software Sync, Depthcharge sends Flash write chunks that cross page boundary. With this change, the RW parition does not get corrupted. This can be confirmed by executing a successful "sysjump RW" after a Software Sync. Change-Id: I46349eea0d8e927353de7cb55a61e9960291adb6 Signed-off-by: Shamile Khan <shamile.khan@intel.com> Reviewed-on: https://chromium-review.googlesource.com/275760 Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--chip/mec1322/flash.c2
-rw-r--r--common/spi_flash.c45
2 files changed, 32 insertions, 15 deletions
diff --git a/chip/mec1322/flash.c b/chip/mec1322/flash.c
index 9681511f5a..e4ee512172 100644
--- a/chip/mec1322/flash.c
+++ b/chip/mec1322/flash.c
@@ -62,8 +62,6 @@ int flash_physical_write(int offset, int size, const char *data)
(uint8_t *)data + i);
if (ret != EC_SUCCESS)
break;
- /* BUG: Multi-page writes fail if no delay */
- msleep(1);
}
spi_enable(0);
return ret;
diff --git a/common/spi_flash.c b/common/spi_flash.c
index 23ac520059..126e38d7f7 100644
--- a/common/spi_flash.c
+++ b/common/spi_flash.c
@@ -257,28 +257,47 @@ int spi_flash_erase(unsigned int offset, unsigned int bytes)
int spi_flash_write(unsigned int offset, unsigned int bytes,
const uint8_t const *data)
{
- int rv;
+ int rv, write_size;
/* Invalid input */
if (!data || offset + bytes > CONFIG_SPI_FLASH_SIZE ||
bytes > SPI_FLASH_MAX_WRITE_SIZE)
return EC_ERROR_INVAL;
- /* Enable writing to SPI flash */
- rv = spi_flash_write_enable();
- if (rv)
- return rv;
+ while (bytes > 0) {
+ /* Write length can not go beyond the end of the flash page */
+ write_size = MIN(bytes, SPI_FLASH_MAX_WRITE_SIZE -
+ (offset & (SPI_FLASH_MAX_WRITE_SIZE - 1)));
- /* Copy data to send buffer; buffers may overlap */
- memmove(buf + 4, data, bytes);
+ /* Wait for previous operation to complete */
+ rv = spi_flash_wait();
+ if (rv)
+ return rv;
- /* Compose instruction */
- buf[0] = SPI_FLASH_PAGE_PRGRM;
- buf[1] = (offset >> 16) & 0xFF;
- buf[2] = (offset >> 8) & 0xFF;
- buf[3] = offset & 0xFF;
+ /* Enable writing to SPI flash */
+ rv = spi_flash_write_enable();
+ if (rv)
+ return rv;
+
+ /* Copy data to send buffer; buffers may overlap */
+ memmove(buf + 4, data, write_size);
+
+ /* Compose instruction */
+ buf[0] = SPI_FLASH_PAGE_PRGRM;
+ buf[1] = (offset) >> 16;
+ buf[2] = (offset) >> 8;
+ buf[3] = offset;
+
+ rv = spi_transaction(buf, 4 + write_size, NULL, 0);
+ if (rv)
+ return rv;
- return spi_transaction(buf, 4 + bytes, NULL, 0);
+ data += write_size;
+ offset += write_size;
+ bytes -= write_size;
+ }
+
+ return rv;
}
/**