From 2a0fae025e56afbe38441d411f57667b08f44d0e Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 18 Mar 2016 16:24:44 +0200 Subject: [PATCH] dmaengine: dw: set LMS field in descriptors The LMS field indicates from which master the descriptor is to be read. This patch assumes this is always the same as the memory side in a peripheral transfer which is true for all known systems. Signed-off-by: Mans Rullgard Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 26 ++++++++++++++------------ drivers/dma/dw/regs.h | 4 ++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index be48051502aa..23bb460fff6a 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -217,6 +217,7 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) { struct dw_dma *dw = to_dw_dma(dwc->chan.device); + u8 lms = DWC_LLP_LMS(dwc->m_master); unsigned long was_soft_llp; /* ASSERT: channel is idle */ @@ -252,9 +253,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) dwc_initialize(dwc); - channel_writel(dwc, LLP, first->txd.phys); - channel_writel(dwc, CTL_LO, - DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); + channel_writel(dwc, LLP, first->txd.phys | lms); + channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); channel_writel(dwc, CTL_HI, 0); channel_set_bit(dw, CH_EN, dwc->mask); } @@ -418,7 +418,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) dwc->residue = desc->total_len; /* Check first descriptors addr */ - if (desc->txd.phys == llp) { + if (desc->txd.phys == DWC_LLP_LOC(llp)) { spin_unlock_irqrestore(&dwc->lock, flags); return; } @@ -705,6 +705,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, unsigned int dst_width; unsigned int data_width; u32 ctllo; + u8 lms = DWC_LLP_LMS(dwc->m_master); dev_vdbg(chan2dev(chan), "%s: d%pad s%pad l0x%zx f0x%lx\n", __func__, @@ -747,7 +748,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, if (!first) { first = desc; } else { - lli_write(prev, llp, desc->txd.phys); + lli_write(prev, llp, desc->txd.phys | lms); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; @@ -779,6 +780,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, struct dw_desc *prev; struct dw_desc *first; u32 ctllo; + u8 lms = DWC_LLP_LMS(dwc->m_master); dma_addr_t reg; unsigned int reg_width; unsigned int mem_width; @@ -843,7 +845,7 @@ slave_sg_todev_fill_desc: if (!first) { first = desc; } else { - lli_write(prev, llp, desc->txd.phys); + lli_write(prev, llp, desc->txd.phys | lms); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; @@ -898,7 +900,7 @@ slave_sg_fromdev_fill_desc: if (!first) { first = desc; } else { - lli_write(prev, llp, desc->txd.phys); + lli_write(prev, llp, desc->txd.phys | lms); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; @@ -1330,6 +1332,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, struct dw_cyclic_desc *retval = NULL; struct dw_desc *desc; struct dw_desc *last = NULL; + u8 lms = DWC_LLP_LMS(dwc->m_master); unsigned long was_cyclic; unsigned int reg_width; unsigned int periods; @@ -1438,13 +1441,13 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, cdesc->desc[i] = desc; if (last) - lli_write(last, llp, desc->txd.phys); + lli_write(last, llp, desc->txd.phys | lms); last = desc; } /* Let's make a cyclic list */ - lli_write(last, llp, cdesc->desc[0]->txd.phys); + lli_write(last, llp, cdesc->desc[0]->txd.phys | lms); dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf %pad len %zu period %zu periods %d\n", @@ -1646,9 +1649,8 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dwc->block_size = pdata->block_size; /* Check if channel supports multi block transfer */ - channel_writel(dwc, LLP, 0xfffffffc); - dwc->nollp = - (channel_readl(dwc, LLP) & 0xfffffffc) == 0; + channel_writel(dwc, LLP, DWC_LLP_LOC(0xffffffff)); + dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0; channel_writel(dwc, LLP, 0); } } diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 6571100a07e4..59d6cec01dca 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -143,6 +143,10 @@ enum dw_dma_msize { DW_DMA_MSIZE_256, }; +/* Bitfields in LLP */ +#define DWC_LLP_LMS(x) ((x) & 3) /* list master select */ +#define DWC_LLP_LOC(x) ((x) & ~3) /* next lli */ + /* Bitfields in CTL_LO */ #define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ #define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ -- 2.39.5