diff options
author | Shamile Khan <shamile.khan@intel.com> | 2015-06-05 17:01:14 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-06-12 16:37:47 +0000 |
commit | a0bec46ef3f7804ad4ae59d5a89b89da636a54a3 (patch) | |
tree | 8db4bb611efb0d4589f2c752554c1e3d783a3a8c /common | |
parent | 5b7cfac64e971a7e925d17a8b33e651a01e71707 (diff) | |
download | chrome-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')
-rw-r--r-- | common/spi_flash.c | 45 |
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; } /** |