diff options
author | Jingchang Lu <jingchang.lu@freescale.com> | 2014-09-05 08:57:05 (GMT) |
---|---|---|
committer | Matthew Weigel <Matthew.Weigel@freescale.com> | 2014-12-11 18:36:02 (GMT) |
commit | 1a8b32f3fc34b98f1d892a305829f3ddf0fa71e2 (patch) | |
tree | 41a2b310ae7d5b6b39e479cc27c69a6bed7c3894 /drivers | |
parent | a2814c6b29c8455e0cece39207025aa1cd270d8c (diff) | |
download | linux-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')
-rw-r--r-- | drivers/dma/fsl-edma.c | 89 |
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, |