Commit 4a533218 authored by Maxime Ripard's avatar Maxime Ripard Committed by Vinod Koul

dmaengine: sa11x0: Split device_control

Split the device_control callback of the SA-11x0 DMA driver to make use of the
newly introduced callbacks, that will eventually be used to retrieve slave
capabilities.
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 39ad4600
...@@ -669,8 +669,10 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic( ...@@ -669,8 +669,10 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
return vchan_tx_prep(&c->vc, &txd->vd, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); return vchan_tx_prep(&c->vc, &txd->vd, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
} }
static int sa11x0_dma_slave_config(struct sa11x0_dma_chan *c, struct dma_slave_config *cfg) static int sa11x0_dma_slave_config(struct dma_chan *chan,
struct dma_slave_config *cfg)
{ {
struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
u32 ddar = c->ddar & ((0xf << 4) | DDAR_RW); u32 ddar = c->ddar & ((0xf << 4) | DDAR_RW);
dma_addr_t addr; dma_addr_t addr;
enum dma_slave_buswidth width; enum dma_slave_buswidth width;
...@@ -704,8 +706,7 @@ static int sa11x0_dma_slave_config(struct sa11x0_dma_chan *c, struct dma_slave_c ...@@ -704,8 +706,7 @@ static int sa11x0_dma_slave_config(struct sa11x0_dma_chan *c, struct dma_slave_c
return 0; return 0;
} }
static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, static int sa11x0_dma_pause(struct dma_chan *chan)
unsigned long arg)
{ {
struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan); struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
...@@ -714,89 +715,95 @@ static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ...@@ -714,89 +715,95 @@ static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
unsigned long flags; unsigned long flags;
int ret; int ret;
switch (cmd) { dev_dbg(d->slave.dev, "vchan %p: pause\n", &c->vc);
case DMA_SLAVE_CONFIG: spin_lock_irqsave(&c->vc.lock, flags);
return sa11x0_dma_slave_config(c, (struct dma_slave_config *)arg); if (c->status == DMA_IN_PROGRESS) {
c->status = DMA_PAUSED;
case DMA_TERMINATE_ALL:
dev_dbg(d->slave.dev, "vchan %p: terminate all\n", &c->vc);
/* Clear the tx descriptor lists */
spin_lock_irqsave(&c->vc.lock, flags);
vchan_get_all_descriptors(&c->vc, &head);
p = c->phy; p = c->phy;
if (p) { if (p) {
dev_dbg(d->slave.dev, "pchan %u: terminating\n", p->num); writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C);
/* vchan is assigned to a pchan - stop the channel */ } else {
writel(DCSR_RUN | DCSR_IE |
DCSR_STRTA | DCSR_DONEA |
DCSR_STRTB | DCSR_DONEB,
p->base + DMA_DCSR_C);
if (p->txd_load) {
if (p->txd_load != p->txd_done)
list_add_tail(&p->txd_load->vd.node, &head);
p->txd_load = NULL;
}
if (p->txd_done) {
list_add_tail(&p->txd_done->vd.node, &head);
p->txd_done = NULL;
}
c->phy = NULL;
spin_lock(&d->lock); spin_lock(&d->lock);
p->vchan = NULL; list_del_init(&c->node);
spin_unlock(&d->lock); spin_unlock(&d->lock);
tasklet_schedule(&d->task);
} }
spin_unlock_irqrestore(&c->vc.lock, flags); }
vchan_dma_desc_free_list(&c->vc, &head); spin_unlock_irqrestore(&c->vc.lock, flags);
ret = 0;
break;
case DMA_PAUSE: return 0;
dev_dbg(d->slave.dev, "vchan %p: pause\n", &c->vc); }
spin_lock_irqsave(&c->vc.lock, flags);
if (c->status == DMA_IN_PROGRESS) {
c->status = DMA_PAUSED;
p = c->phy; static int sa11x0_dma_resume(struct dma_chan *chan)
if (p) { {
writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C); struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
} else { struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
spin_lock(&d->lock); struct sa11x0_dma_phy *p;
list_del_init(&c->node); LIST_HEAD(head);
spin_unlock(&d->lock); unsigned long flags;
} int ret;
}
spin_unlock_irqrestore(&c->vc.lock, flags);
ret = 0;
break;
case DMA_RESUME: dev_dbg(d->slave.dev, "vchan %p: resume\n", &c->vc);
dev_dbg(d->slave.dev, "vchan %p: resume\n", &c->vc); spin_lock_irqsave(&c->vc.lock, flags);
spin_lock_irqsave(&c->vc.lock, flags); if (c->status == DMA_PAUSED) {
if (c->status == DMA_PAUSED) { c->status = DMA_IN_PROGRESS;
c->status = DMA_IN_PROGRESS;
p = c->phy;
p = c->phy; if (p) {
if (p) { writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_S);
writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_S); } else if (!list_empty(&c->vc.desc_issued)) {
} else if (!list_empty(&c->vc.desc_issued)) { spin_lock(&d->lock);
spin_lock(&d->lock); list_add_tail(&c->node, &d->chan_pending);
list_add_tail(&c->node, &d->chan_pending); spin_unlock(&d->lock);
spin_unlock(&d->lock);
}
} }
spin_unlock_irqrestore(&c->vc.lock, flags); }
ret = 0; spin_unlock_irqrestore(&c->vc.lock, flags);
break;
default: return 0;
ret = -ENXIO; }
break;
static int sa11x0_dma_terminate_all(struct dma_chan *chan)
{
struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
struct sa11x0_dma_phy *p;
LIST_HEAD(head);
unsigned long flags;
int ret;
dev_dbg(d->slave.dev, "vchan %p: terminate all\n", &c->vc);
/* Clear the tx descriptor lists */
spin_lock_irqsave(&c->vc.lock, flags);
vchan_get_all_descriptors(&c->vc, &head);
p = c->phy;
if (p) {
dev_dbg(d->slave.dev, "pchan %u: terminating\n", p->num);
/* vchan is assigned to a pchan - stop the channel */
writel(DCSR_RUN | DCSR_IE |
DCSR_STRTA | DCSR_DONEA |
DCSR_STRTB | DCSR_DONEB,
p->base + DMA_DCSR_C);
if (p->txd_load) {
if (p->txd_load != p->txd_done)
list_add_tail(&p->txd_load->vd.node, &head);
p->txd_load = NULL;
}
if (p->txd_done) {
list_add_tail(&p->txd_done->vd.node, &head);
p->txd_done = NULL;
}
c->phy = NULL;
spin_lock(&d->lock);
p->vchan = NULL;
spin_unlock(&d->lock);
tasklet_schedule(&d->task);
} }
spin_unlock_irqrestore(&c->vc.lock, flags);
vchan_dma_desc_free_list(&c->vc, &head);
return ret; return 0;
} }
struct sa11x0_dma_channel_desc { struct sa11x0_dma_channel_desc {
...@@ -833,7 +840,10 @@ static int sa11x0_dma_init_dmadev(struct dma_device *dmadev, ...@@ -833,7 +840,10 @@ static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
dmadev->dev = dev; dmadev->dev = dev;
dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_chan_resources; dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_chan_resources;
dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources; dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources;
dmadev->device_control = sa11x0_dma_control; dmadev->device_config = sa11x0_dma_slave_config;
dmadev->device_pause = sa11x0_dma_pause;
dmadev->device_resume = sa11x0_dma_resume;
dmadev->device_terminate_all = sa11x0_dma_terminate_all;
dmadev->device_tx_status = sa11x0_dma_tx_status; dmadev->device_tx_status = sa11x0_dma_tx_status;
dmadev->device_issue_pending = sa11x0_dma_issue_pending; dmadev->device_issue_pending = sa11x0_dma_issue_pending;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment