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>
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index 1b00078..93335de 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -113,6 +113,34 @@
 	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 @@
 	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 @@
 	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);
 }