diff options
Diffstat (limited to 'meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch')
-rw-r--r-- | meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch b/meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch new file mode 100644 index 0000000..64782f7 --- /dev/null +++ b/meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch @@ -0,0 +1,83 @@ +From 1066e8ae45193732f235df740ac31f3e60fc1fe6 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 10 Nov 2017 13:07:55 +0900 +Subject: [PATCH 1/3] dmaengine: rcar-dmac: ensure CHCR DE bit is actually 0 + after clear + +DMAC reads data from source device, and buffered it until transferable +size for shink deivce. Because of this behavoir, DMAC is including +buffered data . + +Now, CHCR DE bit is controlling DMA transfer enable/disable. + +If DE bit was cleared during data transfering, 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 cleared. + +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> +--- + 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..16ebd5d 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; ++ 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 + |