diff mbox series

[U-Boot,4/4] spi: sh_qspi: Make use of the 32byte FIFO

Message ID 20180410151540.12103-4-marek.vasut+renesas@gmail.com
State Accepted
Commit ea5512eb095067dda27930246792d2957feb9434
Delegated to: Marek Vasut
Headers show
Series [U-Boot,1/4] spi: sh_qspi: Replace data types with short ones | expand

Commit Message

Marek Vasut April 10, 2018, 3:15 p.m. UTC
The QSPI controller on RCar Gen2 has 32byte FIFO. Instead of doing
the SPI transmission 1 byte at time, if there is a 32byte chunk of
data to be transferred, fill the FIFO completely and then transfer
the data to/from the FIFO. This increases the SPI NOR access speed
significantly.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
---
 drivers/spi/sh_qspi.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
index d7f558a541..5075be3cd1 100644
--- a/drivers/spi/sh_qspi.c
+++ b/drivers/spi/sh_qspi.c
@@ -36,6 +36,8 @@ 
 			SPCMD_BRDV0
 #define SPBFCR_TXRST	BIT(7)
 #define SPBFCR_RXRST	BIT(6)
+#define SPBFCR_TXTRG	0x30
+#define SPBFCR_RXTRG	0x07
 
 /* SH QSPI register set */
 struct sh_qspi_regs {
@@ -201,8 +203,8 @@  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 	     void *din, unsigned long flags)
 {
 	struct sh_qspi_slave *ss = to_sh_qspi(slave);
-	u32 nbyte;
-	int ret = 0;
+	u32 nbyte, chunk;
+	int i, ret = 0;
 	u8 dtdata = 0, drdata;
 	u8 *tdata = &dtdata, *rdata = &drdata;
 	u32 *spbmul0 = &ss->regs->spbmul0;
@@ -237,26 +239,38 @@  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 		rdata = din;
 
 	while (nbyte > 0) {
+		/*
+		 * Check if there is 32 Byte chunk and if there is, transfer
+		 * it in one burst, otherwise transfer on byte-by-byte basis.
+		 */
+		chunk = (nbyte >= 32) ? 32 : 1;
+
+		clrsetbits_8(&ss->regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG,
+			     chunk == 32 ? SPBFCR_TXTRG | SPBFCR_RXTRG : 0);
+
 		ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF,
 				     true, 1000, true);
 		if (ret)
 			return ret;
 
-		writeb(*tdata, (u8 *)(&ss->regs->spdr));
+		for (i = 0; i < chunk; i++) {
+			writeb(*tdata, &ss->regs->spdr);
+			if (dout != NULL)
+				tdata++;
+		}
 
 		ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
 				     true, 1000, true);
 		if (ret)
 			return ret;
 
-		*rdata = readb((u8 *)(&ss->regs->spdr));
-
-		if (dout != NULL)
-			tdata++;
-		if (din != NULL)
-			rdata++;
+		for (i = 0; i < chunk; i++) {
+			*rdata = readb(&ss->regs->spdr);
+			if (din != NULL)
+				rdata++;
+		}
 
-		nbyte--;
+		nbyte -= chunk;
 	}
 
 	if (flags & SPI_XFER_END)