summaryrefslogtreecommitdiff
path: root/drivers/dma/amba-pl08x.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-18 08:49:20 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-18 08:49:20 -0800
commitce1d3fde87d1a21f1ec1147dde32b2825dd3a276 (patch)
tree6ffab43e47e3a22a76bf9bf4efeecdf1b90dcb6f /drivers/dma/amba-pl08x.c
parent928fce2f6d8152d897790c1a5bbeef5642f69e0e (diff)
parent88987d2c7534a0269f567fb101e6d71a08f0f01d (diff)
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul: "This update brings: - the big cleanup up by Maxime for device control and slave capabilities. This makes the API much cleaner. - new IMG MDC driver by Andrew - new Renesas R-Car Gen2 DMA Controller driver by Laurent along with bunch of fixes on rcar drivers - odd fixes and updates spread over driver" * 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (130 commits) dmaengine: pl330: add DMA_PAUSE feature dmaengine: pl330: improve pl330_tx_status() function dmaengine: rcar-dmac: Disable channel 0 when using IOMMU dmaengine: rcar-dmac: Work around descriptor mode IOMMU errata dmaengine: rcar-dmac: Allocate hardware descriptors with DMAC device dmaengine: rcar-dmac: Fix oops due to unintialized list in error ISR dmaengine: rcar-dmac: Fix spinlock issues in interrupt dmaenegine: edma: fix sparse warnings dmaengine: rcar-dmac: Fix uninitialized variable usage dmaengine: shdmac: extend PM methods dmaengine: shdmac: use SET_RUNTIME_PM_OPS() dmaengine: pl330: fix bug that cause start the same descs in cyclic dmaengine: at_xdmac: allow muliple dwidths when doing slave transfers dmaengine: at_xdmac: simplify channel configuration stuff dmaengine: at_xdmac: introduce save_cc field dmaengine: at_xdmac: wait for in-progress transaction to complete after pausing a channel ioat: fail self-test if wait_for_completion times out dmaengine: dw: define DW_DMA_MAX_NR_MASTERS dmaengine: dw: amend description of dma_dev field dmatest: move src_off, dst_off, len inside loop ...
Diffstat (limited to 'drivers/dma/amba-pl08x.c')
-rw-r--r--drivers/dma/amba-pl08x.c156
1 files changed, 90 insertions, 66 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);