[PATCH 1/8] sunxi: SPL SPI: extract code for doing SPI transfer
Andre Przywara
andre.przywara at arm.com
Tue Dec 12 19:12:16 CET 2023
On Fri, 14 Oct 2022 11:05:13 +0800
Icenowy Zheng <uwu at icenowy.me> wrote:
Hi,
> 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.
I was looking for a better solution than this inflated function parameter
list, but everything I came up with is actually worse. So it's fine like
you wrote it here.
I think it now even looks a bit better, since that long list is now
wrapped completely by the spi0_xfer() function.
It increases the code size by 20 (Thumb2) and 28 bytes (AArch64), that's
not great, but acceptable.
> Signed-off-by: Icenowy Zheng <uwu at icenowy.me>
With that one array index change that Samuel suggested (I can fix this up
myself):
Acked-by: Andre Przywara <andre.przywara at arm.com>
Cheers,
Andre
> ---
> 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;
More information about the U-Boot
mailing list