aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/spi
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2018-01-25 17:30:45 -0700
committerAaron Durbin <adurbin@chromium.org>2018-01-26 23:37:39 +0000
commit3a649eec28b9440a628626a7b882a9fb185a9a4a (patch)
tree9e0e774a2c4abb994186e7f39bdf8e0d09197dae /src/drivers/spi
parente98722856e37c31152f1561891a1428a7bdbb557 (diff)
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/drivers/spi')
-rw-r--r--src/drivers/spi/spi_flash.c32
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);
}