提交 826b15a7 编写于 作者: M Maxime Ripard 提交者: Vinod Koul

dmaengine: sun6i: Split device_control

Split the device_control callback of the Allwinner A31 DMA driver to make use
of the newly introduced callbacks, that will eventually be used to retrieve
slave capabilities.
Signed-off-by: NMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: NVinod Koul <vinod.koul@intel.com>
上级 ed14a7c9
...@@ -355,38 +355,6 @@ static void sun6i_dma_free_desc(struct virt_dma_desc *vd) ...@@ -355,38 +355,6 @@ static void sun6i_dma_free_desc(struct virt_dma_desc *vd)
kfree(txd); kfree(txd);
} }
static int sun6i_dma_terminate_all(struct sun6i_vchan *vchan)
{
struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
struct sun6i_pchan *pchan = vchan->phy;
unsigned long flags;
LIST_HEAD(head);
spin_lock(&sdev->lock);
list_del_init(&vchan->node);
spin_unlock(&sdev->lock);
spin_lock_irqsave(&vchan->vc.lock, flags);
vchan_get_all_descriptors(&vchan->vc, &head);
if (pchan) {
writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE);
writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE);
vchan->phy = NULL;
pchan->vchan = NULL;
pchan->desc = NULL;
pchan->done = NULL;
}
spin_unlock_irqrestore(&vchan->vc.lock, flags);
vchan_dma_desc_free_list(&vchan->vc, &head);
return 0;
}
static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
{ {
struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device); struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
...@@ -675,57 +643,92 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( ...@@ -675,57 +643,92 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
return NULL; return NULL;
} }
static int sun6i_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, static int sun6i_dma_config(struct dma_chan *chan,
unsigned long arg) struct dma_slave_config *config)
{
struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
memcpy(&vchan->cfg, config, sizeof(*config));
return 0;
}
static int sun6i_dma_pause(struct dma_chan *chan)
{
struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
struct sun6i_pchan *pchan = vchan->phy;
dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc);
if (pchan) {
writel(DMA_CHAN_PAUSE_PAUSE,
pchan->base + DMA_CHAN_PAUSE);
} else {
spin_lock(&sdev->lock);
list_del_init(&vchan->node);
spin_unlock(&sdev->lock);
}
return 0;
}
static int sun6i_dma_resume(struct dma_chan *chan)
{ {
struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device); struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
struct sun6i_vchan *vchan = to_sun6i_vchan(chan); struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
struct sun6i_pchan *pchan = vchan->phy; struct sun6i_pchan *pchan = vchan->phy;
unsigned long flags; unsigned long flags;
int ret = 0;
switch (cmd) { dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc);
case DMA_RESUME:
dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc);
spin_lock_irqsave(&vchan->vc.lock, flags); spin_lock_irqsave(&vchan->vc.lock, flags);
if (pchan) { if (pchan) {
writel(DMA_CHAN_PAUSE_RESUME, writel(DMA_CHAN_PAUSE_RESUME,
pchan->base + DMA_CHAN_PAUSE); pchan->base + DMA_CHAN_PAUSE);
} else if (!list_empty(&vchan->vc.desc_issued)) { } else if (!list_empty(&vchan->vc.desc_issued)) {
spin_lock(&sdev->lock); spin_lock(&sdev->lock);
list_add_tail(&vchan->node, &sdev->pending); list_add_tail(&vchan->node, &sdev->pending);
spin_unlock(&sdev->lock); spin_unlock(&sdev->lock);
} }
spin_unlock_irqrestore(&vchan->vc.lock, flags); spin_unlock_irqrestore(&vchan->vc.lock, flags);
break;
case DMA_PAUSE: return 0;
dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc); }
if (pchan) { static int sun6i_dma_terminate_all(struct dma_chan *chan)
writel(DMA_CHAN_PAUSE_PAUSE, {
pchan->base + DMA_CHAN_PAUSE); struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
} else { struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
spin_lock(&sdev->lock); struct sun6i_pchan *pchan = vchan->phy;
list_del_init(&vchan->node); unsigned long flags;
spin_unlock(&sdev->lock); LIST_HEAD(head);
}
break; spin_lock(&sdev->lock);
list_del_init(&vchan->node);
case DMA_TERMINATE_ALL: spin_unlock(&sdev->lock);
ret = sun6i_dma_terminate_all(vchan);
break; spin_lock_irqsave(&vchan->vc.lock, flags);
case DMA_SLAVE_CONFIG:
memcpy(&vchan->cfg, (void *)arg, sizeof(struct dma_slave_config)); vchan_get_all_descriptors(&vchan->vc, &head);
break;
default: if (pchan) {
ret = -ENXIO; writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE);
break; writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE);
vchan->phy = NULL;
pchan->vchan = NULL;
pchan->desc = NULL;
pchan->done = NULL;
} }
return ret;
spin_unlock_irqrestore(&vchan->vc.lock, flags);
vchan_dma_desc_free_list(&vchan->vc, &head);
return 0;
} }
static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan, static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan,
...@@ -960,8 +963,11 @@ static int sun6i_dma_probe(struct platform_device *pdev) ...@@ -960,8 +963,11 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.device_issue_pending = sun6i_dma_issue_pending; sdc->slave.device_issue_pending = sun6i_dma_issue_pending;
sdc->slave.device_prep_slave_sg = sun6i_dma_prep_slave_sg; sdc->slave.device_prep_slave_sg = sun6i_dma_prep_slave_sg;
sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy; sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy;
sdc->slave.device_control = sun6i_dma_control;
sdc->slave.copy_align = 4; sdc->slave.copy_align = 4;
sdc->slave.device_config = sun6i_dma_config;
sdc->slave.device_pause = sun6i_dma_pause;
sdc->slave.device_resume = sun6i_dma_resume;
sdc->slave.device_terminate_all = sun6i_dma_terminate_all;
sdc->slave.dev = &pdev->dev; sdc->slave.dev = &pdev->dev;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册