Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+84 −74
Original line number Diff line number Diff line
@@ -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);
}

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);
	dma_addr_t addr;
	enum dma_slave_buswidth width;
@@ -704,8 +706,7 @@ static int sa11x0_dma_slave_config(struct sa11x0_dma_chan *c, struct dma_slave_c
	return 0;
}

static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
	unsigned long arg)
static int sa11x0_dma_pause(struct dma_chan *chan)
{
	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
	struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
@@ -714,46 +715,6 @@ static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
	unsigned long flags;
	int ret;

	switch (cmd) {
	case DMA_SLAVE_CONFIG:
		return sa11x0_dma_slave_config(c, (struct dma_slave_config *)arg);

	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;
		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);
		ret = 0;
		break;

	case DMA_PAUSE:
	dev_dbg(d->slave.dev, "vchan %p: pause\n", &c->vc);
	spin_lock_irqsave(&c->vc.lock, flags);
	if (c->status == DMA_IN_PROGRESS) {
@@ -769,10 +730,19 @@ static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
		}
	}
	spin_unlock_irqrestore(&c->vc.lock, flags);
		ret = 0;
		break;

	case DMA_RESUME:
	return 0;
}

static int sa11x0_dma_resume(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: resume\n", &c->vc);
	spin_lock_irqsave(&c->vc.lock, flags);
	if (c->status == DMA_PAUSED) {
@@ -788,15 +758,52 @@ static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
		}
	}
	spin_unlock_irqrestore(&c->vc.lock, flags);
		ret = 0;
		break;

	default:
		ret = -ENXIO;
		break;
	return 0;
}

	return ret;
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 0;
}

struct sa11x0_dma_channel_desc {
@@ -833,7 +840,10 @@ static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
	dmadev->dev = dev;
	dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_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_issue_pending = sa11x0_dma_issue_pending;