diff options
author | Vladimir Barinov <vladimir.barinov@cogentembedded.com> | 2017-12-10 23:51:43 +0300 |
---|---|---|
committer | Vladimir Barinov <vladimir.barinov@cogentembedded.com> | 2017-12-10 23:51:43 +0300 |
commit | 157552575a14a71b923821641551c98df94055f3 (patch) | |
tree | 2003978701637f51726844b154226ece01d40856 /meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch | |
parent | 47bbe76d08109fb77ced2ce98ec734cb7740792e (diff) |
DMAC fixes
- Backport RCAR DMAC fixes from upstream
- Reeneable DMA for SCIF0 on R8A7797
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch')
-rw-r--r-- | meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch new file mode 100644 index 0000000..e1597ea --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch @@ -0,0 +1,87 @@ +From a8d46a7f5d17ca9cbe9e9c7d1d23dc6ea437e141 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 17 Nov 2017 11:00:28 +0900 +Subject: [PATCH 1/2] 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> +--- + drivers/dma/sh/rcar-dmac.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c +index 2b2c7db..c99fd0f 100644 +--- a/drivers/dma/sh/rcar-dmac.c ++++ b/drivers/dma/sh/rcar-dmac.c +@@ -10,6 +10,7 @@ + * published by the Free Software Foundation. + */ + ++#include <linux/delay.h> + #include <linux/dma-mapping.h> + #include <linux/dmaengine.h> + #include <linux/interrupt.h> +@@ -741,6 +742,24 @@ static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan, + /* ----------------------------------------------------------------------------- + * Stop and reset + */ ++static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan) ++{ ++ u32 chcr; ++ unsigned int i; ++ ++ /* ++ * Ensure that the setting of the DE bit is actually 0 after ++ * clearing it. ++ */ ++ for (i = 0; i < 1024; i++) { ++ chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); ++ if (!(chcr & RCAR_DMACHCR_DE)) ++ return; ++ udelay(1); ++ } ++ ++ dev_err(chan->chan.device->dev, "CHCR DE check error\n"); ++} + + static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) + { +@@ -749,6 +768,7 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) + chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE | + RCAR_DMACHCR_TE | RCAR_DMACHCR_DE); + rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); ++ rcar_dmac_chcr_de_barrier(chan); + } + + static 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) + if (chcr & RCAR_DMACHCR_TE) + mask |= RCAR_DMACHCR_DE; + rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask); ++ if (mask & RCAR_DMACHCR_DE) ++ rcar_dmac_chcr_de_barrier(chan); + + if (chcr & RCAR_DMACHCR_DSE) + ret |= rcar_dmac_isr_desc_stage_end(chan); +-- +1.9.1 + |