From 377eaf3b3c4ad74efed77e846320188fc312a0e2 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 19 Aug 2018 19:27:14 +0200 Subject: dmaengine: fsl-edma: add edma version and configurable registers This patch adds configurable registers (using __iomem addresses) to allow the use of fsl-edma-common code with slightly different edma module versions, as Vybrid (v1) and ColdFire (v2) are. Signed-off-by: Angelo Dureghello Tested-by: Krzysztof Kozlowski Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma-common.c | 106 ++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 30 deletions(-) (limited to 'drivers/dma/fsl-edma-common.c') diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c index 3fc786b3d03c..227034de256e 100644 --- a/drivers/dma/fsl-edma-common.c +++ b/drivers/dma/fsl-edma-common.c @@ -43,20 +43,20 @@ static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan) { - void __iomem *addr = fsl_chan->edma->membase; + struct edma_regs *regs = &fsl_chan->edma->regs; u32 ch = fsl_chan->vchan.chan.chan_id; - edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), addr + EDMA_SEEI); - edma_writeb(fsl_chan->edma, ch, addr + EDMA_SERQ); + edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei); + edma_writeb(fsl_chan->edma, ch, regs->serq); } void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan) { - void __iomem *addr = fsl_chan->edma->membase; + struct edma_regs *regs = &fsl_chan->edma->regs; u32 ch = fsl_chan->vchan.chan.chan_id; - edma_writeb(fsl_chan->edma, ch, addr + EDMA_CERQ); - edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), addr + EDMA_CEEI); + edma_writeb(fsl_chan->edma, ch, regs->cerq); + edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei); } EXPORT_SYMBOL_GPL(fsl_edma_disable_request); @@ -184,7 +184,7 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan, struct virt_dma_desc *vdesc, bool in_progress) { struct fsl_edma_desc *edesc = fsl_chan->edesc; - void __iomem *addr = fsl_chan->edma->membase; + struct edma_regs *regs = &fsl_chan->edma->regs; u32 ch = fsl_chan->vchan.chan.chan_id; enum dma_transfer_direction dir = fsl_chan->fsc.dir; dma_addr_t cur_addr, dma_addr; @@ -200,11 +200,9 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan, return len; if (dir == DMA_MEM_TO_DEV) - cur_addr = edma_readl( - fsl_chan->edma, addr + EDMA_TCD_SADDR(ch)); + cur_addr = edma_readl(fsl_chan->edma, ®s->tcd[ch].saddr); else - cur_addr = edma_readl( - fsl_chan->edma, addr + EDMA_TCD_DADDR(ch)); + cur_addr = edma_readl(fsl_chan->edma, ®s->tcd[ch].daddr); /* figure out the finished and calculate the residue */ for (i = 0; i < fsl_chan->edesc->n_tcds; i++) { @@ -261,7 +259,7 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan, struct fsl_edma_hw_tcd *tcd) { struct fsl_edma_engine *edma = fsl_chan->edma; - void __iomem *addr = fsl_chan->edma->membase; + struct edma_regs *regs = &fsl_chan->edma->regs; u32 ch = fsl_chan->vchan.chan.chan_id; /* @@ -269,24 +267,24 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan, * endian format. However, we need to load the TCD registers in * big- or little-endian obeying the eDMA engine model endian. */ - edma_writew(edma, 0, addr + EDMA_TCD_CSR(ch)); - edma_writel(edma, le32_to_cpu(tcd->saddr), addr + EDMA_TCD_SADDR(ch)); - edma_writel(edma, le32_to_cpu(tcd->daddr), addr + EDMA_TCD_DADDR(ch)); + edma_writew(edma, 0, ®s->tcd[ch].csr); + edma_writel(edma, le32_to_cpu(tcd->saddr), ®s->tcd[ch].saddr); + edma_writel(edma, le32_to_cpu(tcd->daddr), ®s->tcd[ch].daddr); - edma_writew(edma, le16_to_cpu(tcd->attr), addr + EDMA_TCD_ATTR(ch)); - edma_writew(edma, le16_to_cpu(tcd->soff), addr + EDMA_TCD_SOFF(ch)); + edma_writew(edma, le16_to_cpu(tcd->attr), ®s->tcd[ch].attr); + edma_writew(edma, le16_to_cpu(tcd->soff), ®s->tcd[ch].soff); - edma_writel(edma, le32_to_cpu(tcd->nbytes), addr + EDMA_TCD_NBYTES(ch)); - edma_writel(edma, le32_to_cpu(tcd->slast), addr + EDMA_TCD_SLAST(ch)); + edma_writel(edma, le32_to_cpu(tcd->nbytes), ®s->tcd[ch].nbytes); + edma_writel(edma, le32_to_cpu(tcd->slast), ®s->tcd[ch].slast); - edma_writew(edma, le16_to_cpu(tcd->citer), addr + EDMA_TCD_CITER(ch)); - edma_writew(edma, le16_to_cpu(tcd->biter), addr + EDMA_TCD_BITER(ch)); - edma_writew(edma, le16_to_cpu(tcd->doff), addr + EDMA_TCD_DOFF(ch)); + edma_writew(edma, le16_to_cpu(tcd->citer), ®s->tcd[ch].citer); + edma_writew(edma, le16_to_cpu(tcd->biter), ®s->tcd[ch].biter); + edma_writew(edma, le16_to_cpu(tcd->doff), ®s->tcd[ch].doff); - edma_writel(edma, - le32_to_cpu(tcd->dlast_sga), addr + EDMA_TCD_DLAST_SGA(ch)); + edma_writel(edma, le32_to_cpu(tcd->dlast_sga), + ®s->tcd[ch].dlast_sga); - edma_writew(edma, le16_to_cpu(tcd->csr), addr + EDMA_TCD_CSR(ch)); + edma_writew(edma, le16_to_cpu(tcd->csr), ®s->tcd[ch].csr); } static inline @@ -308,15 +306,15 @@ void fsl_edma_fill_tcd(struct fsl_edma_hw_tcd *tcd, u32 src, u32 dst, tcd->attr = cpu_to_le16(attr); - tcd->soff = cpu_to_le16(EDMA_TCD_SOFF_SOFF(soff)); + tcd->soff = cpu_to_le16(soff); - tcd->nbytes = cpu_to_le32(EDMA_TCD_NBYTES_NBYTES(nbytes)); - tcd->slast = cpu_to_le32(EDMA_TCD_SLAST_SLAST(slast)); + tcd->nbytes = cpu_to_le32(nbytes); + tcd->slast = cpu_to_le32(slast); tcd->citer = cpu_to_le16(EDMA_TCD_CITER_CITER(citer)); - tcd->doff = cpu_to_le16(EDMA_TCD_DOFF_DOFF(doff)); + tcd->doff = cpu_to_le16(doff); - tcd->dlast_sga = cpu_to_le32(EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga)); + tcd->dlast_sga = cpu_to_le32(dlast_sga); tcd->biter = cpu_to_le16(EDMA_TCD_BITER_BITER(biter)); if (major_int) @@ -549,4 +547,52 @@ void fsl_edma_cleanup_vchan(struct dma_device *dmadev) } EXPORT_SYMBOL_GPL(fsl_edma_cleanup_vchan); +/* + * On the 32 channels Vybrid/mpc577x edma version (here called "v1"), + * register offsets are different compared to ColdFire mcf5441x 64 channels + * edma (here called "v2"). + * + * This function sets up register offsets as per proper declared version + * so must be called in xxx_edma_probe() just after setting the + * edma "version" and "membase" appropriately. + */ +void fsl_edma_setup_regs(struct fsl_edma_engine *edma) +{ + edma->regs.cr = edma->membase + EDMA_CR; + edma->regs.es = edma->membase + EDMA_ES; + edma->regs.erql = edma->membase + EDMA_ERQ; + edma->regs.eeil = edma->membase + EDMA_EEI; + + edma->regs.serq = edma->membase + ((edma->version == v1) ? + EDMA_SERQ : EDMA64_SERQ); + edma->regs.cerq = edma->membase + ((edma->version == v1) ? + EDMA_CERQ : EDMA64_CERQ); + edma->regs.seei = edma->membase + ((edma->version == v1) ? + EDMA_SEEI : EDMA64_SEEI); + edma->regs.ceei = edma->membase + ((edma->version == v1) ? + EDMA_CEEI : EDMA64_CEEI); + edma->regs.cint = edma->membase + ((edma->version == v1) ? + EDMA_CINT : EDMA64_CINT); + edma->regs.cerr = edma->membase + ((edma->version == v1) ? + EDMA_CERR : EDMA64_CERR); + edma->regs.ssrt = edma->membase + ((edma->version == v1) ? + EDMA_SSRT : EDMA64_SSRT); + edma->regs.cdne = edma->membase + ((edma->version == v1) ? + EDMA_CDNE : EDMA64_CDNE); + edma->regs.intl = edma->membase + ((edma->version == v1) ? + EDMA_INTR : EDMA64_INTL); + edma->regs.errl = edma->membase + ((edma->version == v1) ? + EDMA_ERR : EDMA64_ERRL); + + if (edma->version == v2) { + edma->regs.erqh = edma->membase + EDMA64_ERQH; + edma->regs.eeih = edma->membase + EDMA64_EEIH; + edma->regs.errh = edma->membase + EDMA64_ERRH; + edma->regs.inth = edma->membase + EDMA64_INTH; + } + + edma->regs.tcd = edma->membase + EDMA_TCD; +} +EXPORT_SYMBOL_GPL(fsl_edma_setup_regs); + MODULE_LICENSE("GPL v2"); -- cgit v1.2.3