spi: dw: Clear DMAC register when done or stopped
If DMAC register is left uncleared any further DMAless transfers may cause the DMAC hardware handshaking interface getting activated. So the next DMA-based Rx/Tx transaction will be started right after the dma_async_issue_pending() method is invoked even if no DMATDLR/DMARDLR conditions are met. This at the same time may cause the Tx/Rx FIFO buffers underrun/overrun. In order to fix this we must clear DMAC register after a current DMA-based transaction is finished. Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru> Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20200515104758.6934-4-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
77810d484f
Коммит
0327f0b881
|
@ -106,6 +106,8 @@ static void mid_spi_dma_exit(struct dw_spi *dws)
|
|||
dmaengine_terminate_sync(dws->rxchan);
|
||||
dma_release_channel(dws->rxchan);
|
||||
}
|
||||
|
||||
dw_writel(dws, DW_SPI_DMACR, 0);
|
||||
}
|
||||
|
||||
static irqreturn_t dma_transfer(struct dw_spi *dws)
|
||||
|
@ -152,6 +154,8 @@ static void dw_spi_dma_tx_done(void *arg)
|
|||
clear_bit(TX_BUSY, &dws->dma_chan_busy);
|
||||
if (test_bit(RX_BUSY, &dws->dma_chan_busy))
|
||||
return;
|
||||
|
||||
dw_writel(dws, DW_SPI_DMACR, 0);
|
||||
spi_finalize_current_transfer(dws->master);
|
||||
}
|
||||
|
||||
|
@ -199,6 +203,8 @@ static void dw_spi_dma_rx_done(void *arg)
|
|||
clear_bit(RX_BUSY, &dws->dma_chan_busy);
|
||||
if (test_bit(TX_BUSY, &dws->dma_chan_busy))
|
||||
return;
|
||||
|
||||
dw_writel(dws, DW_SPI_DMACR, 0);
|
||||
spi_finalize_current_transfer(dws->master);
|
||||
}
|
||||
|
||||
|
@ -292,6 +298,8 @@ static void mid_spi_dma_stop(struct dw_spi *dws)
|
|||
dmaengine_terminate_sync(dws->rxchan);
|
||||
clear_bit(RX_BUSY, &dws->dma_chan_busy);
|
||||
}
|
||||
|
||||
dw_writel(dws, DW_SPI_DMACR, 0);
|
||||
}
|
||||
|
||||
static const struct dw_spi_dma_ops mfld_dma_ops = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче