On Wed, Dec 18, 2013 at 11:48 PM, Stephen Warren <[email protected]> wrote: > From: Yen Lin <[email protected]> > > 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 <[email protected]> > [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 <[email protected]> > --- > V2: Rebased on u-boot/master rather than a local branch with some Tegra124 > changes applied first. > > drivers/spi/tegra114_spi.c | 21 ++++++++------------- > 1 file changed, 8 insertions(+), 13 deletions(-) > > diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c > index 4d2af483d77f..810fa4718ce1 100644 > --- a/drivers/spi/tegra114_spi.c > +++ b/drivers/spi/tegra114_spi.c > @@ -289,9 +289,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)); > @@ -305,7 +302,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; > @@ -319,6 +315,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); > @@ -329,20 +328,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) > @@ -367,7 +360,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) { > @@ -377,6 +369,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 >
Applied to u-boot-spi/master -- Thanks, Jagan. -------- Jagannadha Sutradharudu Teki, E: [email protected], P: +91-9676773388 Engineer - System Software Hacker U-boot - SPI Custodian and Zynq APSOC Ln: http://www.linkedin.com/in/jaganteki _______________________________________________ U-Boot mailing list [email protected] http://lists.denx.de/mailman/listinfo/u-boot

