[PATCH 1/8] sunxi: SPL SPI: extract code for doing SPI transfer
Icenowy Zheng
uwu at icenowy.me
Fri Oct 14 05:05:13 CEST 2022
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 at icenowy.me>
---
arch/arm/mach-sunxi/spl_spi_sunxi.c | 105 ++++++++++++++++------------
1 file changed, 59 insertions(+), 46 deletions(-)
diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 925bf85f2d..7975457758 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -243,77 +243,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;
--
2.37.1
More information about the U-Boot
mailing list