Skip to content

Commit

Permalink
spi: dw: Clear DMAC register when done or stopped
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Serge Semin authored and Mark Brown committed May 15, 2020
1 parent 77810d4 commit 0327f0b
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/spi/spi-dw-mid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit 0327f0b

Please sign in to comment.