mirror of https://gitee.com/openkylin/linux.git
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 commit0b2b66514f
("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:0b2b66514f
("spi: dw: Use DMA max burst to set the request thresholds") Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Reviewed-by: Andy 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.ru Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
ed7815db70
commit
affe93dd5b
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue