lkml.org 
[lkml]   [2020]   [May]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 03/19] spi: dw: Clear DMAC register when done or stopped
Date
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>
Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Allison Randal <allison@lohutok.net>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Gareth Williams <gareth.williams.jx@renesas.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org

---

Changelog v2:
- Move the patch to the head of the series so one could be picked up to
the stable kernels as a fix.
- Clear the DMACR in the DMA exit callback too.
---
drivers/spi/spi-dw-mid.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index 7a5ae1506365..0c597b6bb154 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -108,6 +108,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)
@@ -178,6 +180,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);
}

@@ -249,6 +253,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);
}

@@ -342,6 +348,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 = {
--
2.25.1
\
 
 \ /
  Last update: 2020-05-15 12:49    [W:0.596 / U:0.068 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site