summaryrefslogtreecommitdiff
path: root/common/spi_flash.c
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 /common/spi_flash.c
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>
Diffstat (limited to 'common/spi_flash.c')
-rw-r--r--common/spi_flash.c45
1 files changed, 32 insertions, 13 deletions
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;
}
/**