diff options
author | Aaron Durbin <adurbin@chromium.org> | 2018-01-25 17:30:45 -0700 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2018-01-26 23:37:39 +0000 |
commit | 3a649eec28b9440a628626a7b882a9fb185a9a4a (patch) | |
tree | 9e0e774a2c4abb994186e7f39bdf8e0d09197dae /src | |
parent | e98722856e37c31152f1561891a1428a7bdbb557 (diff) | |
download | coreboot-3a649eec28b9440a628626a7b882a9fb185a9a4a.tar.xz |
drivers/spi/spi_flash: honor spi controller fifo size for reads
The spi_flash_cmd_read_fast() and spi_flash_cmd_read_slow() were just
passing full size buffers to the spi controller ops. However, the
code wasn't honoring what the spi controller can actually perform.
This would cause failures to read on controllers when large requests
were sent in. Fix this by introducing a
spi_flash_cmd_read_array_wrapped() function that calls
spi_flash_cmd_read_array() in a loop once the maximum transfer size is
calculated based on the spi controller's settings.
BUG=b:65485690
Change-Id: I442d6e77a93fda411cb289b606189e490a4e464e
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/23444
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Justin TerAvest <teravest@chromium.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/drivers/spi/spi_flash.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index 1b00078d5d..93335de24a 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -113,6 +113,34 @@ static int spi_flash_cmd_read_array(const struct spi_slave *spi, u8 *cmd, return spi_flash_cmd_read(spi, cmd, cmd_len, data, len); } +/* Perform the read operation honoring spi controller fifo size, reissuing + * the read command until the full request completed. */ +static int spi_flash_cmd_read_array_wrapped(const struct spi_slave *spi, + u8 *cmd, size_t cmd_len, u32 offset, + size_t len, void *buf) +{ + int ret; + size_t xfer_len; + uint8_t *data = buf; + + while (len) { + xfer_len = spi_crop_chunk(spi, cmd_len, len); + + /* Perform the read. */ + ret = spi_flash_cmd_read_array(spi, cmd, cmd_len, + offset, xfer_len, data); + + if (ret) + return ret; + + offset += xfer_len; + data += xfer_len; + len -= xfer_len; + } + + return 0; +} + int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset, size_t len, void *data) { @@ -121,7 +149,7 @@ int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset, cmd[0] = CMD_READ_ARRAY_FAST; cmd[4] = 0x00; - return spi_flash_cmd_read_array(&flash->spi, cmd, sizeof(cmd), + return spi_flash_cmd_read_array_wrapped(&flash->spi, cmd, sizeof(cmd), offset, len, data); } @@ -131,7 +159,7 @@ int spi_flash_cmd_read_slow(const struct spi_flash *flash, u32 offset, u8 cmd[4]; cmd[0] = CMD_READ_ARRAY_SLOW; - return spi_flash_cmd_read_array(&flash->spi, cmd, sizeof(cmd), + return spi_flash_cmd_read_array_wrapped(&flash->spi, cmd, sizeof(cmd), offset, len, data); } |