dmaengine: dw: set LMS field in descriptors
authorMans Rullgard <mans@mansr.com>
Fri, 18 Mar 2016 14:24:44 +0000 (16:24 +0200)
committerVinod Koul <vinod.koul@intel.com>
Wed, 13 Apr 2016 16:06:10 +0000 (21:36 +0530)
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 <mans@mansr.com>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
drivers/dma/dw/core.c
drivers/dma/dw/regs.h

index be48051502aa9a4c92348dcf01625ac4269d58e2..23bb460fff6a0fcef747f2a5665d68bb971ebe19 100644 (file)
@@ -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);
                }
        }
index 6571100a07e490520ab8434810c9d3b932cd0579..59d6cec01dca6ca5331130e4a72c5a875aeb1598 100644 (file)
@@ -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 */