summaryrefslogtreecommitdiff
path: root/src/drivers/spi
diff options
context:
space:
mode:
authorFelix Held <felix-coreboot@felixheld.de>2024-11-08 20:38:36 +0100
committerFelix Held <felix-coreboot@felixheld.de>2024-11-12 15:41:22 +0000
commit6ab9623f46548d9fcd2f3f7814ae11d6941829b4 (patch)
treef3a059e4612a7926270abf782c5789b419d2a1c3 /src/drivers/spi
parent95d8edadcb33cad63460db1176ab565d087f4930 (diff)
drivers/spi/spi_flash_sfdp: use spi_crop_chunk when reading SFDP data
The basic flash parameter table described in JESB216F can be up to 23 DWORDs (92 bytes) long which is larger than the 47 byte SPI data buffer in the AMD SoCs which also contains the data from the command buffer except the command byte. TEST=Calling 'read_sfdp_data' with a data length of 256 bytes which is larger than the buffer of the AMD SPI host controller now works and returns the SFDP data expected from the W74M12JW SPI flash: 0x00: 53 46 44 50 06 01 02 ff 00 06 01 10 80 00 00 ff SFDP............ 0x10: 84 00 01 02 d0 00 00 ff 03 00 01 02 f0 00 00 ff ................ 0x20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ ... 0x80: e5 20 f9 ff ff ff ff 07 44 eb 08 6b 08 3b 42 bb . ......D..k.;B. 0x90: fe ff ff ff ff ff 00 00 ff ff 40 eb 0c 20 0f 52 ..........@.. .R 0xa0: 10 d8 00 00 36 02 a6 00 82 ea 14 c9 e9 63 76 33 ....6........cv3 0xb0: 7a 75 7a 75 f7 bd d5 5c 19 f7 4d ff e9 30 f8 80 zuzu...\..M..0.. 0xc0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 0xd0: 00 00 f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 0xe0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 0xf0: 38 9b 96 f0 a5 ad a5 ff ff ff ff ff ff ff ff ff 8............... Change-Id: Ia602a54566c9e9cffaebc813ee493254d966e9e4 Signed-off-by: Felix Held <felix-coreboot@felixheld.de> Reviewed-on: https://review.coreboot.org/c/coreboot/+/85059 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Matt DeVillier <matt.devillier@amd.corp-partner.google.com>
Diffstat (limited to 'src/drivers/spi')
-rw-r--r--src/drivers/spi/spi_flash_sfdp.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/drivers/spi/spi_flash_sfdp.c b/src/drivers/spi/spi_flash_sfdp.c
index 46117bca38..94509fdf56 100644
--- a/src/drivers/spi/spi_flash_sfdp.c
+++ b/src/drivers/spi/spi_flash_sfdp.c
@@ -10,8 +10,6 @@
/*
* Assumptions (not) made in the code:
* - code is supposed to be endian-safe
- * - requested SFDP data blocks are small enough to fit into the SPI controller buffer, so no
- * spi_crop_chunk calls are needed
*
* Limitations:
* - only legacy access protocol supported:
@@ -24,20 +22,35 @@
#define CMD_READ_SFDP 0x5a
+static void read_sfdp_data_update_buffer_offset(uint8_t *buf_cmd, uint32_t offset)
+{
+ buf_cmd[1] = offset >> 16 & 0xff;
+ buf_cmd[2] = offset >> 8 & 0xff;
+ buf_cmd[3] = offset >> 0 & 0xff;
+}
+
static enum cb_err read_sfdp_data(const struct spi_flash *flash, uint32_t offset, size_t len,
uint8_t *buf)
{
uint8_t buf_cmd[5];
buf_cmd[0] = CMD_READ_SFDP;
- buf_cmd[1] = offset >> 16 & 0xff;
- buf_cmd[2] = offset >> 8 & 0xff;
- buf_cmd[3] = offset >> 0 & 0xff;
+ /* the read offset in buf_cmd[1..3] gets written in
+ read_sfdp_data_update_buffer_offset */
buf_cmd[4] = 0; /* dummy byte */
- /* TODO: use spi_crop_chunk to break up larger transfers */
- if (spi_flash_cmd_multi(&flash->spi, buf_cmd, sizeof(buf_cmd), buf, len))
- return CB_ERR;
+ uint8_t *data = buf;
+
+ /* split data transfers into chunks that each fit into the SPI controller's buffer */
+ while (len) {
+ uint32_t xfer_len = spi_crop_chunk(&flash->spi, sizeof(buf_cmd), len);
+ read_sfdp_data_update_buffer_offset(buf_cmd, offset);
+ if (spi_flash_cmd_multi(&flash->spi, buf_cmd, sizeof(buf_cmd), data, xfer_len))
+ return CB_ERR;
+ offset += xfer_len;
+ data += xfer_len;
+ len -= xfer_len;
+ }
return CB_SUCCESS;
}