Skip to content
Snippets Groups Projects
Commit 611c9ba2 authored by David Dueck's avatar David Dueck Committed by Jagannadha Sutradharudu Teki
Browse files

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: default avatarDavid 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: default avatarDavid Dueck <davidcdueck@googlemail.com>
Reviewed-by: default avatarJagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
parent 122d805f
No related branches found
No related tags found
No related merge requests found
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <asm/io.h> #include <asm/io.h>
#include "omap3_spi.h" #include "omap3_spi.h"
#define SPI_WAIT_TIMEOUT 3000000 #define SPI_WAIT_TIMEOUT 10
static void spi_reset(struct omap3_spi_slave *ds) 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, ...@@ -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); struct omap3_spi_slave *ds = to_omap3_spi(slave);
int i; int i;
int timeout = SPI_WAIT_TIMEOUT; ulong start;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
/* Enable the channel */ /* Enable the channel */
...@@ -241,9 +241,10 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, ...@@ -241,9 +241,10 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
/* wait till TX register is empty (TXS == 1) */ /* wait till TX register is empty (TXS == 1) */
start = get_timer(0);
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_TXS)) { OMAP3_MCSPI_CHSTAT_TXS)) {
if (--timeout <= 0) { if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI TXS timed out, status=0x%08x\n", printf("SPI TXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat)); readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1; return -1;
...@@ -280,7 +281,7 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, ...@@ -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); struct omap3_spi_slave *ds = to_omap3_spi(slave);
int i; int i;
int timeout = SPI_WAIT_TIMEOUT; ulong start;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
/* Enable the channel */ /* Enable the channel */
...@@ -295,10 +296,11 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, ...@@ -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); writel(0, &ds->regs->channel[ds->slave.cs].tx);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
start = get_timer(0);
/* Wait till RX register contains data (RXS == 1) */ /* Wait till RX register contains data (RXS == 1) */
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_RXS)) { OMAP3_MCSPI_CHSTAT_RXS)) {
if (--timeout <= 0) { if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI RXS timed out, status=0x%08x\n", printf("SPI RXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat)); readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1; return -1;
...@@ -332,7 +334,7 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, ...@@ -332,7 +334,7 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
const void *txp, void *rxp, unsigned long flags) const void *txp, void *rxp, unsigned long flags)
{ {
struct omap3_spi_slave *ds = to_omap3_spi(slave); 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 chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
int irqstatus = readl(&ds->regs->irqstatus); int irqstatus = readl(&ds->regs->irqstatus);
int i=0; int i=0;
...@@ -350,9 +352,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, ...@@ -350,9 +352,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
for (i=0; i < len; i++){ for (i=0; i < len; i++){
/* Write: wait for TX empty (TXS == 1)*/ /* Write: wait for TX empty (TXS == 1)*/
irqstatus |= (1<< (4*(ds->slave.bus))); irqstatus |= (1<< (4*(ds->slave.bus)));
start = get_timer(0);
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_TXS)) { OMAP3_MCSPI_CHSTAT_TXS)) {
if (--timeout <= 0) { if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI TXS timed out, status=0x%08x\n", printf("SPI TXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat)); readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1; return -1;
...@@ -368,9 +371,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, ...@@ -368,9 +371,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
writel(((u8 *)txp)[i], tx); writel(((u8 *)txp)[i], tx);
/*Read: wait for RX containing data (RXS == 1)*/ /*Read: wait for RX containing data (RXS == 1)*/
start = get_timer(0);
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_RXS)) { OMAP3_MCSPI_CHSTAT_RXS)) {
if (--timeout <= 0) { if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI RXS timed out, status=0x%08x\n", printf("SPI RXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat)); readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1; return -1;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment