Commit affe93dd authored by Serge Semin's avatar Serge Semin Committed by Mark Brown

spi: dw-dma: Fix Tx DMA channel working too fast

It turns out having a Rx DMA channel serviced with higher priority than
a Tx DMA channel is not enough to provide a well balanced DMA-based SPI
transfer interface. There might still be moments when the Tx DMA channel
is occasionally handled faster than the Rx DMA channel. That in its turn
will eventually cause the SPI Rx FIFO overflow if SPI bus speed is high
enough to fill the SPI Rx FIFO in before it's cleared by the Rx DMA
channel. That's why having the DMA-based SPI Tx interface too optimized
is the errors prone, so the commit 0b2b6651 ("spi: dw: Use DMA max
burst to set the request thresholds") though being perfectly normal from
the standard functionality point of view implicitly introduced the problem
described above. In order to fix that the Tx DMA activity is intentionally
slowed down by limiting the SPI Tx FIFO depth with a value twice bigger
than the Tx burst length calculated earlier by the
dw_spi_dma_maxburst_init() method.

Fixes: 0b2b6651 ("spi: dw: Use DMA max burst to set the request thresholds")
Signed-off-by: default avatarSerge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Feng Tang <feng.tang@intel.com>
Link: https://lore.kernel.org/r/20200721203951.2159-1-Sergey.Semin@baikalelectronics.ruSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent ed7815db
...@@ -372,8 +372,20 @@ static int dw_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer) ...@@ -372,8 +372,20 @@ static int dw_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
{ {
u16 imr = 0, dma_ctrl = 0; u16 imr = 0, dma_ctrl = 0;
/*
* Having a Rx DMA channel serviced with higher priority than a Tx DMA
* channel might not be enough to provide a well balanced DMA-based
* SPI transfer interface. There might still be moments when the Tx DMA
* channel is occasionally handled faster than the Rx DMA channel.
* That in its turn will eventually cause the SPI Rx FIFO overflow if
* SPI bus speed is high enough to fill the SPI Rx FIFO in before it's
* cleared by the Rx DMA channel. In order to fix the problem the Tx
* DMA activity is intentionally slowed down by limiting the SPI Tx
* FIFO depth with a value twice bigger than the Tx burst length
* calculated earlier by the dw_spi_dma_maxburst_init() method.
*/
dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1); dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1);
dw_writel(dws, DW_SPI_DMATDLR, dws->fifo_len - dws->txburst); dw_writel(dws, DW_SPI_DMATDLR, dws->txburst);
if (xfer->tx_buf) if (xfer->tx_buf)
dma_ctrl |= SPI_DMA_TDMAE; dma_ctrl |= SPI_DMA_TDMAE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment