mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 21:51:05 +00:00
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: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
This commit is contained in:
parent
ed14a7c9fa
commit
826b15a7a8
1 changed files with 81 additions and 75 deletions
|
@ -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 @@ err_lli_free:
|
||||||
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);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DMA_PAUSE:
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DMA_TERMINATE_ALL:
|
|
||||||
ret = sun6i_dma_terminate_all(vchan);
|
|
||||||
break;
|
|
||||||
case DMA_SLAVE_CONFIG:
|
|
||||||
memcpy(&vchan->cfg, (void *)arg, sizeof(struct dma_slave_config));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENXIO;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
spin_unlock_irqrestore(&vchan->vc.lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sun6i_dma_terminate_all(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;
|
||||||
|
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 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)
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue