aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2017-11-16 21:00:28 -0500
committerVinod Koul <vinod.koul@intel.com>2017-11-29 09:12:57 -0500
commita8d46a7f5d17ca9cbe9e9c7d1d23dc6ea437e141 (patch)
treedccacc000a57e194a089d4bb2ccc0a693fca0c5f
parent4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff)
dmaengine: rcar-dmac: ensure CHCR DE bit is actually 0 after clearing
DMAC reads data from source device, and buffered it until transferable size for sink device. Because of this behavior, DMAC is including buffered data . Now, CHCR DE bit is controlling DMA transfer enable/disable. If DE bit was cleared during data transferring, or during buffering, it will flush buffered data if source device was peripheral device (The buffered data will be removed if source device was memory). Because of this behavior, driver should ensure that DE bit is actually 0 after clearing. This patch adds new rcar_dmac_chcr_de_barrier() and call it after CHCR register access. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> Tested-by: Ryo Kodama <ryo.kodama.vz@renesas.com> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/sh/rcar-dmac.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 2b2c7db3e480..c99fd0f6ff13 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -10,6 +10,7 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/delay.h>
13#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
14#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
15#include <linux/interrupt.h> 16#include <linux/interrupt.h>
@@ -741,6 +742,24 @@ static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
741/* ----------------------------------------------------------------------------- 742/* -----------------------------------------------------------------------------
742 * Stop and reset 743 * Stop and reset
743 */ 744 */
745static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
746{
747 u32 chcr;
748 unsigned int i;
749
750 /*
751 * Ensure that the setting of the DE bit is actually 0 after
752 * clearing it.
753 */
754 for (i = 0; i < 1024; i++) {
755 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
756 if (!(chcr & RCAR_DMACHCR_DE))
757 return;
758 udelay(1);
759 }
760
761 dev_err(chan->chan.device->dev, "CHCR DE check error\n");
762}
744 763
745static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) 764static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
746{ 765{
@@ -749,6 +768,7 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
749 chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE | 768 chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE |
750 RCAR_DMACHCR_TE | RCAR_DMACHCR_DE); 769 RCAR_DMACHCR_TE | RCAR_DMACHCR_DE);
751 rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); 770 rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
771 rcar_dmac_chcr_de_barrier(chan);
752} 772}
753 773
754static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan) 774static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan)
@@ -1481,6 +1501,8 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
1481 if (chcr & RCAR_DMACHCR_TE) 1501 if (chcr & RCAR_DMACHCR_TE)
1482 mask |= RCAR_DMACHCR_DE; 1502 mask |= RCAR_DMACHCR_DE;
1483 rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask); 1503 rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask);
1504 if (mask & RCAR_DMACHCR_DE)
1505 rcar_dmac_chcr_de_barrier(chan);
1484 1506
1485 if (chcr & RCAR_DMACHCR_DSE) 1507 if (chcr & RCAR_DMACHCR_DSE)
1486 ret |= rcar_dmac_isr_desc_stage_end(chan); 1508 ret |= rcar_dmac_isr_desc_stage_end(chan);