Message ID | 1387234034-6163-1-git-send-email-swarren@wwwdotorg.org |
---|---|
State | Superseded |
Delegated to: | Jagannadha Sutradharudu Teki |
Headers | show |
On Tue, Dec 17, 2013 at 4:17 AM, Stephen Warren <swarren@wwwdotorg.org> wrote: > From: Yen Lin <yelin@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@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@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 >
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; } }