dmaengine: fsl-edma: move tcd into struct fsl_dma_chan

Relocates the tcd into the fsl_dma_chan structure. This adjustment reduces
the need to reference back to fsl_edma_engine, paving the way for EDMA V3
support.

Unified the edma_writel and edma_writew functions for accessing TCD
(Transfer Control Descriptor) registers. A new macro is added that can
automatically detect whether a 32-bit or 16-bit access should be used
based on the structure field definition. This provide better support
64-bit TCD with future v5 version.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202305271951.gmRobs3a-lkp@intel.com/
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20230821161617.2142561-11-Frank.Li@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Frank Li
2023-08-21 12:16:15 -04:00
committed by Vinod Koul
parent 9b05554c5c
commit 7536f8b371
4 changed files with 42 additions and 28 deletions

View File

@@ -40,8 +40,6 @@
#define EDMA64_ERRH 0x28 #define EDMA64_ERRH 0x28
#define EDMA64_ERRL 0x2c #define EDMA64_ERRL 0x2c
#define EDMA_TCD 0x1000
void fsl_edma_tx_chan_handler(struct fsl_edma_chan *fsl_chan) void fsl_edma_tx_chan_handler(struct fsl_edma_chan *fsl_chan)
{ {
spin_lock(&fsl_chan->vchan.lock); spin_lock(&fsl_chan->vchan.lock);
@@ -285,8 +283,6 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan,
struct virt_dma_desc *vdesc, bool in_progress) struct virt_dma_desc *vdesc, bool in_progress)
{ {
struct fsl_edma_desc *edesc = fsl_chan->edesc; struct fsl_edma_desc *edesc = fsl_chan->edesc;
struct edma_regs *regs = &fsl_chan->edma->regs;
u32 ch = fsl_chan->vchan.chan.chan_id;
enum dma_transfer_direction dir = edesc->dirn; enum dma_transfer_direction dir = edesc->dirn;
dma_addr_t cur_addr, dma_addr; dma_addr_t cur_addr, dma_addr;
size_t len, size; size_t len, size;
@@ -301,9 +297,9 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan,
return len; return len;
if (dir == DMA_MEM_TO_DEV) if (dir == DMA_MEM_TO_DEV)
cur_addr = edma_readl(fsl_chan->edma, &regs->tcd[ch].saddr); cur_addr = edma_read_tcdreg(fsl_chan, saddr);
else else
cur_addr = edma_readl(fsl_chan->edma, &regs->tcd[ch].daddr); cur_addr = edma_read_tcdreg(fsl_chan, daddr);
/* figure out the finished and calculate the residue */ /* figure out the finished and calculate the residue */
for (i = 0; i < fsl_chan->edesc->n_tcds; i++) { for (i = 0; i < fsl_chan->edesc->n_tcds; i++) {
@@ -358,9 +354,6 @@ enum dma_status fsl_edma_tx_status(struct dma_chan *chan,
static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan, static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
struct fsl_edma_hw_tcd *tcd) struct fsl_edma_hw_tcd *tcd)
{ {
struct fsl_edma_engine *edma = fsl_chan->edma;
struct edma_regs *regs = &fsl_chan->edma->regs;
u32 ch = fsl_chan->vchan.chan.chan_id;
u16 csr = 0; u16 csr = 0;
/* /*
@@ -369,23 +362,22 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
* big- or little-endian obeying the eDMA engine model endian, * big- or little-endian obeying the eDMA engine model endian,
* and this is performed from specific edma_write functions * and this is performed from specific edma_write functions
*/ */
edma_writew(edma, 0, &regs->tcd[ch].csr); edma_write_tcdreg(fsl_chan, 0, csr);
edma_writel(edma, (s32)tcd->saddr, &regs->tcd[ch].saddr); edma_write_tcdreg(fsl_chan, tcd->saddr, saddr);
edma_writel(edma, (s32)tcd->daddr, &regs->tcd[ch].daddr); edma_write_tcdreg(fsl_chan, tcd->daddr, daddr);
edma_writew(edma, (s16)tcd->attr, &regs->tcd[ch].attr); edma_write_tcdreg(fsl_chan, tcd->attr, attr);
edma_writew(edma, tcd->soff, &regs->tcd[ch].soff); edma_write_tcdreg(fsl_chan, tcd->soff, soff);
edma_writel(edma, (s32)tcd->nbytes, &regs->tcd[ch].nbytes); edma_write_tcdreg(fsl_chan, tcd->nbytes, nbytes);
edma_writel(edma, (s32)tcd->slast, &regs->tcd[ch].slast); edma_write_tcdreg(fsl_chan, tcd->slast, slast);
edma_writew(edma, (s16)tcd->citer, &regs->tcd[ch].citer); edma_write_tcdreg(fsl_chan, tcd->citer, citer);
edma_writew(edma, (s16)tcd->biter, &regs->tcd[ch].biter); edma_write_tcdreg(fsl_chan, tcd->biter, biter);
edma_writew(edma, (s16)tcd->doff, &regs->tcd[ch].doff); edma_write_tcdreg(fsl_chan, tcd->doff, doff);
edma_writel(edma, (s32)tcd->dlast_sga, edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga);
&regs->tcd[ch].dlast_sga);
if (fsl_chan->is_sw) { if (fsl_chan->is_sw) {
csr = le16_to_cpu(tcd->csr); csr = le16_to_cpu(tcd->csr);
@@ -393,7 +385,7 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
tcd->csr = cpu_to_le16(csr); tcd->csr = cpu_to_le16(csr);
} }
edma_writew(edma, (s16)tcd->csr, &regs->tcd[ch].csr); edma_write_tcdreg(fsl_chan, tcd->csr, csr);
} }
static inline static inline
@@ -736,8 +728,6 @@ void fsl_edma_setup_regs(struct fsl_edma_engine *edma)
edma->regs.errh = edma->membase + EDMA64_ERRH; edma->regs.errh = edma->membase + EDMA64_ERRH;
edma->regs.inth = edma->membase + EDMA64_INTH; edma->regs.inth = edma->membase + EDMA64_INTH;
} }
edma->regs.tcd = edma->membase + EDMA_TCD;
} }
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@@ -48,6 +48,8 @@
#define DMAMUX_NR 2 #define DMAMUX_NR 2
#define EDMA_TCD 0x1000
#define FSL_EDMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ #define FSL_EDMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
@@ -93,7 +95,6 @@ struct edma_regs {
void __iomem *intl; void __iomem *intl;
void __iomem *errh; void __iomem *errh;
void __iomem *errl; void __iomem *errl;
struct fsl_edma_hw_tcd __iomem *tcd;
}; };
struct fsl_edma_sw_tcd { struct fsl_edma_sw_tcd {
@@ -117,6 +118,7 @@ struct fsl_edma_chan {
u32 dma_dev_size; u32 dma_dev_size;
enum dma_data_direction dma_dir; enum dma_data_direction dma_dir;
char chan_name[32]; char chan_name[32];
struct fsl_edma_hw_tcd __iomem *tcd;
}; };
struct fsl_edma_desc { struct fsl_edma_desc {
@@ -156,6 +158,16 @@ struct fsl_edma_engine {
struct fsl_edma_chan chans[]; struct fsl_edma_chan chans[];
}; };
#define edma_read_tcdreg(chan, __name) \
(sizeof(chan->tcd->__name) == sizeof(u32) ? \
edma_readl(chan->edma, &chan->tcd->__name) : \
edma_readw(chan->edma, &chan->tcd->__name))
#define edma_write_tcdreg(chan, val, __name) \
(sizeof(chan->tcd->__name) == sizeof(u32) ? \
edma_writel(chan->edma, (u32 __force)val, &chan->tcd->__name) : \
edma_writew(chan->edma, (u16 __force)val, &chan->tcd->__name))
/* /*
* R/W functions for big- or little-endian registers: * R/W functions for big- or little-endian registers:
* The eDMA controller's endian is independent of the CPU core's endian. * The eDMA controller's endian is independent of the CPU core's endian.
@@ -170,6 +182,14 @@ static inline u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
return ioread32(addr); return ioread32(addr);
} }
static inline u16 edma_readw(struct fsl_edma_engine *edma, void __iomem *addr)
{
if (edma->big_endian)
return ioread16be(addr);
else
return ioread16(addr);
}
static inline void edma_writeb(struct fsl_edma_engine *edma, static inline void edma_writeb(struct fsl_edma_engine *edma,
u8 val, void __iomem *addr) u8 val, void __iomem *addr)
{ {

View File

@@ -320,9 +320,11 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_chan->idle = true; fsl_chan->idle = true;
fsl_chan->dma_dir = DMA_NONE; fsl_chan->dma_dir = DMA_NONE;
fsl_chan->vchan.desc_free = fsl_edma_free_desc; fsl_chan->vchan.desc_free = fsl_edma_free_desc;
fsl_chan->tcd = fsl_edma->membase + EDMA_TCD
+ i * sizeof(struct fsl_edma_hw_tcd);
vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev); vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
edma_writew(fsl_edma, 0x0, &regs->tcd[i].csr); edma_write_tcdreg(fsl_chan, 0, csr);
fsl_edma_chan_mux(fsl_chan, 0, false); fsl_edma_chan_mux(fsl_chan, 0, false);
} }
@@ -430,7 +432,7 @@ static int fsl_edma_resume_early(struct device *dev)
for (i = 0; i < fsl_edma->n_chans; i++) { for (i = 0; i < fsl_edma->n_chans; i++) {
fsl_chan = &fsl_edma->chans[i]; fsl_chan = &fsl_edma->chans[i];
fsl_chan->pm_state = RUNNING; fsl_chan->pm_state = RUNNING;
edma_writew(fsl_edma, 0x0, &regs->tcd[i].csr); edma_write_tcdreg(fsl_chan, 0, csr);
if (fsl_chan->slave_id != 0) if (fsl_chan->slave_id != 0)
fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id, true); fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id, true);
} }

View File

@@ -199,7 +199,9 @@ static int mcf_edma_probe(struct platform_device *pdev)
mcf_chan->dma_dir = DMA_NONE; mcf_chan->dma_dir = DMA_NONE;
mcf_chan->vchan.desc_free = fsl_edma_free_desc; mcf_chan->vchan.desc_free = fsl_edma_free_desc;
vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev); vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev);
iowrite32(0x0, &regs->tcd[i].csr); mcf_chan->tcd = mcf_edma->membase + EDMA_TCD
+ i * sizeof(struct fsl_edma_hw_tcd);
iowrite32(0x0, &mcf_chan->tcd->csr);
} }
iowrite32(~0, regs->inth); iowrite32(~0, regs->inth);