diff options
author | Vinod Koul <vinod.koul@intel.com> | 2015-02-02 16:55:35 -0800 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-02-02 16:55:35 -0800 |
commit | 2cd6f7928ca42c7744f493e0ae2a4acaf02331a0 (patch) | |
tree | 2051ca01dbfeaa3185df454d874b6c450f540a92 /drivers/dma | |
parent | c914570f28552eb4ed6f016ec7b1db292a7c924b (diff) | |
parent | 5cf5aec5b38a5143883fc5b689bf5c1c8ee48aa3 (diff) |
Merge branch 'topic/slave_caps_device_control_fix_rebased' into for-linus
Diffstat (limited to 'drivers/dma')
44 files changed, 1531 insertions, 1715 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 1364d00881dd..4a5fd245014e 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1386,32 +1386,6 @@ static u32 pl08x_get_cctl(struct pl08x_dma_chan *plchan, return pl08x_cctl(cctl); } -static int dma_set_runtime_config(struct dma_chan *chan, - struct dma_slave_config *config) -{ - struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); - struct pl08x_driver_data *pl08x = plchan->host; - - if (!plchan->slave) - return -EINVAL; - - /* Reject definitely invalid configurations */ - if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || - config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES) - return -EINVAL; - - if (config->device_fc && pl08x->vd->pl080s) { - dev_err(&pl08x->adev->dev, - "%s: PL080S does not support peripheral flow control\n", - __func__); - return -EINVAL; - } - - plchan->cfg = *config; - - return 0; -} - /* * Slave transactions callback to the slave device to allow * synchronization of slave DMA signals with the DMAC enable @@ -1693,20 +1667,71 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic( return vchan_tx_prep(&plchan->vc, &txd->vd, flags); } -static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, - unsigned long arg) +static int pl08x_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); + struct pl08x_driver_data *pl08x = plchan->host; + + if (!plchan->slave) + return -EINVAL; + + /* Reject definitely invalid configurations */ + if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || + config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES) + return -EINVAL; + + if (config->device_fc && pl08x->vd->pl080s) { + dev_err(&pl08x->adev->dev, + "%s: PL080S does not support peripheral flow control\n", + __func__); + return -EINVAL; + } + + plchan->cfg = *config; + + return 0; +} + +static int pl08x_terminate_all(struct dma_chan *chan) { struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); struct pl08x_driver_data *pl08x = plchan->host; unsigned long flags; - int ret = 0; - /* Controls applicable to inactive channels */ - if (cmd == DMA_SLAVE_CONFIG) { - return dma_set_runtime_config(chan, - (struct dma_slave_config *)arg); + spin_lock_irqsave(&plchan->vc.lock, flags); + if (!plchan->phychan && !plchan->at) { + spin_unlock_irqrestore(&plchan->vc.lock, flags); + return 0; } + plchan->state = PL08X_CHAN_IDLE; + + if (plchan->phychan) { + /* + * Mark physical channel as free and free any slave + * signal + */ + pl08x_phy_free(plchan); + } + /* Dequeue jobs and free LLIs */ + if (plchan->at) { + pl08x_desc_free(&plchan->at->vd); + plchan->at = NULL; + } + /* Dequeue jobs not yet fired as well */ + pl08x_free_txd_list(pl08x, plchan); + + spin_unlock_irqrestore(&plchan->vc.lock, flags); + + return 0; +} + +static int pl08x_pause(struct dma_chan *chan) +{ + struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); + unsigned long flags; + /* * Anything succeeds on channels with no physical allocation and * no queued transfers. @@ -1717,42 +1742,35 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, return 0; } - switch (cmd) { - case DMA_TERMINATE_ALL: - plchan->state = PL08X_CHAN_IDLE; + pl08x_pause_phy_chan(plchan->phychan); + plchan->state = PL08X_CHAN_PAUSED; - if (plchan->phychan) { - /* - * Mark physical channel as free and free any slave - * signal - */ - pl08x_phy_free(plchan); - } - /* Dequeue jobs and free LLIs */ - if (plchan->at) { - pl08x_desc_free(&plchan->at->vd); - plchan->at = NULL; - } - /* Dequeue jobs not yet fired as well */ - pl08x_free_txd_list(pl08x, plchan); - break; - case DMA_PAUSE: - pl08x_pause_phy_chan(plchan->phychan); - plchan->state = PL08X_CHAN_PAUSED; - break; - case DMA_RESUME: - pl08x_resume_phy_chan(plchan->phychan); - plchan->state = PL08X_CHAN_RUNNING; - break; - default: - /* Unknown command */ - ret = -ENXIO; - break; + spin_unlock_irqrestore(&plchan->vc.lock, flags); + + return 0; +} + +static int pl08x_resume(struct dma_chan *chan) +{ + struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); + unsigned long flags; + + /* + * Anything succeeds on channels with no physical allocation and + * no queued transfers. + */ + spin_lock_irqsave(&plchan->vc.lock, flags); + if (!plchan->phychan && !plchan->at) { + spin_unlock_irqrestore(&plchan->vc.lock, flags); + return 0; } + pl08x_resume_phy_chan(plchan->phychan); + plchan->state = PL08X_CHAN_RUNNING; + spin_unlock_irqrestore(&plchan->vc.lock, flags); - return ret; + return 0; } bool pl08x_filter_id(struct dma_chan *chan, void *chan_id) @@ -2048,7 +2066,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt; pl08x->memcpy.device_tx_status = pl08x_dma_tx_status; pl08x->memcpy.device_issue_pending = pl08x_issue_pending; - pl08x->memcpy.device_control = pl08x_control; + pl08x->memcpy.device_config = pl08x_config; + pl08x->memcpy.device_pause = pl08x_pause; + pl08x->memcpy.device_resume = pl08x_resume; + pl08x->memcpy.device_terminate_all = pl08x_terminate_all; /* Initialize slave engine */ dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask); @@ -2061,7 +2082,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) pl08x->slave.device_issue_pending = pl08x_issue_pending; pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg; pl08x->slave.device_prep_dma_cyclic = pl08x_prep_dma_cyclic; - pl08x->slave.device_control = pl08x_control; + pl08x->slave.device_config = pl08x_config; + pl08x->slave.device_pause = pl08x_pause; + pl08x->slave.device_resume = pl08x_resume; + pl08x->slave.device_terminate_all = pl08x_terminate_all; /* Get the platform data */ pl08x->pd = dev_get_platdata(&adev->dev); diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index ca9dd2613283..1e1a4c567542 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -42,6 +42,11 @@ #define ATC_DEFAULT_CFG (ATC_FIFOCFG_HALFFIFO) #define ATC_DEFAULT_CTRLB (ATC_SIF(AT_DMA_MEM_IF) \ |ATC_DIF(AT_DMA_MEM_IF)) +#define ATC_DMA_BUSWIDTHS\ + (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\ + BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |\ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) /* * Initial number of descriptors to allocate for each channel. This could @@ -972,11 +977,13 @@ err_out: return NULL; } -static int set_runtime_config(struct dma_chan *chan, - struct dma_slave_config *sconfig) +static int atc_config(struct dma_chan *chan, + struct dma_slave_config *sconfig) { struct at_dma_chan *atchan = to_at_dma_chan(chan); + dev_vdbg(chan2dev(chan), "%s\n", __func__); + /* Check if it is chan is configured for slave transfers */ if (!chan->private) return -EINVAL; @@ -989,9 +996,28 @@ static int set_runtime_config(struct dma_chan *chan, return 0; } +static int atc_pause(struct dma_chan *chan) +{ + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_dma *atdma = to_at_dma(chan->device); + int chan_id = atchan->chan_common.chan_id; + unsigned long flags; -static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, - unsigned long arg) + LIST_HEAD(list); + + dev_vdbg(chan2dev(chan), "%s\n", __func__); + + spin_lock_irqsave(&atchan->lock, flags); + + dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id)); + set_bit(ATC_IS_PAUSED, &atchan->status); + + spin_unlock_irqrestore(&atchan->lock, flags); + + return 0; +} + +static int atc_resume(struct dma_chan *chan) { struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma *atdma = to_at_dma(chan->device); @@ -1000,60 +1026,61 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, LIST_HEAD(list); - dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd); + dev_vdbg(chan2dev(chan), "%s\n", __func__); - if (cmd == DMA_PAUSE) { - spin_lock_irqsave(&atchan->lock, flags); + if (!atc_chan_is_paused(atchan)) + return 0; - dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id)); - set_bit(ATC_IS_PAUSED, &atchan->status); + spin_lock_irqsave(&atchan->lock, flags); - spin_unlock_irqrestore(&atchan->lock, flags); - } else if (cmd == DMA_RESUME) { - if (!atc_chan_is_paused(atchan)) - return 0; + dma_writel(atdma, CHDR, AT_DMA_RES(chan_id)); + clear_bit(ATC_IS_PAUSED, &atchan->status); - spin_lock_irqsave(&atchan->lock, flags); + spin_unlock_irqrestore(&atchan->lock, flags); - dma_writel(atdma, CHDR, AT_DMA_RES(chan_id)); - clear_bit(ATC_IS_PAUSED, &atchan->status); + return 0; +} - spin_unlock_irqrestore(&atchan->lock, flags); - } else if (cmd == DMA_TERMINATE_ALL) { - struct at_desc *desc, *_desc; - /* - * This is only called when something went wrong elsewhere, so - * we don't really care about the data. Just disable the - * channel. We still have to poll the channel enable bit due - * to AHB/HSB limitations. - */ - spin_lock_irqsave(&atchan->lock, flags); +static int atc_terminate_all(struct dma_chan *chan) +{ + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_dma *atdma = to_at_dma(chan->device); + int chan_id = atchan->chan_common.chan_id; + struct at_desc *desc, *_desc; + unsigned long flags; - /* disabling channel: must also remove suspend state */ - dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask); + LIST_HEAD(list); - /* confirm that this channel is disabled */ - while (dma_readl(atdma, CHSR) & atchan->mask) - cpu_relax(); + dev_vdbg(chan2dev(chan), "%s\n", __func__); - /* active_list entries will end up before queued entries */ - list_splice_init(&atchan->queue, &list); - list_splice_init(&atchan->active_list, &list); + /* + * This is only called when something went wrong elsewhere, so + * we don't really care about the data. Just disable the + * channel. We still have to poll the channel enable bit due + * to AHB/HSB limitations. + */ + spin_lock_irqsave(&atchan->lock, flags); - /* Flush all pending and queued descriptors */ - list_for_each_entry_safe(desc, _desc, &list, desc_node) - atc_chain_complete(atchan, desc); + /* disabling channel: must also remove suspend state */ + dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask); - clear_bit(ATC_IS_PAUSED, &atchan->status); - /* if channel dedicated to cyclic operations, free it */ - clear_bit(ATC_IS_CYCLIC, &atchan->status); + /* confirm that this channel is disabled */ + while (dma_readl(atdma, CHSR) & atchan->mask) + cpu_relax(); - spin_unlock_irqrestore(&atchan->lock, flags); - } else if (cmd == DMA_SLAVE_CONFIG) { - return set_runtime_config(chan, (struct dma_slave_config *)arg); - } else { - return -ENXIO; - } + /* active_list entries will end up before queued entries */ + list_splice_init(&atchan->queue, &list); + list_splice_init(&atchan->active_list, &list); + + /* Flush all pending and queued descriptors */ + list_for_each_entry_safe(desc, _desc, &list, desc_node) + atc_chain_complete(atchan, desc); + + clear_bit(ATC_IS_PAUSED, &atchan->status); + /* if channel dedicated to cyclic operations, free it */ + clear_bit(ATC_IS_CYCLIC, &atchan->status); + + spin_unlock_irqrestore(&atchan->lock, flags); return 0; } @@ -1505,7 +1532,14 @@ static int __init at_dma_probe(struct platform_device *pdev) /* controller can do slave DMA: can trigger cyclic transfers */ dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask); atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic; - atdma->dma_common.device_control = atc_control; + atdma->dma_common.device_config = atc_config; + atdma->dma_common.device_pause = atc_pause; + atdma->dma_common.device_resume = atc_resume; + atdma->dma_common.device_terminate_all = atc_terminate_all; + atdma->dma_common.src_addr_widths = ATC_DMA_BUSWIDTHS; + atdma->dma_common.dst_addr_widths = ATC_DMA_BUSWIDTHS; + atdma->dma_common.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + atdma->dma_common.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; } dma_writel(atdma, EN, AT_DMA_ENABLE); @@ -1622,7 +1656,7 @@ static void atc_suspend_cyclic(struct at_dma_chan *atchan) if (!atc_chan_is_paused(atchan)) { dev_warn(chan2dev(chan), "cyclic channel not paused, should be done by channel user\n"); - atc_control(chan, DMA_PAUSE, 0); + atc_pause(chan); } /* now preserve additional data for cyclic operations */ diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index 2787aba60c6b..d6bba6c636c2 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -232,7 +232,8 @@ enum atc_status { * @save_dscr: for cyclic operations, preserve next descriptor address in * the cyclic list on suspend/resume cycle * @remain_desc: to save remain desc length - * @dma_sconfig: configuration for slave transfers, passed via DMA_SLAVE_CONFIG + * @dma_sconfig: configuration for slave transfers, passed via + * .device_config * @lock: serializes enqueue/dequeue operations to descriptors lists * @active_list: list of descriptors dmaengine is being running on * @queue: list of descriptors ready to be submitted to engine diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 1c4c96b7e2bf..c39000b9980a 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -174,6 +174,13 @@ #define AT_XDMAC_MAX_CHAN 0x20 +#define AT_XDMAC_DMA_BUSWIDTHS\ + (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\ + BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |\ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |\ + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)) + enum atc_status { AT_XDMAC_CHAN_IS_CYCLIC = 0, AT_XDMAC_CHAN_IS_PAUSED, @@ -1107,58 +1114,75 @@ static void at_xdmac_issue_pending(struct dma_chan *chan) return; } -static int at_xdmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, - unsigned long arg) +static int at_xdmac_device_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); + int ret; + + dev_dbg(chan2dev(chan), "%s\n", __func__); + + spin_lock_bh(&atchan->lock); + ret = at_xdmac_set_slave_config(chan, config); + spin_unlock_bh(&atchan->lock); + + return ret; +} + +static int at_xdmac_device_pause(struct dma_chan *chan) { - struct at_xdmac_desc *desc, *_desc; struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); - int ret = 0; - dev_dbg(chan2dev(chan), "%s: cmd=%d\n", __func__, cmd); + dev_dbg(chan2dev(chan), "%s\n", __func__); spin_lock_bh(&atchan->lock); + at_xdmac_write(atxdmac, AT_XDMAC_GRWS, atchan->mask); + set_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); + spin_unlock_bh(&atchan->lock); + + return 0; +} - switch (cmd) { - case DMA_PAUSE: - at_xdmac_write(atxdmac, AT_XDMAC_GRWS, atchan->mask); - set_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); - break; +static int at_xdmac_device_resume(struct dma_chan *chan) +{ + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); - case DMA_RESUME: - if (!at_xdmac_chan_is_paused(atchan)) - break; + dev_dbg(chan2dev(chan), "%s\n", __func__); - at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask); - clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); - break; + spin_lock_bh(&atchan->lock); + if (!at_xdmac_chan_is_paused(atchan)) + return 0; - case DMA_TERMINATE_ALL: - at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); - while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask) - cpu_relax(); + at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask); + clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); + spin_unlock_bh(&atchan->lock); + + return 0; +} - /* Cancel all pending transfers. */ - list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node) - at_xdmac_remove_xfer(atchan, desc); +static int at_xdmac_device_terminate_all(struct dma_chan *chan) +{ + struct at_xdmac_desc *desc, *_desc; + struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); - clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status); - break; + dev_dbg(chan2dev(chan), "%s\n", __func__); - case DMA_SLAVE_CONFIG: - ret = at_xdmac_set_slave_config(chan, - (struct dma_slave_config *)arg); - break; + spin_lock_bh(&atchan->lock); + at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); + while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask) + cpu_relax(); - default: - dev_err(chan2dev(chan), - "unmanaged or unknown dma control cmd: %d\n", cmd); - ret = -ENXIO; - } + /* Cancel all pending transfers. */ + list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node) + at_xdmac_remove_xfer(atchan, desc); + clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status); spin_unlock_bh(&atchan->lock); - return ret; + return 0; } static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) @@ -1217,27 +1241,6 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan) return; } -#define AT_XDMAC_DMA_BUSWIDTHS\ - (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\ - BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |\ - BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\ - BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |\ - BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)) - -static int at_xdmac_device_slave_caps(struct dma_chan *dchan, - struct dma_slave_caps *caps) -{ - - caps->src_addr_widths = AT_XDMAC_DMA_BUSWIDTHS; - caps->dstn_addr_widths = AT_XDMAC_DMA_BUSWIDTHS; - caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); - caps->cmd_pause = true; - caps->cmd_terminate = true; - caps->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - - return 0; -} - #ifdef CONFIG_PM static int atmel_xdmac_prepare(struct device *dev) { @@ -1270,7 +1273,7 @@ static int atmel_xdmac_suspend(struct device *dev) if (at_xdmac_chan_is_cyclic(atchan)) { if (!at_xdmac_chan_is_paused(atchan)) - at_xdmac_control(chan, DMA_PAUSE, 0); + at_xdmac_device_pause(chan); atchan->save_cim = at_xdmac_chan_read(atchan, AT_XDMAC_CIM); atchan->save_cnda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA); atchan->save_cndc = at_xdmac_chan_read(atchan, AT_XDMAC_CNDC); @@ -1407,8 +1410,14 @@ static int at_xdmac_probe(struct platform_device *pdev) atxdmac->dma.device_prep_dma_cyclic = at_xdmac_prep_dma_cyclic; atxdmac->dma.device_prep_dma_memcpy = at_xdmac_prep_dma_memcpy; atxdmac->dma.device_prep_slave_sg = at_xdmac_prep_slave_sg; - atxdmac->dma.device_control = at_xdmac_control; - atxdmac->dma.device_slave_caps = at_xdmac_device_slave_caps; + atxdmac->dma.device_config = at_xdmac_device_config; + atxdmac->dma.device_pause = at_xdmac_device_pause; + atxdmac->dma.device_resume = at_xdmac_device_resume; + atxdmac->dma.device_terminate_all = at_xdmac_device_terminate_all; + atxdmac->dma.src_addr_widths = AT_XDMAC_DMA_BUSWIDTHS; + atxdmac->dma.dst_addr_widths = AT_XDMAC_DMA_BUSWIDTHS; + atxdmac->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + atxdmac->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; /* Disable all chans and interrupts. */ at_xdmac_off(atxdmac); diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 918b7b3f766f..0723096fb50a 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -436,9 +436,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( return vchan_tx_prep(&c->vc, &d->vd, flags); } -static int bcm2835_dma_slave_config(struct bcm2835_chan *c, - struct dma_slave_config *cfg) +static int bcm2835_dma_slave_config(struct dma_chan *chan, + struct dma_slave_config *cfg) { + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + if ((cfg->direction == DMA_DEV_TO_MEM && cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || (cfg->direction == DMA_MEM_TO_DEV && @@ -452,8 +454,9 @@ static int bcm2835_dma_slave_config(struct bcm2835_chan *c, return 0; } -static int bcm2835_dma_terminate_all(struct bcm2835_chan *c) +static int bcm2835_dma_terminate_all(struct dma_chan *chan) { + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); unsigned long flags; int timeout = 10000; @@ -495,24 +498,6 @@ static int bcm2835_dma_terminate_all(struct bcm2835_chan *c) return 0; } -static int bcm2835_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, - unsigned long arg) -{ - struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); - - switch (cmd) { - case DMA_SLAVE_CONFIG: - return bcm2835_dma_slave_config(c, - (struct dma_slave_config *)arg); - - case DMA_TERMINATE_ALL: - return bcm2835_dma_terminate_all(c); - - default: - return -ENXIO; - } -} - static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) { struct bcm2835_chan *c; @@ -565,18 +550,6 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec, return chan; } -static int bcm2835_dma_device_slave_caps(struct dma_chan *dchan, - struct dma_slave_caps *caps) -{ - caps->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - caps->dstn_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); - caps->cmd_pause = false; - caps->cmd_terminate = true; - - return 0; -} - static int bcm2835_dma_probe(struct platform_device *pdev) { struct bcm2835_dmadev *od; @@ -615,9 +588,12 @@ static int bcm2835_dma_probe(struct platform_device *pdev) od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; od->ddev.device_tx_status = bcm2835_dma_tx_status; od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_slave_caps = bcm2835_dma_device_slave_caps; od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; - od->ddev.device_control = bcm2835_dma_control; + od->ddev.device_config = bcm2835_dma_slave_config; + od->ddev.device_terminate_all = bcm2835_dma_terminate_all; + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); spin_lock_init(&od->lock); diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index e88588d8ecd3..fd22dd36985f 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1690,7 +1690,7 @@ static u32 coh901318_get_bytes_left(struct dma_chan *chan) * Pauses a transfer without losing data. Enables power save. * Use this function in conjunction with coh901318_resume. */ -static void coh901318_pause(struct dma_chan *chan) +static int coh901318_pause(struct dma_chan *chan) { u32 val; unsigned long flags; @@ -1730,12 +1730,13 @@ static void coh901318_pause(struct dma_chan *chan) enable_powersave(cohc); spin_unlock_irqrestore(&cohc->lock, flags); + return 0; } /* Resumes a transfer that has been stopped via 300_dma_stop(..). Power save is handled. */ -static void coh901318_resume(struct dma_chan *chan) +static int coh901318_resume(struct dma_chan *chan) { u32 val; unsigned long flags; @@ -1760,6 +1761,7 @@ static void coh901318_resume(struct dma_chan *chan) } spin_unlock_irqrestore(&cohc->lock, flags); + return 0; } bool coh901318_filter_id(struct dma_chan *chan, void *chan_id) @@ -2114,6 +2116,57 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static int coh901318_terminate_all(struct dma_chan *chan |