summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2015-01-27 16:33:29 (GMT)
committerVinod Koul <vinod.koul@intel.com>2015-02-16 04:03:34 (GMT)
commit3f46306127bb7d8a69078ff9ef8a5827677c2159 (patch)
treee1f0acc09d71f37b906cc56901392496ce83ea8a /drivers/dma
parent6a634808e315a148dfe8db925215cbaaa3ea1831 (diff)
downloadlinux-3f46306127bb7d8a69078ff9ef8a5827677c2159.tar.xz
dmaengine: rcar-dmac: Work around descriptor mode IOMMU errata
When descriptor memory is accessed through an IOMMU the DMADAR register isn't initialized automatically from the first descriptor at beginning of transfer by the DMAC like it should. Initialize it manually with the destination address of the first chunk. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/sh/rcar-dmac.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index bb93038..711da01 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -325,6 +325,8 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
rcar_dmac_chan_write(chan, RCAR_DMARS, chan->mid_rid);
if (desc->hwdescs.use) {
+ struct rcar_dmac_xfer_chunk *chunk;
+
dev_dbg(chan->chan.device->dev,
"chan%u: queue desc %p: %u@%pad\n",
chan->index, desc, desc->nchunks, &desc->hwdescs.dma);
@@ -341,6 +343,18 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
RCAR_DMACHCRB_DRST);
/*
+ * Errata: When descriptor memory is accessed through an IOMMU
+ * the DMADAR register isn't initialized automatically from the
+ * first descriptor at beginning of transfer by the DMAC like it
+ * should. Initialize it manually with the destination address
+ * of the first chunk.
+ */
+ chunk = list_first_entry(&desc->chunks,
+ struct rcar_dmac_xfer_chunk, node);
+ rcar_dmac_chan_write(chan, RCAR_DMADAR,
+ chunk->dst_addr & 0xffffffff);
+
+ /*
* Program the descriptor stage interrupt to occur after the end
* of the first stage.
*/