[U-Boot] [PATCH REPOST2] spi: tegra: clear RDY bit prior to every transfer

Jagan Teki jagannadh.teki at gmail.com
Wed Dec 18 18:57:45 CET 2013


On Tue, Dec 17, 2013 at 4:17 AM, Stephen Warren <swarren at wwwdotorg.org> wrote:
> From: Yen Lin <yelin at nvidia.com>
>
> The RDY bit indicates that a transfer is complete. This needs to be
> cleared by SW before every single HW transaction, rather than only
> at the start of each SW transaction (those being made up of n HW
> transactions).
>
> It seems that earlier HW may have cleared this bit autonomously when
> starting a new transfer, and hence this code was not needed in practice.
> However, this is generally a good idea in all cases. In Tegra124, the
> HW behaviour appears to have changed, and SW must explicitly clear this
> bit. Otherwise, SW will believe that transfers have completed when they
> have not, and may e.g. read stale data from the RX FIFO.
>
> Signed-off-by: Yen Lin <yelin at nvidia.com>
> [swarren, rewrote commit description, unified duplicate RDY clearing code
> and moved it right before the start of the HW transaction, unconditionally
> exit loop after reading RX data, rather than checking if TX FIFO is empty,
> since it is guaranteed to be]
> Signed-off-by: Stephen Warren <swarren at nvidia.com>
> ---
>  drivers/spi/tegra1x4_spi.c | 21 ++++++++-------------
File not there in master -- please check.

>  1 file changed, 8 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/spi/tegra1x4_spi.c b/drivers/spi/tegra1x4_spi.c
> index 2742443e184c..a0c6537e8f5c 100644
> --- a/drivers/spi/tegra1x4_spi.c
> +++ b/drivers/spi/tegra1x4_spi.c
> @@ -275,9 +275,6 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>         reg = readl(&regs->fifo_status);
>         writel(reg, &regs->fifo_status);
>
> -       /* clear ready bit */
> -       setbits_le32(&regs->xfer_status, SPI_XFER_STS_RDY);
> -
>         clrsetbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL,
>                         SPI_CMD1_RX_EN | SPI_CMD1_TX_EN | SPI_CMD1_LSBY_FE |
>                         (slave->cs << SPI_CMD1_CS_SEL_SHIFT));
> @@ -291,7 +288,6 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>         /* handle data in 32-bit chunks */
>         while (num_bytes > 0) {
>                 int bytes;
> -               int is_read = 0;
>                 int tm, i;
>
>                 tmpdout = 0;
> @@ -305,6 +301,9 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>
>                 num_bytes -= bytes;
>
> +               /* clear ready bit */
> +               setbits_le32(&regs->xfer_status, SPI_XFER_STS_RDY);
> +
>                 clrsetbits_le32(&regs->command1,
>                                 SPI_CMD1_BIT_LEN_MASK << SPI_CMD1_BIT_LEN_SHIFT,
>                                 (bytes * 8 - 1) << SPI_CMD1_BIT_LEN_SHIFT);
> @@ -315,20 +314,14 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>                  * Wait for SPI transmit FIFO to empty, or to time out.
>                  * The RX FIFO status will be read and cleared last
>                  */
> -               for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
> +               for (tm = 0; tm < SPI_TIMEOUT; ++tm) {
>                         u32 fifo_status, xfer_status;
>
> -                       fifo_status = readl(&regs->fifo_status);
> -
> -                       /* We can exit when we've had both RX and TX activity */
> -                       if (is_read &&
> -                           (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY))
> -                               break;
> -
>                         xfer_status = readl(&regs->xfer_status);
>                         if (!(xfer_status & SPI_XFER_STS_RDY))
>                                 continue;
>
> +                       fifo_status = readl(&regs->fifo_status);
>                         if (fifo_status & SPI_FIFO_STS_ERR) {
>                                 debug("%s: got a fifo error: ", __func__);
>                                 if (fifo_status & SPI_FIFO_STS_TX_FIFO_OVF)
> @@ -353,7 +346,6 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>
>                         if (!(fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)) {
>                                 tmpdin = readl(&regs->rx_fifo);
> -                               is_read = 1;
>
>                                 /* swap bytes read in */
>                                 if (din != NULL) {
> @@ -363,6 +355,9 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>                                         }
>                                         din += bytes;
>                                 }
> +
> +                               /* We can exit when we've had both RX and TX */
> +                               break;
>                         }
>                 }
>
> --
> 1.8.1.5
>

-- 
Thanks,
Jagan.
--------
Jagannadha Sutradharudu Teki,
E: jagannadh.teki at gmail.com, P: +91-9676773388
Engineer - System Software Hacker
U-boot - SPI Custodian and Zynq APSOC
Ln: http://www.linkedin.com/in/jaganteki


More information about the U-Boot mailing list