From 0530b299212b4d584571ab588ad1d750ae57e251 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Mon, 14 Nov 2016 13:49:56 -0800 Subject: intel/apollolake: Ensure SPI operations do not cross 256-byte boundary BIOS needs to ensure that SPI write does not cross 256-byte boundary. Else, if the write is across 256-byte boundary, then it corrupts the block by wrapping write to start of current block. Thus, ensure nuclear_spi_{read,write} operate within a single 256-byte block only at a time. BUG=chrome-os-partner:59813 BRANCH=None TEST=Verified that elog writes do not corrupt the event log when write is across 256-byte blocks. Change-Id: I854ca2979d65b9f1232f93182cb84d4dee4f4139 Signed-off-by: Furquan Shaikh Reviewed-on: https://review.coreboot.org/17419 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/intel/apollolake/spi.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/soc/intel/apollolake/spi.c b/src/soc/intel/apollolake/spi.c index 8cb8aa5d6d..d60176a9aa 100644 --- a/src/soc/intel/apollolake/spi.c +++ b/src/soc/intel/apollolake/spi.c @@ -259,6 +259,21 @@ static int nuclear_spi_erase(struct spi_flash *flash, uint32_t offset, size_t le return SUCCESS; } +/* + * Ensure read/write xfer len is not greater than SPIBAR_FDATA_FIFO_SIZE and + * that the operation does not cross 256-byte boundary. + */ +static size_t get_xfer_len(uint32_t addr, size_t len) +{ + size_t xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE); + size_t bytes_left = ALIGN_UP(addr, 256) - addr; + + if (bytes_left) + xfer_len = min(xfer_len, bytes_left); + + return xfer_len; +} + static int nuclear_spi_read(struct spi_flash *flash, uint32_t addr, size_t len, void *buf) { int ret; @@ -268,7 +283,7 @@ static int nuclear_spi_read(struct spi_flash *flash, uint32_t addr, size_t len, BOILERPLATE_CREATE_CTX(ctx); while (len) { - xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE); + xfer_len = get_xfer_len(addr, len); ret = exec_sync_hwseq_xfer(ctx, SPIBAR_HSFSTS_CYCLE_READ, addr, xfer_len); @@ -295,7 +310,7 @@ static int nuclear_spi_write(struct spi_flash *flash, BOILERPLATE_CREATE_CTX(ctx); while (len) { - xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE); + xfer_len = get_xfer_len(addr, len); fill_xfer_fifo(ctx, data, xfer_len); ret = exec_sync_hwseq_xfer(ctx, SPIBAR_HSFSTS_CYCLE_WRITE, -- cgit v1.2.3