diff options
author | David Dueck <davidcdueck@googlemail.com> | 2015-04-01 14:20:24 +0200 |
---|---|---|
committer | Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com> | 2015-04-27 21:08:42 +0530 |
commit | 611c9ba2b8c27d6e3c63b663c88f1c8be9638c3a (patch) | |
tree | 052bb82f7e9edac667f76a32df52e28d96fb5fa1 | |
parent | 122d805fd4bd478bb83536348291d34ae648364b (diff) |
spi: omap3: Fix timeout handling
The timeout value is never reset during the transfer. This means that when
transferring more data we eventually trigger the timeout.
This was reported on the mailing list:
"Spansion SPI flash read timeout with AM335x"
Signed-off-by: David Dueck <davidcdueck@googlemail.com>
CC: Tom Rini <trini@konsulko.com>
CC: Stefan Roese <sr@denx.de>
CC: Andy Pont <andy.pont@sdcsystems.com>
Tested-by: David Dueck <davidcdueck@googlemail.com>
Reviewed-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
-rw-r--r-- | drivers/spi/omap3_spi.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 651e46e4bd..85f9e85fd4 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -20,7 +20,7 @@ #include <asm/io.h> #include "omap3_spi.h" -#define SPI_WAIT_TIMEOUT 3000000 +#define SPI_WAIT_TIMEOUT 10 static void spi_reset(struct omap3_spi_slave *ds) { @@ -227,7 +227,7 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, { struct omap3_spi_slave *ds = to_omap3_spi(slave); int i; - int timeout = SPI_WAIT_TIMEOUT; + ulong start; int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); /* Enable the channel */ @@ -241,9 +241,10 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, for (i = 0; i < len; i++) { /* wait till TX register is empty (TXS == 1) */ + start = get_timer(0); while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI TXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; @@ -280,7 +281,7 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, { struct omap3_spi_slave *ds = to_omap3_spi(slave); int i; - int timeout = SPI_WAIT_TIMEOUT; + ulong start; int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); /* Enable the channel */ @@ -295,10 +296,11 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, writel(0, &ds->regs->channel[ds->slave.cs].tx); for (i = 0; i < len; i++) { + start = get_timer(0); /* Wait till RX register contains data (RXS == 1) */ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI RXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; @@ -332,7 +334,7 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const void *txp, void *rxp, unsigned long flags) { struct omap3_spi_slave *ds = to_omap3_spi(slave); - int timeout = SPI_WAIT_TIMEOUT; + ulong start; int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); int irqstatus = readl(&ds->regs->irqstatus); int i=0; @@ -350,9 +352,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, for (i=0; i < len; i++){ /* Write: wait for TX empty (TXS == 1)*/ irqstatus |= (1<< (4*(ds->slave.bus))); + start = get_timer(0); while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI TXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; @@ -368,9 +371,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, writel(((u8 *)txp)[i], tx); /*Read: wait for RX containing data (RXS == 1)*/ + start = get_timer(0); while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI RXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; |