dmaengine: pl08x: Make slave engine optional
[linux-2.6-microblaze.git] / drivers / dma / amba-pl08x.c
index d3d660a..6ddb029 100644 (file)
@@ -253,8 +253,9 @@ struct pl08x_dma_chan {
 
 /**
  * struct pl08x_driver_data - the local state holder for the PL08x
- * @slave: slave engine for this instance
+ * @slave: optional slave engine for this instance
  * @memcpy: memcpy engine for this instance
+ * @has_slave: the PL08x has a slave engine (routed signals)
  * @base: virtual memory base (remapped) for the PL08x
  * @adev: the corresponding AMBA (PrimeCell) bus entry
  * @vd: vendor data for this PL08x variant
@@ -269,6 +270,7 @@ struct pl08x_dma_chan {
 struct pl08x_driver_data {
        struct dma_device slave;
        struct dma_device memcpy;
+       bool has_slave;
        void __iomem *base;
        struct amba_device *adev;
        const struct vendor_data *vd;
@@ -705,7 +707,7 @@ static void pl08x_phy_free(struct pl08x_dma_chan *plchan)
                        break;
                }
 
-       if (!next) {
+       if (!next && pl08x->has_slave) {
                list_for_each_entry(p, &pl08x->slave.channels, vc.chan.device_node)
                        if (p->state == PL08X_CHAN_WAITING) {
                                next = p;
@@ -2085,12 +2087,15 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data)
                           pl08x_state_str(chan->state));
        }
 
-       seq_printf(s, "\nPL08x virtual slave channels:\n");
-       seq_printf(s, "CHANNEL:\tSTATE:\n");
-       seq_printf(s, "--------\t------\n");
-       list_for_each_entry(chan, &pl08x->slave.channels, vc.chan.device_node) {
-               seq_printf(s, "%s\t\t%s\n", chan->name,
-                          pl08x_state_str(chan->state));
+       if (pl08x->has_slave) {
+               seq_printf(s, "\nPL08x virtual slave channels:\n");
+               seq_printf(s, "CHANNEL:\tSTATE:\n");
+               seq_printf(s, "--------\t------\n");
+               list_for_each_entry(chan, &pl08x->slave.channels,
+                                   vc.chan.device_node) {
+                       seq_printf(s, "%s\t\t%s\n", chan->name,
+                                  pl08x_state_str(chan->state));
+               }
        }
 
        return 0;
@@ -2128,6 +2133,10 @@ static struct dma_chan *pl08x_find_chan_id(struct pl08x_driver_data *pl08x,
 {
        struct pl08x_dma_chan *chan;
 
+       /* Trying to get a slave channel from something with no slave support */
+       if (!pl08x->has_slave)
+               return NULL;
+
        list_for_each_entry(chan, &pl08x->slave.channels, vc.chan.device_node) {
                if (chan->signal == id)
                        return &chan->vc.chan;
@@ -2265,20 +2274,24 @@ static int pl08x_of_probe(struct amba_device *adev,
         * for a device and have it's AHB interfaces set up at
         * translation time.
         */
-       chanp = devm_kcalloc(&adev->dev,
-                       pl08x->vd->signals,
-                       sizeof(struct pl08x_channel_data),
-                       GFP_KERNEL);
-       if (!chanp)
-               return -ENOMEM;
+       if (pl08x->vd->signals) {
+               chanp = devm_kcalloc(&adev->dev,
+                                    pl08x->vd->signals,
+                                    sizeof(struct pl08x_channel_data),
+                                    GFP_KERNEL);
+               if (!chanp)
+                       return -ENOMEM;
 
-       pd->slave_channels = chanp;
-       for (i = 0; i < pl08x->vd->signals; i++) {
-               /* chanp->periph_buses will be assigned at translation */
-               chanp->bus_id = kasprintf(GFP_KERNEL, "slave%d", i);
-               chanp++;
+               pd->slave_channels = chanp;
+               for (i = 0; i < pl08x->vd->signals; i++) {
+                       /*
+                        * chanp->periph_buses will be assigned at translation
+                        */
+                       chanp->bus_id = kasprintf(GFP_KERNEL, "slave%d", i);
+                       chanp++;
+               }
+               pd->num_slave_channels = pl08x->vd->signals;
        }
-       pd->num_slave_channels = pl08x->vd->signals;
 
        pl08x->pd = pd;
 
@@ -2340,24 +2353,34 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        pl08x->memcpy.directions = BIT(DMA_MEM_TO_MEM);
        pl08x->memcpy.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
 
-       /* Initialize slave engine */
-       dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
-       dma_cap_set(DMA_CYCLIC, pl08x->slave.cap_mask);
-       pl08x->slave.dev = &adev->dev;
-       pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
-       pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
-       pl08x->slave.device_tx_status = pl08x_dma_tx_status;
-       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_config = pl08x_config;
-       pl08x->slave.device_pause = pl08x_pause;
-       pl08x->slave.device_resume = pl08x_resume;
-       pl08x->slave.device_terminate_all = pl08x_terminate_all;
-       pl08x->slave.src_addr_widths = PL80X_DMA_BUSWIDTHS;
-       pl08x->slave.dst_addr_widths = PL80X_DMA_BUSWIDTHS;
-       pl08x->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-       pl08x->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+       /*
+        * Initialize slave engine, if the block has no signals, that means
+        * we have no slave support.
+        */
+       if (vd->signals) {
+               pl08x->has_slave = true;
+               dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
+               dma_cap_set(DMA_CYCLIC, pl08x->slave.cap_mask);
+               pl08x->slave.dev = &adev->dev;
+               pl08x->slave.device_free_chan_resources =
+                       pl08x_free_chan_resources;
+               pl08x->slave.device_prep_dma_interrupt =
+                       pl08x_prep_dma_interrupt;
+               pl08x->slave.device_tx_status = pl08x_dma_tx_status;
+               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_config = pl08x_config;
+               pl08x->slave.device_pause = pl08x_pause;
+               pl08x->slave.device_resume = pl08x_resume;
+               pl08x->slave.device_terminate_all = pl08x_terminate_all;
+               pl08x->slave.src_addr_widths = PL80X_DMA_BUSWIDTHS;
+               pl08x->slave.dst_addr_widths = PL80X_DMA_BUSWIDTHS;
+               pl08x->slave.directions =
+                       BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+               pl08x->slave.residue_granularity =
+                       DMA_RESIDUE_GRANULARITY_SEGMENT;
+       }
 
        /* Get the platform data */
        pl08x->pd = dev_get_platdata(&adev->dev);
@@ -2465,13 +2488,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        }
 
        /* Register slave channels */
-       ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
-                       pl08x->pd->num_slave_channels, true);
-       if (ret < 0) {
-               dev_warn(&pl08x->adev->dev,
-                       "%s failed to enumerate slave channels - %d\n",
-                               __func__, ret);
-               goto out_no_slave;
+       if (pl08x->has_slave) {
+               ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
+                                       pl08x->pd->num_slave_channels, true);
+               if (ret < 0) {
+                       dev_warn(&pl08x->adev->dev,
+                                "%s failed to enumerate slave channels - %d\n",
+                                __func__, ret);
+                       goto out_no_slave;
+               }
        }
 
        ret = dma_async_device_register(&pl08x->memcpy);
@@ -2482,12 +2507,14 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
                goto out_no_memcpy_reg;
        }
 
-       ret = dma_async_device_register(&pl08x->slave);
-       if (ret) {
-               dev_warn(&pl08x->adev->dev,
+       if (pl08x->has_slave) {
+               ret = dma_async_device_register(&pl08x->slave);
+               if (ret) {
+                       dev_warn(&pl08x->adev->dev,
                        "%s failed to register slave as an async device - %d\n",
                        __func__, ret);
-               goto out_no_slave_reg;
+                       goto out_no_slave_reg;
+               }
        }
 
        amba_set_drvdata(adev, pl08x);
@@ -2501,7 +2528,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 out_no_slave_reg:
        dma_async_device_unregister(&pl08x->memcpy);
 out_no_memcpy_reg:
-       pl08x_free_virtual_channels(&pl08x->slave);
+       if (pl08x->has_slave)
+               pl08x_free_virtual_channels(&pl08x->slave);
 out_no_slave:
        pl08x_free_virtual_channels(&pl08x->memcpy);
 out_no_memcpy: