dmaengine: pl08x: Split device_control
authorMaxime Ripard <maxime.ripard@free-electrons.com>
Mon, 17 Nov 2014 13:42:05 +0000 (14:42 +0100)
committerVinod Koul <vinod.koul@intel.com>
Mon, 22 Dec 2014 06:58:56 +0000 (12:28 +0530)
Split the device_control callback of the AMBA PL08x 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>
drivers/dma/amba-pl08x.c

index 1364d00881dd5659d7c083b2f354f95be5749cb8..4a5fd245014e6666721c111b85515b2e1b05f74c 100644 (file)
@@ -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);