summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/spi/spi_flash.c44
-rw-r--r--src/drivers/spi/spi_flash_internal.h14
-rw-r--r--src/include/spi-generic.h5
-rw-r--r--src/soc/imgtec/pistachio/spi.c5
4 files changed, 37 insertions, 31 deletions
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index d737ee9e618f..607fb214a80f 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 6f184848b680..4798b109257a 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 bd0020f5d2f0..4de138cf0988 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 69682d045660..5522f2408eec 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;