summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorJingchang Lu <jingchang.lu@freescale.com>2014-09-05 08:57:05 (GMT)
committerMatthew Weigel <Matthew.Weigel@freescale.com>2014-12-11 18:36:02 (GMT)
commit1a8b32f3fc34b98f1d892a305829f3ddf0fa71e2 (patch)
tree41a2b310ae7d5b6b39e479cc27c69a6bed7c3894 /drivers/dma
parenta2814c6b29c8455e0cece39207025aa1cd270d8c (diff)
downloadlinux-fsl-qoriq-1a8b32f3fc34b98f1d892a305829f3ddf0fa71e2.tar.xz
dmaengine: fsl-edma: add S/G support for big-endian eDMA model
The hardware Scatter/Gather requires the to-be auto loaded TCDs struct in memory retains the same endian as the core independent of the model's register endian, the auto load engine will do the swap if need. Signed-off-by: Jingchang Lu <jingchang.lu@freescale.com> Change-Id: I4251239bd06a64c166873f05e5799d95b267ead8 Reviewed-on: http://git.am.freescale.net:8181/19200 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Huan Wang <alison.wang@freescale.com> Reviewed-by: Zhengxiong Jin <Jason.Jin@freescale.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/fsl-edma.c89
1 files changed, 51 insertions, 38 deletions
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 9159831..1cc536b 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -183,11 +183,14 @@ struct fsl_edma_engine {
static u16 edma_readw(struct fsl_edma_engine *edma, void __iomem *addr)
{
+ u32 dst;
/* swap the reg offset for that in big-endian mode*/
- if (edma->big_endian)
- return ioread16be((void __iomem *)(((u32)addr & ~0x3) | (((u32)addr & 0x3) ^ 0x2)));
- else
+ if (edma->big_endian) {
+ dst = ((u32)addr & ~0x3) | (((u32)addr & 0x3) ^ 0x2);
+ return ioread16be((void __iomem *)dst);
+ } else {
return ioread16(addr);
+ }
}
static u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
@@ -200,28 +203,26 @@ static u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
static void edma_writeb(struct fsl_edma_engine *edma, u8 val, void __iomem *addr)
{
+ u32 dst;
/* swap the reg offset for that in big-endian mode*/
- if (edma->big_endian)
- iowrite8(val, (void __iomem *)(((u32)addr & ~0x3) | (((u32)addr & 0x3) ^ 0x3)));
- else
+ if (edma->big_endian) {
+ dst = ((u32)addr & ~0x3) | (((u32)addr & 0x3) ^ 0x3);
+ iowrite8(val, (void __iomem *)dst);
+ } else {
iowrite8(val, addr);
+ }
}
static void edma_writew(struct fsl_edma_engine *edma, u16 val, void __iomem *addr)
{
+ u32 dst;
/* swap the reg offset for that in big-endian mode*/
- if (edma->big_endian)
- writew(val, (void __iomem *)(((u32)addr & ~0x3) | (((u32)addr & 0x3) ^ 0x2)));
- else
- writew(val, addr);
-}
-
-static void edma_tcd_writew(struct fsl_edma_engine *edma, u16 val, void __iomem *addr)
-{
- if (edma->big_endian)
- iowrite16be(val, addr);
- else
+ if (edma->big_endian) {
+ dst = ((u32)addr & ~0x3) | (((u32)addr & 0x3) ^ 0x2);
+ iowrite16be(val, (void __iomem *)dst);
+ } else {
iowrite16(val, addr);
+ }
}
static void edma_writel(struct fsl_edma_engine *edma, u32 val, void __iomem *addr)
@@ -448,20 +449,25 @@ static void fsl_edma_set_tcd_params(struct fsl_edma_chan *fsl_chan,
u32 ch = fsl_chan->vchan.chan.chan_id;
/*
- * TCD parameters have been swapped in fill_tcd_params(),
- * so just write them to registers in the cpu endian here
+ * TCD parameters should be swapped according the eDMA
+ * engine requirement.
*/
edma_writew(fsl_chan->edma, 0, addr + EDMA_TCD_CSR(ch));
- writel(src, addr + EDMA_TCD_SADDR(ch));
- writel(dst, addr + EDMA_TCD_DADDR(ch));
+ edma_writel(fsl_chan->edma, src, addr + EDMA_TCD_SADDR(ch));
+ edma_writel(fsl_chan->edma, dst, addr + EDMA_TCD_DADDR(ch));
+
edma_writew(fsl_chan->edma, attr, addr + EDMA_TCD_ATTR(ch));
edma_writew(fsl_chan->edma, soff, addr + EDMA_TCD_SOFF(ch));
- writel(nbytes, addr + EDMA_TCD_NBYTES(ch));
- writel(slast, addr + EDMA_TCD_SLAST(ch));
+
+ edma_writel(fsl_chan->edma, nbytes, addr + EDMA_TCD_NBYTES(ch));
+ edma_writel(fsl_chan->edma, slast, addr + EDMA_TCD_SLAST(ch));
+
edma_writew(fsl_chan->edma, citer, addr + EDMA_TCD_CITER(ch));
edma_writew(fsl_chan->edma, biter, addr + EDMA_TCD_BITER(ch));
edma_writew(fsl_chan->edma, doff, addr + EDMA_TCD_DOFF(ch));
- writel(dlast_sga, addr + EDMA_TCD_DLAST_SGA(ch));
+
+ edma_writel(fsl_chan->edma, dlast_sga, addr + EDMA_TCD_DLAST_SGA(ch));
+
edma_writew(fsl_chan->edma, csr, addr + EDMA_TCD_CSR(ch));
}
@@ -474,20 +480,27 @@ static void fill_tcd_params(struct fsl_edma_engine *edma,
u16 csr = 0;
/*
- * eDMA hardware SGs require the TCD parameters stored in memory
- * the same endian as the eDMA module so that they can be loaded
- * automatically by the engine
+ * eDMA hardware SGs requires the TCDs to be auto loaded
+ * in the same endian as the core whenver the eDAM engine's
+ * register endian. So we don't swap the value, waitting
+ * for fsl_set_tcd_params doing the swap.
*/
- edma_writel(edma, src, &(tcd->saddr));
- edma_writel(edma, dst, &(tcd->daddr));
- edma_tcd_writew(edma, attr, &(tcd->attr));
- edma_tcd_writew(edma, EDMA_TCD_SOFF_SOFF(soff), &(tcd->soff));
- edma_writel(edma, EDMA_TCD_NBYTES_NBYTES(nbytes), &(tcd->nbytes));
- edma_writel(edma, EDMA_TCD_SLAST_SLAST(slast), &(tcd->slast));
- edma_tcd_writew(edma, EDMA_TCD_CITER_CITER(citer), &(tcd->citer));
- edma_tcd_writew(edma, EDMA_TCD_DOFF_DOFF(doff), &(tcd->doff));
- edma_writel(edma, EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga), &(tcd->dlast_sga));
- edma_tcd_writew(edma, EDMA_TCD_BITER_BITER(biter), &(tcd->biter));
+ writel(src, &(tcd->saddr));
+ writel(dst, &(tcd->daddr));
+
+ writew(attr, &(tcd->attr));
+
+ writew(EDMA_TCD_SOFF_SOFF(soff), &(tcd->soff));
+
+ writel(EDMA_TCD_NBYTES_NBYTES(nbytes), &(tcd->nbytes));
+ writel(EDMA_TCD_SLAST_SLAST(slast), &(tcd->slast));
+
+ writew(EDMA_TCD_CITER_CITER(citer), &(tcd->citer));
+ writew(EDMA_TCD_DOFF_DOFF(doff), &(tcd->doff));
+
+ writel(EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga), &(tcd->dlast_sga));
+
+ writew(EDMA_TCD_BITER_BITER(biter), &(tcd->biter));
if (major_int)
csr |= EDMA_TCD_CSR_INT_MAJOR;
@@ -497,7 +510,7 @@ static void fill_tcd_params(struct fsl_edma_engine *edma,
if (enable_sg)
csr |= EDMA_TCD_CSR_E_SG;
- edma_tcd_writew(edma, csr, &(tcd->csr));
+ writew(csr, &(tcd->csr));
}
static struct fsl_edma_desc *fsl_edma_alloc_desc(struct fsl_edma_chan *fsl_chan,