[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(®s->fifo_status);
> writel(reg, ®s->fifo_status);
>
> - /* clear ready bit */
> - setbits_le32(®s->xfer_status, SPI_XFER_STS_RDY);
> -
> clrsetbits_le32(®s->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(®s->xfer_status, SPI_XFER_STS_RDY);
> +
> clrsetbits_le32(®s->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(®s->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(®s->xfer_status);
> if (!(xfer_status & SPI_XFER_STS_RDY))
> continue;
>
> + fifo_status = readl(®s->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(®s->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