Skip to content

Commit 0327f0b

Browse files
fancerbroonie
authored andcommitted
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 <[email protected]> Signed-off-by: Georgy Vlasov <[email protected]> Signed-off-by: Serge Semin <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 77810d4 commit 0327f0b

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

drivers/spi/spi-dw-mid.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ static void mid_spi_dma_exit(struct dw_spi *dws)
106106
dmaengine_terminate_sync(dws->rxchan);
107107
dma_release_channel(dws->rxchan);
108108
}
109+
110+
dw_writel(dws, DW_SPI_DMACR, 0);
109111
}
110112

111113
static irqreturn_t dma_transfer(struct dw_spi *dws)
@@ -152,6 +154,8 @@ static void dw_spi_dma_tx_done(void *arg)
152154
clear_bit(TX_BUSY, &dws->dma_chan_busy);
153155
if (test_bit(RX_BUSY, &dws->dma_chan_busy))
154156
return;
157+
158+
dw_writel(dws, DW_SPI_DMACR, 0);
155159
spi_finalize_current_transfer(dws->master);
156160
}
157161

@@ -199,6 +203,8 @@ static void dw_spi_dma_rx_done(void *arg)
199203
clear_bit(RX_BUSY, &dws->dma_chan_busy);
200204
if (test_bit(TX_BUSY, &dws->dma_chan_busy))
201205
return;
206+
207+
dw_writel(dws, DW_SPI_DMACR, 0);
202208
spi_finalize_current_transfer(dws->master);
203209
}
204210

@@ -292,6 +298,8 @@ static void mid_spi_dma_stop(struct dw_spi *dws)
292298
dmaengine_terminate_sync(dws->rxchan);
293299
clear_bit(RX_BUSY, &dws->dma_chan_busy);
294300
}
301+
302+
dw_writel(dws, DW_SPI_DMACR, 0);
295303
}
296304

297305
static const struct dw_spi_dma_ops mfld_dma_ops = {

0 commit comments

Comments
 (0)