From 7414a1b8b2b99093d6a271a1220557e87dc1ae94 Mon Sep 17 00:00:00 2001 From: Rajeev KUMAR Date: Wed, 1 Feb 2012 16:12:17 +0530 Subject: dmaengine/dw_dmac: Hibernation support in dw_dmac The suspend and resume implementation is through dev_pm_ops in dmac. So in order to support hibernation, freeze, thaw, restore and poweroff features are required. Signed-off-by: Rajeev Kumar Acked-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 9b592b02b5f4..3a3d7edcd553 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1562,6 +1562,10 @@ static int dw_resume_noirq(struct device *dev) static const struct dev_pm_ops dw_dev_pm_ops = { .suspend_noirq = dw_suspend_noirq, .resume_noirq = dw_resume_noirq, + .freeze_noirq = dw_suspend_noirq, + .thaw_noirq = dw_resume_noirq, + .restore_noirq = dw_resume_noirq, + .poweroff_noirq = dw_suspend_noirq, }; static struct platform_driver dw_driver = { -- cgit v1.2.2 From e8d9f875c9b02bb56ba3bb44834ae81ba0e8efbc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Feb 2012 16:12:21 +0530 Subject: dmaengine/dw_dmac: Don't use magic number for total number of channels Total number of channels is passed in pdata->nr_channels variable, thus we must not use magic number '7' for total number of channels. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 3a3d7edcd553..157739423734 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1432,7 +1432,7 @@ static int __init dw_probe(struct platform_device *pdev) /* 7 is highest priority & 0 is lowest. */ if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) - dwc->priority = 7 - i; + dwc->priority = pdata->nr_channels - i - 1; else dwc->priority = i; -- cgit v1.2.2 From 6c618c9de5f2b4b43c30c6203869620bec6ed929 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Feb 2012 16:12:22 +0530 Subject: dmaengine/dw_dmac: Use dev_get_platdata() instead of accessing dev directly Use already defined function dev_get_platdata() instead of accessing pdev->dev.data. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 157739423734..f3aecb3c0343 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1369,7 +1369,7 @@ static int __init dw_probe(struct platform_device *pdev) int err; int i; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) return -EINVAL; -- cgit v1.2.2 From ff7b05f29fd4db810021d905e2dad95ab4fe2984 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Feb 2012 16:12:23 +0530 Subject: dmaengine/dw_dmac: Don't handle block interrupts Block interrupts give interrupt on completion of every LLI, which is actually too much interrupts. This is just not required for current functioning of dw_dmac. So, just don't handle them at all. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index f3aecb3c0343..5d7b199208d9 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -192,7 +192,6 @@ static void dwc_initialize(struct dw_dma_chan *dwc) /* Enable interrupts */ channel_set_bit(dw, MASK.XFER, dwc->mask); - channel_set_bit(dw, MASK.BLOCK, dwc->mask); channel_set_bit(dw, MASK.ERROR, dwc->mask); dwc->initialized = true; @@ -329,12 +328,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) unsigned long flags; spin_lock_irqsave(&dwc->lock, flags); - /* - * Clear block interrupt flag before scanning so that we don't - * miss any, and read LLP before RAW_XFER to ensure it is - * valid if we decide to scan the list. - */ - dma_writel(dw, CLEAR.BLOCK, dwc->mask); llp = channel_readl(dwc, LLP); status_xfer = dma_readl(dw, RAW.XFER); @@ -470,17 +463,16 @@ EXPORT_SYMBOL(dw_dma_get_dst_addr); /* called with dwc->lock held and all DMAC interrupts disabled */ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, - u32 status_block, u32 status_err, u32 status_xfer) + u32 status_err, u32 status_xfer) { unsigned long flags; - if (status_block & dwc->mask) { + if (dwc->mask) { void (*callback)(void *param); void *callback_param; dev_vdbg(chan2dev(&dwc->chan), "new cyclic period llp 0x%08x\n", channel_readl(dwc, LLP)); - dma_writel(dw, CLEAR.BLOCK, dwc->mask); callback = dwc->cdesc->period_callback; callback_param = dwc->cdesc->period_callback_param; @@ -520,7 +512,6 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, channel_writel(dwc, CTL_LO, 0); channel_writel(dwc, CTL_HI, 0); - dma_writel(dw, CLEAR.BLOCK, dwc->mask); dma_writel(dw, CLEAR.ERROR, dwc->mask); dma_writel(dw, CLEAR.XFER, dwc->mask); @@ -537,36 +528,29 @@ static void dw_dma_tasklet(unsigned long data) { struct dw_dma *dw = (struct dw_dma *)data; struct dw_dma_chan *dwc; - u32 status_block; u32 status_xfer; u32 status_err; int i; - status_block = dma_readl(dw, RAW.BLOCK); status_xfer = dma_readl(dw, RAW.XFER); status_err = dma_readl(dw, RAW.ERROR); - dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n", - status_block, status_err); + dev_vdbg(dw->dma.dev, "tasklet: status_err=%x\n", status_err); for (i = 0; i < dw->dma.chancnt; i++) { dwc = &dw->chan[i]; if (test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) - dwc_handle_cyclic(dw, dwc, status_block, status_err, - status_xfer); + dwc_handle_cyclic(dw, dwc, status_err, status_xfer); else if (status_err & (1 << i)) dwc_handle_error(dw, dwc); - else if ((status_block | status_xfer) & (1 << i)) + else if (status_xfer & (1 << i)) dwc_scan_descriptors(dw, dwc); } /* - * Re-enable interrupts. Block Complete interrupts are only - * enabled if the INT_EN bit in the descriptor is set. This - * will trigger a scan before the whole list is done. + * Re-enable interrupts. */ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask); channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask); } @@ -583,7 +567,6 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id) * softirq handler. */ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); status = dma_readl(dw, STATUS_INT); @@ -594,7 +577,6 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id) /* Try to recover */ channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1); - channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1); channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1); channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1); channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1); @@ -1068,7 +1050,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) /* Disable interrupts */ channel_clear_bit(dw, MASK.XFER, dwc->mask); - channel_clear_bit(dw, MASK.BLOCK, dwc->mask); channel_clear_bit(dw, MASK.ERROR, dwc->mask); spin_unlock_irqrestore(&dwc->lock, flags); @@ -1120,7 +1101,6 @@ int dw_dma_cyclic_start(struct dma_chan *chan) return -EBUSY; } - dma_writel(dw, CLEAR.BLOCK, dwc->mask); dma_writel(dw, CLEAR.ERROR, dwc->mask); dma_writel(dw, CLEAR.XFER, dwc->mask); @@ -1322,7 +1302,6 @@ void dw_dma_cyclic_free(struct dma_chan *chan) while (dma_readl(dw, CH_EN) & dwc->mask) cpu_relax(); - dma_writel(dw, CLEAR.BLOCK, dwc->mask); dma_writel(dw, CLEAR.ERROR, dwc->mask); dma_writel(dw, CLEAR.XFER, dwc->mask); @@ -1347,7 +1326,6 @@ static void dw_dma_off(struct dw_dma *dw) dma_writel(dw, CFG, 0); channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask); channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask); channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); @@ -1449,13 +1427,11 @@ static int __init dw_probe(struct platform_device *pdev) /* Clear/disable all interrupts on all channels. */ dma_writel(dw, CLEAR.XFER, dw->all_chan_mask); - dma_writel(dw, CLEAR.BLOCK, dw->all_chan_mask); dma_writel(dw, CLEAR.SRC_TRAN, dw->all_chan_mask); dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask); dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask); channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask); channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask); channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask); -- cgit v1.2.2 From 6bc711f6bd9dd393e1f9bbae354906affcd02aa5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Feb 2012 16:12:25 +0530 Subject: dmaengine/dw_dmac: Add 64 bit access width support for slave xfers on mem side 64 bit transfers are possible on both sides in slave transfers (memory as well as peripherals). This patch adds support for it memory side 64 bit transfers. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 5d7b199208d9..9f4310f013f5 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -749,8 +749,14 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_phys(sg); len = sg_dma_len(sg); - mem_width = 2; - if (unlikely(mem & 3 || len & 3)) + + if (!((mem | len) & 7)) + mem_width = 3; + else if (!((mem | len) & 3)) + mem_width = 2; + else if (!((mem | len) & 1)) + mem_width = 1; + else mem_width = 0; slave_sg_todev_fill_desc: @@ -807,8 +813,14 @@ slave_sg_todev_fill_desc: mem = sg_phys(sg); len = sg_dma_len(sg); - mem_width = 2; - if (unlikely(mem & 3 || len & 3)) + + if (!((mem | len) & 7)) + mem_width = 3; + else if (!((mem | len) & 3)) + mem_width = 2; + else if (!((mem | len) & 1)) + mem_width = 1; + else mem_width = 0; slave_sg_fromdev_fill_desc: -- cgit v1.2.2 From 327e6970258618da810f72e86cf2a8b803927e14 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Feb 2012 16:12:26 +0530 Subject: dmaengine/dw_dmac: Add support for DMA_SLAVE_CONFIG This patch adds support for DMA_SLAVE_CONFIG in dwc DMAC controller. Fields in struct dw_dma_slave for passing similar data are preserved in this patch untill all existing users are fixed. That will be handled later in this patchset. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 119 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 29 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 9f4310f013f5..0e4b5c6a2f86 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -9,6 +9,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -33,19 +34,23 @@ * which does not support descriptor writeback. */ -#define DWC_DEFAULT_CTLLO(private) ({ \ - struct dw_dma_slave *__slave = (private); \ - int dms = __slave ? __slave->dst_master : 0; \ - int sms = __slave ? __slave->src_master : 1; \ - u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \ - u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \ +#define DWC_DEFAULT_CTLLO(_chan) ({ \ + struct dw_dma_slave *__slave = (_chan->private); \ + struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ + struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ + int _dms = __slave ? __slave->dst_master : 0; \ + int _sms = __slave ? __slave->src_master : 1; \ + u8 _smsize = __slave ? _sconfig->src_maxburst : \ + DW_DMA_MSIZE_16; \ + u8 _dmsize = __slave ? _sconfig->dst_maxburst : \ + DW_DMA_MSIZE_16; \ \ - (DWC_CTLL_DST_MSIZE(dmsize) \ - | DWC_CTLL_SRC_MSIZE(smsize) \ + (DWC_CTLL_DST_MSIZE(_dmsize) \ + | DWC_CTLL_SRC_MSIZE(_smsize) \ | DWC_CTLL_LLP_D_EN \ | DWC_CTLL_LLP_S_EN \ - | DWC_CTLL_DMS(dms) \ - | DWC_CTLL_SMS(sms)); \ + | DWC_CTLL_DMS(_dms) \ + | DWC_CTLL_SMS(_sms)); \ }) /* @@ -656,7 +661,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, else src_width = dst_width = 0; - ctllo = DWC_DEFAULT_CTLLO(chan->private) + ctllo = DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_DST_WIDTH(dst_width) | DWC_CTLL_SRC_WIDTH(src_width) | DWC_CTLL_DST_INC @@ -717,6 +722,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma_slave *dws = chan->private; + struct dma_slave_config *sconfig = &dwc->dma_sconfig; struct dw_desc *prev; struct dw_desc *first; u32 ctllo; @@ -732,17 +738,20 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (unlikely(!dws || !sg_len)) return NULL; - reg_width = dws->reg_width; prev = first = NULL; switch (direction) { case DMA_MEM_TO_DEV: - ctllo = (DWC_DEFAULT_CTLLO(chan->private) + reg_width = __fls(sconfig->dst_addr_width); + reg = sconfig->dst_addr; + ctllo = (DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_FIX - | DWC_CTLL_SRC_INC - | DWC_CTLL_FC(dws->fc)); - reg = dws->tx_reg; + | DWC_CTLL_SRC_INC); + + ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : + DWC_CTLL_FC(DW_DMA_FC_D_M2P); + for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; u32 len, dlen, mem; @@ -800,13 +809,16 @@ slave_sg_todev_fill_desc: } break; case DMA_DEV_TO_MEM: - ctllo = (DWC_DEFAULT_CTLLO(chan->private) + reg_width = __fls(sconfig->src_addr_width); + reg = sconfig->src_addr; + ctllo = (DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_INC - | DWC_CTLL_SRC_FIX - | DWC_CTLL_FC(dws->fc)); + | DWC_CTLL_SRC_FIX); + + ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : + DWC_CTLL_FC(DW_DMA_FC_D_P2M); - reg = dws->rx_reg; for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; u32 len, dlen, mem; @@ -884,6 +896,39 @@ err_desc_get: return NULL; } +/* + * Fix sconfig's burst size according to dw_dmac. We need to convert them as: + * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. + * + * NOTE: burst size 2 is not supported by controller. + * + * This can be done by finding least significant bit set: n & (n - 1) + */ +static inline void convert_burst(u32 *maxburst) +{ + if (*maxburst > 1) + *maxburst = fls(*maxburst) - 2; + else + *maxburst = 0; +} + +static int +set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + + /* Check if it is chan is configured for slave transfers */ + if (!chan->private) + return -EINVAL; + + memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); + + convert_burst(&dwc->dma_sconfig.src_maxburst); + convert_burst(&dwc->dma_sconfig.dst_maxburst); + + return 0; +} + static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { @@ -933,8 +978,11 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, /* Flush all pending and queued descriptors */ list_for_each_entry_safe(desc, _desc, &list, desc_node) dwc_descriptor_complete(dwc, desc, false); - } else + } else if (cmd == DMA_SLAVE_CONFIG) { + return set_runtime_config(chan, (struct dma_slave_config *)arg); + } else { return -ENXIO; + } return 0; } @@ -1167,11 +1215,11 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, enum dma_transfer_direction direction) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dma_slave_config *sconfig = &dwc->dma_sconfig; struct dw_cyclic_desc *cdesc; struct dw_cyclic_desc *retval = NULL; struct dw_desc *desc; struct dw_desc *last = NULL; - struct dw_dma_slave *dws = chan->private; unsigned long was_cyclic; unsigned int reg_width; unsigned int periods; @@ -1195,7 +1243,12 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, } retval = ERR_PTR(-EINVAL); - reg_width = dws->reg_width; + + if (direction == DMA_MEM_TO_DEV) + reg_width = __ffs(sconfig->dst_addr_width); + else + reg_width = __ffs(sconfig->src_addr_width); + periods = buf_len / period_len; /* Check for too big/unaligned periods and unaligned DMA buffer. */ @@ -1228,26 +1281,34 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, switch (direction) { case DMA_MEM_TO_DEV: - desc->lli.dar = dws->tx_reg; + desc->lli.dar = sconfig->dst_addr; desc->lli.sar = buf_addr + (period_len * i); - desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) + desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_FIX | DWC_CTLL_SRC_INC - | DWC_CTLL_FC(dws->fc) | DWC_CTLL_INT_EN); + + desc->lli.ctllo |= sconfig->device_fc ? + DWC_CTLL_FC(DW_DMA_FC_P_M2P) : + DWC_CTLL_FC(DW_DMA_FC_D_M2P); + break; case DMA_DEV_TO_MEM: desc->lli.dar = buf_addr + (period_len * i); - desc->lli.sar = dws->rx_reg; - desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) + desc->lli.sar = sconfig->src_addr; + desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_INC | DWC_CTLL_SRC_FIX - | DWC_CTLL_FC(dws->fc) | DWC_CTLL_INT_EN); + + desc->lli.ctllo |= sconfig->device_fc ? + DWC_CTLL_FC(DW_DMA_FC_P_P2M) : + DWC_CTLL_FC(DW_DMA_FC_D_P2M); + break; default: break; -- cgit v1.2.2 From 4d4e58de32a192fea65ab84509d17d199bd291c8 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Tue, 6 Mar 2012 22:34:06 +0000 Subject: dmaengine: move last completed cookie into generic dma_chan structure Every DMA engine implementation declares a last completed dma cookie in their private dma channel structures. This is pointless, and forces driver specific code. Move this out into the common dma_chan structure. Signed-off-by: Russell King Tested-by: Linus Walleij Reviewed-by: Linus Walleij Acked-by: Jassi Brar [imx-sdma.c & mxs-dma.c] Tested-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 0e4b5c6a2f86..5bd23006ff4a 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -249,7 +249,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie); spin_lock_irqsave(&dwc->lock, flags); - dwc->completed = txd->cookie; + dwc->chan.completed_cookie = txd->cookie; if (callback_required) { callback = txd->callback; param = txd->callback_param; @@ -997,14 +997,14 @@ dwc_tx_status(struct dma_chan *chan, dma_cookie_t last_complete; int ret; - last_complete = dwc->completed; + last_complete = chan->completed_cookie; last_used = chan->cookie; ret = dma_async_is_complete(cookie, last_complete, last_used); if (ret != DMA_SUCCESS) { dwc_scan_descriptors(to_dw_dma(chan->device), dwc); - last_complete = dwc->completed; + last_complete = chan->completed_cookie; last_used = chan->cookie; ret = dma_async_is_complete(cookie, last_complete, last_used); @@ -1046,7 +1046,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) return -EIO; } - dwc->completed = chan->cookie = 1; + chan->completed_cookie = chan->cookie = 1; /* * NOTE: some controllers may have additional features that we @@ -1474,7 +1474,7 @@ static int __init dw_probe(struct platform_device *pdev) struct dw_dma_chan *dwc = &dw->chan[i]; dwc->chan.device = &dw->dma; - dwc->chan.cookie = dwc->completed = 1; + dwc->chan.cookie = dwc->chan.completed_cookie = 1; if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING) list_add_tail(&dwc->chan.device_node, &dw->dma.channels); -- cgit v1.2.2 From d2ebfb335b0426deb1a4fb14e4e926d81ecd8235 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Tue, 6 Mar 2012 22:34:26 +0000 Subject: dmaengine: add private header file Add a local private header file to contain definitions and declarations which should only be used by DMA engine drivers. We also fix linux/dmaengine.h to use LINUX_DMAENGINE_H to guard against multiple inclusion. Signed-off-by: Russell King Tested-by: Linus Walleij Reviewed-by: Linus Walleij Acked-by: Jassi Brar [imx-sdma.c & mxs-dma.c] Tested-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 5bd23006ff4a..b279e1920725 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -23,6 +23,7 @@ #include #include "dw_dmac_regs.h" +#include "dmaengine.h" /* * This supports the Synopsys "DesignWare AHB Central DMA Controller", -- cgit v1.2.2 From 884485e1f12dcd39390f042e772cdbefc9ebb750 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Tue, 6 Mar 2012 22:34:46 +0000 Subject: dmaengine: consolidate assignment of DMA cookies Everyone deals with assigning DMA cookies in the same way (it's part of the API so they should be), so lets consolidate the common code into a helper function to avoid this duplication. Signed-off-by: Russell King Tested-by: Linus Walleij Reviewed-by: Linus Walleij Acked-by: Jassi Brar [imx-sdma.c & mxs-dma.c] Tested-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index b279e1920725..3a4ca67ace02 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -157,21 +157,6 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) } } -/* Called with dwc->lock held and bh disabled */ -static dma_cookie_t -dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc) -{ - dma_cookie_t cookie = dwc->chan.cookie; - - if (++cookie < 0) - cookie = 1; - - dwc->chan.cookie = cookie; - desc->txd.cookie = cookie; - - return cookie; -} - static void dwc_initialize(struct dw_dma_chan *dwc) { struct dw_dma *dw = to_dw_dma(dwc->chan.device); @@ -603,7 +588,7 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) unsigned long flags; spin_lock_irqsave(&dwc->lock, flags); - cookie = dwc_assign_cookie(dwc, desc); + cookie = dma_cookie_assign(tx); /* * REVISIT: We should attempt to chain as many descriptors as -- cgit v1.2.2 From f7fbce07c6ce26a25b4e0cb5f241c361fde87901 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Tue, 6 Mar 2012 22:35:07 +0000 Subject: dmaengine: provide a common function for completing a dma descriptor Provide a common function to do the cookie mechanics for completing a DMA descriptor. Signed-off-by: Russell King Tested-by: Linus Walleij Reviewed-by: Linus Walleij Acked-by: Jassi Brar [imx-sdma.c & mxs-dma.c] Tested-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 3a4ca67ace02..12ea60b2a1be 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -235,7 +235,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie); spin_lock_irqsave(&dwc->lock, flags); - dwc->chan.completed_cookie = txd->cookie; + dma_cookie_complete(txd); if (callback_required) { callback = txd->callback; param = txd->callback_param; -- cgit v1.2.2 From 96a2af41c78b1fbb1f567a3486bdc63f7b31c5fd Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Tue, 6 Mar 2012 22:35:27 +0000 Subject: dmaengine: consolidate tx_status functions Now that we have the completed cookie in the dma_chan structure, we can consolidate the tx_status functions by providing a function to set the txstate structure and returning the DMA status. We also provide a separate helper to set the residue for cookies which are still in progress. Signed-off-by: Russell King Tested-by: Linus Walleij Reviewed-by: Linus Walleij Acked-by: Jassi Brar [imx-sdma.c & mxs-dma.c] Tested-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 12ea60b2a1be..33bde5da850d 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -979,28 +979,17 @@ dwc_tx_status(struct dma_chan *chan, struct dma_tx_state *txstate) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); - dma_cookie_t last_used; - dma_cookie_t last_complete; - int ret; + enum dma_status ret; - last_complete = chan->completed_cookie; - last_used = chan->cookie; - - ret = dma_async_is_complete(cookie, last_complete, last_used); + ret = dma_cookie_status(chan, cookie, txstate); if (ret != DMA_SUCCESS) { dwc_scan_descriptors(to_dw_dma(chan->device), dwc); - last_complete = chan->completed_cookie; - last_used = chan->cookie; - - ret = dma_async_is_complete(cookie, last_complete, last_used); + ret = dma_cookie_status(chan, cookie, txstate); } if (ret != DMA_SUCCESS) - dma_set_tx_state(txstate, last_complete, last_used, - dwc_first_active(dwc)->len); - else - dma_set_tx_state(txstate, last_complete, last_used, 0); + dma_set_residue(txstate, dwc_first_active(dwc)->len); if (dwc->paused) return DMA_PAUSED; -- cgit v1.2.2 From d3ee98cdcd6198ea1cf75c603178acc8a805b69b Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Tue, 6 Mar 2012 22:35:47 +0000 Subject: dmaengine: consolidate initialization of cookies Provide a common function to initialize a channels cookie values. Signed-off-by: Russell King Tested-by: Linus Walleij Reviewed-by: Linus Walleij Acked-by: Jassi Brar [imx-sdma.c & mxs-dma.c] Tested-by: Shawn Guo Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 33bde5da850d..cb173bbdcfdf 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1021,7 +1021,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) return -EIO; } - chan->completed_cookie = chan->cookie = 1; + dma_cookie_init(chan); /* * NOTE: some controllers may have additional features that we @@ -1449,7 +1449,7 @@ static int __init dw_probe(struct platform_device *pdev) struct dw_dma_chan *dwc = &dw->chan[i]; dwc->chan.device = &dw->dma; - dwc->chan.cookie = dwc->chan.completed_cookie = 1; + dma_cookie_init(&dwc->chan); if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING) list_add_tail(&dwc->chan.device_node, &dw->dma.channels); -- cgit v1.2.2 From 185ecb5f4fd43911c35956d4cc7d94a1da30417f Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 8 Mar 2012 15:35:13 -0500 Subject: dmaengine: add context parameter to prep_slave_sg and prep_dma_cyclic Add context parameter to device_prep_slave_sg() and device_prep_dma_cyclic() interfaces to allow passing client/target specific information associated with the data transfer. Modify all affected DMA engine drivers. Signed-off-by: Alexandre Bounine Acked-by: Linus Walleij Acked-by: Felipe Balbi Signed-off-by: Vinod Koul --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/dma/dw_dmac.c') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index cb173bbdcfdf..7439079f5eed 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -704,7 +704,7 @@ err_desc_get: static struct dma_async_tx_descriptor * dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, - unsigned long flags) + unsigned long flags, void *context) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma_slave *dws = chan->private; -- cgit v1.2.2