On Fri, 14 Oct 2022 11:05:13 +0800
Icenowy Zheng <u...@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 <u...@icenowy.me>

With that one array index change that Samuel suggested (I can fix this up
myself):

Acked-by: Andre Przywara <andre.przyw...@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;

Reply via email to