[coreboot-gerrit] New patch to review for coreboot: ccdea55 spi: support controllers with limited transfer size capabilities

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Fri Apr 10 22:34:17 CEST 2015


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9571

-gerrit

commit ccdea55a50f02bc3a9b90af3db2936430a4e4c4d
Author: Vadim Bendebury <vbendeb at chromium.org>
Date:   Sat Nov 29 15:06:26 2014 -0800

    spi: support controllers with limited transfer size capabilities
    
    Some SPI controllers (like Imgtec Pistachio), have a hard limit on SPI
    read and write transactions. Limiting transfer size in the wrapper
    allows to provide the API user with unlimited transfer size
    transactions.
    
    The tranfer size limitation is added to the spi_slave structure, which
    is set up by the controller driver. The value of zero in this field
    means 'unlimited transfer size'. It will work with existion drivers,
    as they all either keep structures in the bss segment, or initialize
    them to all zeros.
    
    This patch addresses the problem for reads only, as coreboot is not
    expected to require to write long chunks into SPI devices.
    
    BRANCH=none
    BUG=chrome-os-partner:32441, chrome-os-partner:31438
    TEST=set transfer size limit to artificially low value (4K) and
         observed proper operation on both Pistachio and ipq8086: both
         Storm and Urara booted through romstage and ramstage.
    
    Change-Id: Ibb96aa499c3eec458c94bf1193fbbbf5f54e1477
    Signed-off-by: Stefan Reinauer <reinauer at chromium.org>
    Original-Commit-Id: 4f064fdca5b6c214e7a7f2751dc24e33cac2ea45
    Original-Change-Id: I9df24f302edc872bed991ea450c0af33a1c0ff7b
    Original-Signed-off-by: Vadim Bendebury <vbendeb at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/232239
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
    Original-Reviewed-by: David Hendricks <dhendrix at chromium.org>
---
 src/drivers/spi/spi_flash.c          | 44 ++++++++++++++++++++++--------------
 src/drivers/spi/spi_flash_internal.h | 14 ------------
 src/include/spi-generic.h            |  5 ++++
 src/soc/imgtec/pistachio/spi.c       |  5 ++++
 4 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index d737ee9..607fb21 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -79,8 +79,8 @@ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
 	return ret;
 }
 
-int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len)
+static int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
+			      size_t cmd_len, void *data, size_t data_len)
 {
 	int ret = do_spi_flash_cmd(spi, cmd, cmd_len, data, data_len);
 	if (ret) {
@@ -108,41 +108,51 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
 	return ret;
 }
 
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len)
+static int spi_flash_cmd_read_array(struct spi_slave *spi, u8 *cmd,
+				    size_t cmd_len, u32 offset,
+				    size_t len, void *data)
 {
-	struct spi_slave *spi = flash->spi;
-	int ret;
+	while (len) {
+		size_t transfer_size;
 
-	spi->rw = SPI_READ_FLAG;
-	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
+		if (spi->max_transfer_size)
+			transfer_size = min(len, spi->max_transfer_size);
+		else
+			transfer_size = len;
 
-	return ret;
+		spi_flash_addr(offset, cmd);
+
+		if (spi_flash_cmd_read(spi, cmd, cmd_len, data, transfer_size))
+			break;
+
+		offset += transfer_size;
+		data = (void *)((uintptr_t)data + transfer_size);
+		len -= transfer_size;
+	}
+
+	return len != 0;
 }
 
 int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 		size_t len, void *data)
 {
-	struct spi_slave *spi = flash->spi;
 	u8 cmd[5];
 
 	cmd[0] = CMD_READ_ARRAY_FAST;
-	spi_flash_addr(offset, cmd);
 	cmd[4] = 0x00;
 
-	return spi_flash_cmd_read(spi, cmd, sizeof(cmd), data, len);
+	return spi_flash_cmd_read_array(flash->spi, cmd, sizeof(cmd),
+					offset, len, data);
 }
 
 int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset,
-		size_t len, void *data)
+			    size_t len, void *data)
 {
-	struct spi_slave *spi = flash->spi;
 	u8 cmd[4];
 
 	cmd[0] = CMD_READ_ARRAY_SLOW;
-	spi_flash_addr(offset, cmd);
-
-	return spi_flash_cmd_read(spi, cmd, sizeof(cmd), data, len);
+	return spi_flash_cmd_read_array(flash->spi, cmd, sizeof(cmd),
+					offset, len, data);
 }
 
 int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h
index 6f18484..4798b10 100644
--- a/src/drivers/spi/spi_flash_internal.h
+++ b/src/drivers/spi/spi_flash_internal.h
@@ -32,13 +32,6 @@
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
 
-/*
- * Send a multi-byte command to the device and read the response. Used
- * for flash array reads, etc.
- */
-int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len);
-
 int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 		size_t len, void *data);
 
@@ -52,13 +45,6 @@ int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset,
 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
 		const void *data, size_t data_len);
 
-/*
- * Same as spi_flash_cmd_read() except it also claims/releases the SPI
- * bus. Used as common part of the ->read() operation.
- */
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len);
-
 /* Send a command to the device and wait for some bit to clear itself. */
 int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
 			   u8 cmd, u8 poll_bit);
diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h
index bd0020f..4de138c 100644
--- a/src/include/spi-generic.h
+++ b/src/include/spi-generic.h
@@ -43,11 +43,16 @@
  *   bus:	ID of the bus that the slave is attached to.
  *   cs:	ID of the chip select connected to the slave.
  *   rw: 	Read or Write flag
+ *   max_transfer_size: maximum amount of bytes which can be sent in a single
+ *              read or write transaction, usually this is a controller
+ *              property, kept in the slave structure for convenience. Zero in
+ *              this field means 'unlimited'.
  */
 struct spi_slave {
 	unsigned int	bus;
 	unsigned int	cs;
 	unsigned int	rw;
+	unsigned int	max_transfer_size;
 	int force_programmer_specific;
 	struct spi_flash * (*programmer_specific_probe) (struct spi_slave *spi);
 };
diff --git a/src/soc/imgtec/pistachio/spi.c b/src/soc/imgtec/pistachio/spi.c
index 69682d0..5522f24 100644
--- a/src/soc/imgtec/pistachio/spi.c
+++ b/src/soc/imgtec/pistachio/spi.c
@@ -25,6 +25,9 @@
 #error "Unsupported SPI driver API"
 #endif
 
+/* Imgtec controller uses 16 bit packet length. */
+#define IMGTEC_SPI_MAX_TRANSFER_SIZE   ((1 << 16) - 1)
+
 struct img_spi_slave {
 	struct spi_slave slave;
 	/* SPIM instance device parameters */
@@ -441,6 +444,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
 	slave->bus = bus;
 	slave->cs = cs;
 	slave->rw = SPI_READ_FLAG | SPI_WRITE_FLAG;
+	slave->max_transfer_size = IMGTEC_SPI_MAX_TRANSFER_SIZE;
+
 	device_parameters->bitrate = 64;
 	device_parameters->cs_setup = 0;
 	device_parameters->cs_hold = 0;



More information about the coreboot-gerrit mailing list