diff mbox series

[RFC,02/15] sunxi: SPL SPI: extract code for doing SPI transfer

Message ID 20240411-spinand-v1-2-62d31bb188e8@jookia.org
State RFC
Delegated to: Andre Przywara
Headers show
Series Support SPI NAND booting on the T113 | expand

Commit Message

John Watts April 11, 2024, 4:25 a.m. UTC
From: Icenowy Zheng <uwu@icenowy.me>

To support SPI NAND flashes, more commands than Read (03h) are needed.

Extract the code for doing SPI transfer from the reading code for code
reuse.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
Reviewed-by: Samuel Holland <samuel@sholland.org>
Tested-by: Samuel Holland <samuel@sholland.org> # Orange Pi Zero Plus
---
 arch/arm/mach-sunxi/spl_spi_sunxi.c | 105 ++++++++++++++++++++----------------
 1 file changed, 59 insertions(+), 46 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 7acb44f52a..e85ae96485 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -282,77 +282,90 @@  static void spi0_deinit(void)
 
 #define SPI_READ_MAX_SIZE 60 /* FIFO size, minus 4 bytes of the header */
 
-static void sunxi_spi0_read_data(u8 *buf, u32 addr, u32 bufsize,
-				 ulong spi_ctl_reg,
-				 ulong spi_ctl_xch_bitmask,
-				 ulong spi_fifo_reg,
-				 ulong spi_tx_reg,
-				 ulong spi_rx_reg,
-				 ulong spi_bc_reg,
-				 ulong spi_tc_reg,
-				 ulong spi_bcc_reg)
+static void sunxi_spi0_xfer(const u8 *txbuf, u32 txlen,
+			    u8 *rxbuf, u32 rxlen,
+			    ulong spi_ctl_reg,
+			    ulong spi_ctl_xch_bitmask,
+			    ulong spi_fifo_reg,
+			    ulong spi_tx_reg,
+			    ulong spi_rx_reg,
+			    ulong spi_bc_reg,
+			    ulong spi_tc_reg,
+			    ulong spi_bcc_reg)
 {
-	writel(4 + bufsize, spi_bc_reg); /* Burst counter (total bytes) */
-	writel(4, spi_tc_reg);           /* Transfer counter (bytes to send) */
+	writel(txlen + rxlen, spi_bc_reg); /* Burst counter (total bytes) */
+	writel(txlen, spi_tc_reg);         /* Transfer counter (bytes to send) */
 	if (spi_bcc_reg)
-		writel(4, spi_bcc_reg);  /* SUN6I also needs this */
+		writel(txlen, spi_bcc_reg);  /* SUN6I also needs this */
 
-	/* Send the Read Data Bytes (03h) command header */
-	writeb(0x03, spi_tx_reg);
-	writeb((u8)(addr >> 16), spi_tx_reg);
-	writeb((u8)(addr >> 8), spi_tx_reg);
-	writeb((u8)(addr), spi_tx_reg);
+	for (u32 i = 0; i < txlen; i++)
+		writeb(*(txbuf++), spi_tx_reg);
 
 	/* Start the data transfer */
 	setbits_le32(spi_ctl_reg, spi_ctl_xch_bitmask);
 
 	/* Wait until everything is received in the RX FIFO */
-	while ((readl(spi_fifo_reg) & 0x7F) < 4 + bufsize)
+	while ((readl(spi_fifo_reg) & 0x7F) < txlen + rxlen)
 		;
 
-	/* Skip 4 bytes */
-	readl(spi_rx_reg);
+	/* Skip txlen bytes */
+	for (u32 i = 0; i < txlen; i++)
+		readb(spi_rx_reg);
 
 	/* Read the data */
-	while (bufsize-- > 0)
-		*buf++ = readb(spi_rx_reg);
+	while (rxlen-- > 0)
+		*rxbuf++ = readb(spi_rx_reg);
+}
+
+static void spi0_xfer(const u8 *txbuf, u32 txlen, u8 *rxbuf, u32 rxlen)
+{
+	uintptr_t base = spi0_base_address();
 
-	/* tSHSL time is up to 100 ns in various SPI flash datasheets */
-	udelay(1);
+	if (is_sun6i_gen_spi()) {
+		sunxi_spi0_xfer(txbuf, txlen, rxbuf, rxlen,
+				base + SUN6I_SPI0_TCR,
+				SUN6I_TCR_XCH,
+				base + SUN6I_SPI0_FIFO_STA,
+				base + SUN6I_SPI0_TXD,
+				base + SUN6I_SPI0_RXD,
+				base + SUN6I_SPI0_MBC,
+				base + SUN6I_SPI0_MTC,
+				base + SUN6I_SPI0_BCC);
+	} else {
+		sunxi_spi0_xfer(txbuf, txlen, rxbuf, rxlen,
+				base + SUN4I_SPI0_CTL,
+				SUN4I_CTL_XCH,
+				base + SUN4I_SPI0_FIFO_STA,
+				base + SUN4I_SPI0_TX,
+				base + SUN4I_SPI0_RX,
+				base + SUN4I_SPI0_BC,
+				base + SUN4I_SPI0_TC,
+				0);
+	}
 }
 
 static void spi0_read_data(void *buf, u32 addr, u32 len)
 {
 	u8 *buf8 = buf;
 	u32 chunk_len;
-	uintptr_t base = spi0_base_address();
+	u8 txbuf[4];
 
 	while (len > 0) {
 		chunk_len = len;
+
+		/* Configure the Read Data Bytes (03h) command header */
+		txbuf[0] = 0x03;
+		txbuf[1] = (u8)(addr >> 16);
+		txbuf[2] = (u8)(addr >> 8);
+		txbuf[3] = (u8)(addr);
+
 		if (chunk_len > SPI_READ_MAX_SIZE)
 			chunk_len = SPI_READ_MAX_SIZE;
 
-		if (is_sun6i_gen_spi()) {
-			sunxi_spi0_read_data(buf8, addr, chunk_len,
-					     base + SUN6I_SPI0_TCR,
-					     SUN6I_TCR_XCH,
-					     base + SUN6I_SPI0_FIFO_STA,
-					     base + SUN6I_SPI0_TXD,
-					     base + SUN6I_SPI0_RXD,
-					     base + SUN6I_SPI0_MBC,
-					     base + SUN6I_SPI0_MTC,
-					     base + SUN6I_SPI0_BCC);
-		} else {
-			sunxi_spi0_read_data(buf8, addr, chunk_len,
-					     base + SUN4I_SPI0_CTL,
-					     SUN4I_CTL_XCH,
-					     base + SUN4I_SPI0_FIFO_STA,
-					     base + SUN4I_SPI0_TX,
-					     base + SUN4I_SPI0_RX,
-					     base + SUN4I_SPI0_BC,
-					     base + SUN4I_SPI0_TC,
-					     0);
-		}
+		spi0_xfer(txbuf, 4, buf8, chunk_len);
+
+		/* tSHSL time is up to 100 ns in various SPI flash datasheets */
+		udelay(1);
 
 		len  -= chunk_len;
 		buf8 += chunk_len;