diff options
author | Linus Walleij <linus.walleij@stericsson.com> | 2010-01-22 15:53:30 +0300 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-01-28 01:00:46 +0300 |
commit | fc05475f867624dddd5ea7089cf8f434f95fbec5 (patch) | |
tree | 2ce5ef39c5f65c5bf80fa836c0a709ee4dda55a9 /drivers/spi | |
parent | 08d1e2e68da977956ff10735148ac1de21c85afd (diff) | |
download | linux-fc05475f867624dddd5ea7089cf8f434f95fbec5.tar.xz |
ARM: 5893/1: SPI AMBA PL022: Limit TX FIFO fills
Added logic to cap TX FIFO fill size based on current free RX
FIFO entries instead of TX status flags. This is to prevent
an issue with RX FIFO overflows.
Signed-off-by: Kevin Wells <kevin.wells@nxp.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/amba-pl022.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index ff5bbb9c43c9..9aeb68113100 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -363,6 +363,7 @@ struct pl022 { void *rx_end; enum ssp_reading read; enum ssp_writing write; + u32 exp_fifo_level; }; /** @@ -501,6 +502,9 @@ static int flush(struct pl022 *pl022) while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) readw(SSP_DR(pl022->virtbase)); } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); + + pl022->exp_fifo_level = 0; + return limit; } @@ -583,10 +587,9 @@ static void readwriter(struct pl022 *pl022) * errons in 8bit wide transfers on ARM variants (just 8 words * FIFO, means only 8x8 = 64 bits in FIFO) at least. * - * FIXME: currently we have no logic to account for this. - * perhaps there is even something broken in HW regarding - * 8bit transfers (it doesn't fail on 16bit) so this needs - * more investigation... + * To prevent this issue, the TX FIFO is only filled to the + * unused RX FIFO fill length, regardless of what the TX + * FIFO status flag indicates. */ dev_dbg(&pl022->adev->dev, "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", @@ -613,11 +616,12 @@ static void readwriter(struct pl022 *pl022) break; } pl022->rx += (pl022->cur_chip->n_bytes); + pl022->exp_fifo_level--; } /* - * Write as much as you can, while keeping an eye on the RX FIFO! + * Write as much as possible up to the RX FIFO size */ - while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) + while ((pl022->exp_fifo_level < pl022->vendor->fifodepth) && (pl022->tx < pl022->tx_end)) { switch (pl022->write) { case WRITING_NULL: @@ -634,6 +638,7 @@ static void readwriter(struct pl022 *pl022) break; } pl022->tx += (pl022->cur_chip->n_bytes); + pl022->exp_fifo_level++; /* * This inner reader takes care of things appearing in the RX * FIFO as we're transmitting. This will happen a lot since the @@ -660,6 +665,7 @@ static void readwriter(struct pl022 *pl022) break; } pl022->rx += (pl022->cur_chip->n_bytes); + pl022->exp_fifo_level--; } } /* |