ARM/dmaengine: edma: Public API to use private struct pointer
authorPeter Ujfalusi <peter.ujfalusi@ti.com>
Wed, 14 Oct 2015 11:42:49 +0000 (14:42 +0300)
committerVinod Koul <vinod.koul@intel.com>
Wed, 14 Oct 2015 14:27:11 +0000 (19:57 +0530)
Instead of relying on indexes pointing to edma private date in the global
pointer array, pass the private data pointer via the public API.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
arch/arm/common/edma.c
drivers/dma/edma.c
include/linux/platform_data/edma.h

index 0b4c0ee59ed9bc2fb8ee1a852c2607c97fc8846f..03692520812a34017dac586eb9221807bf9a05f1 100644 (file)
@@ -130,7 +130,7 @@ struct edma {
 
        struct edma_soc_info *info;
        int             id;
-
+       bool            unused_chan_list_done;
        /* The edma_inuse bit for each PaRAM slot is clear unless the
         * channel is in use ... by ARM or DSP, for QDMA, or whatever.
         */
@@ -264,7 +264,6 @@ static inline void clear_bits(int offset, int len, unsigned long *p)
 }
 
 /*****************************************************************************/
-static struct edma *edma_cc[EDMA_MAX_CC];
 static int arch_num_cc;
 
 /* dummy param set used to (re)initialize parameter RAM slots */
@@ -490,14 +489,18 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data)
 static int prepare_unused_channel_list(struct device *dev, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       int i, count, ctlr;
+       struct edma *cc = data;
+       int i, count;
        struct of_phandle_args  dma_spec;
 
        if (dev->of_node) {
+               struct platform_device *dma_pdev;
+
                count = of_property_count_strings(dev->of_node, "dma-names");
                if (count < 0)
                        return 0;
                for (i = 0; i < count; i++) {
+
                        if (of_parse_phandle_with_args(dev->of_node, "dmas",
                                                       "#dma-cells", i,
                                                       &dma_spec))
@@ -508,8 +511,12 @@ static int prepare_unused_channel_list(struct device *dev, void *data)
                                continue;
                        }
 
+                       dma_pdev = of_find_device_by_node(dma_spec.np);
+                       if (&dma_pdev->dev != cc->dev)
+                               continue;
+
                        clear_bit(EDMA_CHAN_SLOT(dma_spec.args[0]),
-                                 edma_cc[0]->edma_unused);
+                                 cc->edma_unused);
                        of_node_put(dma_spec.np);
                }
                return 0;
@@ -517,11 +524,11 @@ static int prepare_unused_channel_list(struct device *dev, void *data)
 
        /* For non-OF case */
        for (i = 0; i < pdev->num_resources; i++) {
-               if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
-                               (int)pdev->resource[i].start >= 0) {
-                       ctlr = EDMA_CTLR(pdev->resource[i].start);
+               struct resource *res = &pdev->resource[i];
+
+               if ((res->flags & IORESOURCE_DMA) && (int)res->start >= 0) {
                        clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
-                                 edma_cc[ctlr]->edma_unused);
+                                 cc->edma_unused);
                }
        }
 
@@ -530,8 +537,6 @@ static int prepare_unused_channel_list(struct device *dev, void *data)
 
 /*-----------------------------------------------------------------------*/
 
-static bool unused_chan_list_done;
-
 /* Resource alloc/free:  dma channels, parameter RAM slots */
 
 /**
@@ -564,77 +569,73 @@ static bool unused_chan_list_done;
  *
  * Returns the number of the channel, else negative errno.
  */
-int edma_alloc_channel(int channel,
+int edma_alloc_channel(struct edma *cc, int channel,
                void (*callback)(unsigned channel, u16 ch_status, void *data),
                void *data,
                enum dma_event_q eventq_no)
 {
-       unsigned i, done = 0, ctlr = 0;
+       unsigned done = 0;
        int ret = 0;
 
-       if (!unused_chan_list_done) {
+       if (!cc->unused_chan_list_done) {
                /*
                 * Scan all the platform devices to find out the EDMA channels
                 * used and clear them in the unused list, making the rest
                 * available for ARM usage.
                 */
-               ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
-                               prepare_unused_channel_list);
+               ret = bus_for_each_dev(&platform_bus_type, NULL, cc,
+                                      prepare_unused_channel_list);
                if (ret < 0)
                        return ret;
 
-               unused_chan_list_done = true;
+               cc->unused_chan_list_done = true;
        }
 
        if (channel >= 0) {
-               ctlr = EDMA_CTLR(channel);
+               if (cc->id != EDMA_CTLR(channel)) {
+                       dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n",
+                               __func__, cc->id, EDMA_CTLR(channel));
+                       return -EINVAL;
+               }
                channel = EDMA_CHAN_SLOT(channel);
        }
 
        if (channel < 0) {
-               for (i = 0; i < arch_num_cc; i++) {
-                       channel = 0;
-                       for (;;) {
-                               channel = find_next_bit(edma_cc[i]->edma_unused,
-                                               edma_cc[i]->num_channels,
-                                               channel);
-                               if (channel == edma_cc[i]->num_channels)
-                                       break;
-                               if (!test_and_set_bit(channel,
-                                               edma_cc[i]->edma_inuse)) {
-                                       done = 1;
-                                       ctlr = i;
-                                       break;
-                               }
-                               channel++;
-                       }
-                       if (done)
+               channel = 0;
+               for (;;) {
+                       channel = find_next_bit(cc->edma_unused,
+                                               cc->num_channels, channel);
+                       if (channel == cc->num_channels)
+                               break;
+                       if (!test_and_set_bit(channel, cc->edma_inuse)) {
+                               done = 1;
                                break;
+                       }
+                       channel++;
                }
                if (!done)
                        return -ENOMEM;
-       } else if (channel >= edma_cc[ctlr]->num_channels) {
+       } else if (channel >= cc->num_channels) {
                return -EINVAL;
-       } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
+       } else if (test_and_set_bit(channel, cc->edma_inuse)) {
                return -EBUSY;
        }
 
        /* ensure access through shadow region 0 */
-       edma_or_array2(edma_cc[ctlr], EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
+       edma_or_array2(cc, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
 
        /* ensure no events are pending */
-       edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
-       memcpy_toio(edma_cc[ctlr]->base + PARM_OFFSET(channel), &dummy_paramset,
+       edma_stop(cc, EDMA_CTLR_CHAN(cc->id, channel));
+       memcpy_toio(cc->base + PARM_OFFSET(channel), &dummy_paramset,
                    PARM_SIZE);
 
        if (callback)
-               setup_dma_interrupt(edma_cc[ctlr],
-                                   EDMA_CTLR_CHAN(ctlr, channel), callback,
-                                   data);
+               setup_dma_interrupt(cc, EDMA_CTLR_CHAN(cc->id, channel),
+                                   callback, data);
 
-       map_dmach_queue(edma_cc[ctlr], channel, eventq_no);
+       map_dmach_queue(cc, channel, eventq_no);
 
-       return EDMA_CTLR_CHAN(ctlr, channel);
+       return EDMA_CTLR_CHAN(cc->id, channel);
 }
 EXPORT_SYMBOL(edma_alloc_channel);
 
@@ -650,22 +651,25 @@ EXPORT_SYMBOL(edma_alloc_channel);
  * will not be reactivated by linking, chaining, or software calls to
  * edma_start().
  */
-void edma_free_channel(unsigned channel)
+void edma_free_channel(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
 
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel >= edma_cc[ctlr]->num_channels)
+       if (channel >= cc->num_channels)
                return;
 
-       setup_dma_interrupt(edma_cc[ctlr], channel, NULL, NULL);
+       setup_dma_interrupt(cc, channel, NULL, NULL);
        /* REVISIT should probably take out of shadow region 0 */
 
-       memcpy_toio(edma_cc[ctlr]->base + PARM_OFFSET(channel), &dummy_paramset,
+       memcpy_toio(cc->base + PARM_OFFSET(channel), &dummy_paramset,
                    PARM_SIZE);
-       clear_bit(channel, edma_cc[ctlr]->edma_inuse);
+       clear_bit(channel, cc->edma_inuse);
 }
 EXPORT_SYMBOL(edma_free_channel);
 
@@ -683,35 +687,29 @@ EXPORT_SYMBOL(edma_free_channel);
  *
  * Returns the number of the slot, else negative errno.
  */
-int edma_alloc_slot(unsigned ctlr, int slot)
+int edma_alloc_slot(struct edma *cc, int slot)
 {
-       if (!edma_cc[ctlr])
-               return -EINVAL;
-
-       if (slot >= 0)
+       if (slot > 0)
                slot = EDMA_CHAN_SLOT(slot);
-
        if (slot < 0) {
-               slot = edma_cc[ctlr]->num_channels;
+               slot = cc->num_channels;
                for (;;) {
-                       slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
-                                       edma_cc[ctlr]->num_slots, slot);
-                       if (slot == edma_cc[ctlr]->num_slots)
+                       slot = find_next_zero_bit(cc->edma_inuse, cc->num_slots,
+                                                 slot);
+                       if (slot == cc->num_slots)
                                return -ENOMEM;
-                       if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
+                       if (!test_and_set_bit(slot, cc->edma_inuse))
                                break;
                }
-       } else if (slot < edma_cc[ctlr]->num_channels ||
-                       slot >= edma_cc[ctlr]->num_slots) {
+       } else if (slot < cc->num_channels || slot >= cc->num_slots) {
                return -EINVAL;
-       } else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
+       } else if (test_and_set_bit(slot, cc->edma_inuse)) {
                return -EBUSY;
        }
 
-       memcpy_toio(edma_cc[ctlr]->base + PARM_OFFSET(slot), &dummy_paramset,
-                   PARM_SIZE);
+       memcpy_toio(cc->base + PARM_OFFSET(slot), &dummy_paramset, PARM_SIZE);
 
-       return EDMA_CTLR_CHAN(ctlr, slot);
+       return slot;
 }
 EXPORT_SYMBOL(edma_alloc_slot);
 
@@ -723,20 +721,15 @@ EXPORT_SYMBOL(edma_alloc_slot);
  * Callers are responsible for ensuring the slot is inactive, and will
  * not be activated.
  */
-void edma_free_slot(unsigned slot)
+void edma_free_slot(struct edma *cc, unsigned slot)
 {
-       unsigned ctlr;
 
-       ctlr = EDMA_CTLR(slot);
        slot = EDMA_CHAN_SLOT(slot);
-
-       if (slot < edma_cc[ctlr]->num_channels ||
-               slot >= edma_cc[ctlr]->num_slots)
+       if (slot < cc->num_channels || slot >= cc->num_slots)
                return;
 
-       memcpy_toio(edma_cc[ctlr]->base + PARM_OFFSET(slot), &dummy_paramset,
-                   PARM_SIZE);
-       clear_bit(slot, edma_cc[ctlr]->edma_inuse);
+       memcpy_toio(cc->base + PARM_OFFSET(slot), &dummy_paramset, PARM_SIZE);
+       clear_bit(slot, cc->edma_inuse);
 }
 EXPORT_SYMBOL(edma_free_slot);
 
@@ -751,16 +744,15 @@ EXPORT_SYMBOL(edma_free_slot);
  *
  * Returns the position of the current active slot
  */
-dma_addr_t edma_get_position(unsigned slot, bool dst)
+dma_addr_t edma_get_position(struct edma *cc, unsigned slot, bool dst)
 {
-       u32 offs, ctlr = EDMA_CTLR(slot);
+       u32 offs;
 
        slot = EDMA_CHAN_SLOT(slot);
-
        offs = PARM_OFFSET(slot);
        offs += dst ? PARM_DST : PARM_SRC;
 
-       return edma_read(edma_cc[ctlr], offs);
+       return edma_read(cc, offs);
 }
 
 /**
@@ -770,21 +762,15 @@ dma_addr_t edma_get_position(unsigned slot, bool dst)
  *
  * The originating slot should not be part of any active DMA transfer.
  */
-void edma_link(unsigned from, unsigned to)
+void edma_link(struct edma *cc, unsigned from, unsigned to)
 {
-       unsigned ctlr_from, ctlr_to;
-
-       ctlr_from = EDMA_CTLR(from);
        from = EDMA_CHAN_SLOT(from);
-       ctlr_to = EDMA_CTLR(to);
        to = EDMA_CHAN_SLOT(to);
-
-       if (from >= edma_cc[ctlr_from]->num_slots)
+       if (from >= cc->num_slots || to >= cc->num_slots)
                return;
-       if (to >= edma_cc[ctlr_to]->num_slots)
-               return;
-       edma_parm_modify(edma_cc[ctlr_from], PARM_LINK_BCNTRLD, from, 0xffff0000,
-                               PARM_OFFSET(to));
+
+       edma_parm_modify(cc, PARM_LINK_BCNTRLD, from, 0xffff0000,
+                        PARM_OFFSET(to));
 }
 EXPORT_SYMBOL(edma_link);
 
@@ -802,16 +788,13 @@ EXPORT_SYMBOL(edma_link);
  * calls to set up those parameters in small pieces, and provides
  * complete control over all transfer options.
  */
-void edma_write_slot(unsigned slot, const struct edmacc_param *param)
+void edma_write_slot(struct edma *cc, unsigned slot,
+                    const struct edmacc_param *param)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(slot);
        slot = EDMA_CHAN_SLOT(slot);
-
-       if (slot >= edma_cc[ctlr]->num_slots)
+       if (slot >= cc->num_slots)
                return;
-       memcpy_toio(edma_cc[ctlr]->base + PARM_OFFSET(slot), param, PARM_SIZE);
+       memcpy_toio(cc->base + PARM_OFFSET(slot), param, PARM_SIZE);
 }
 EXPORT_SYMBOL(edma_write_slot);
 
@@ -823,17 +806,12 @@ EXPORT_SYMBOL(edma_write_slot);
  * Use this to read data from a parameter RAM slot, perhaps to
  * save them as a template for later reuse.
  */
-void edma_read_slot(unsigned slot, struct edmacc_param *param)
+void edma_read_slot(struct edma *cc, unsigned slot, struct edmacc_param *param)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(slot);
        slot = EDMA_CHAN_SLOT(slot);
-
-       if (slot >= edma_cc[ctlr]->num_slots)
+       if (slot >= cc->num_slots)
                return;
-       memcpy_fromio(param, edma_cc[ctlr]->base + PARM_OFFSET(slot),
-                     PARM_SIZE);
+       memcpy_fromio(param, cc->base + PARM_OFFSET(slot), PARM_SIZE);
 }
 EXPORT_SYMBOL(edma_read_slot);
 
@@ -848,18 +826,19 @@ EXPORT_SYMBOL(edma_read_slot);
  * This temporarily disables EDMA hardware events on the specified channel,
  * preventing them from triggering new transfers on its behalf
  */
-void edma_pause(unsigned channel)
+void edma_pause(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel < edma_cc[ctlr]->num_channels) {
+       if (channel < cc->num_channels) {
                unsigned int mask = BIT(channel & 0x1f);
 
-               edma_shadow0_write_array(edma_cc[ctlr], SH_EECR, channel >> 5,
-                                        mask);
+               edma_shadow0_write_array(cc, SH_EECR, channel >> 5, mask);
        }
 }
 EXPORT_SYMBOL(edma_pause);
@@ -870,36 +849,39 @@ EXPORT_SYMBOL(edma_pause);
  *
  * This re-enables EDMA hardware events on the specified channel.
  */
-void edma_resume(unsigned channel)
+void edma_resume(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel < edma_cc[ctlr]->num_channels) {
+       if (channel < cc->num_channels) {
                unsigned int mask = BIT(channel & 0x1f);
 
-               edma_shadow0_write_array(edma_cc[ctlr], SH_EESR, channel >> 5,
-                                        mask);
+               edma_shadow0_write_array(cc, SH_EESR, channel >> 5, mask);
        }
 }
 EXPORT_SYMBOL(edma_resume);
 
-int edma_trigger_channel(unsigned channel)
+int edma_trigger_channel(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
        unsigned int mask;
 
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return -EINVAL;
+       }
        channel = EDMA_CHAN_SLOT(channel);
        mask = BIT(channel & 0x1f);
 
-       edma_shadow0_write_array(edma_cc[ctlr], SH_ESR, (channel >> 5), mask);
+       edma_shadow0_write_array(cc, SH_ESR, (channel >> 5), mask);
 
        pr_debug("EDMA: ESR%d %08x\n", (channel >> 5),
-                edma_shadow0_read_array(edma_cc[ctlr], SH_ESR,
-                                        (channel >> 5)));
+                edma_shadow0_read_array(cc, SH_ESR, (channel >> 5)));
        return 0;
 }
 EXPORT_SYMBOL(edma_trigger_channel);
@@ -915,15 +897,16 @@ EXPORT_SYMBOL(edma_trigger_channel);
  *
  * Returns zero on success, else negative errno.
  */
-int edma_start(unsigned channel)
+int edma_start(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return -EINVAL;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel < edma_cc[ctlr]->num_channels) {
-               struct edma *cc = edma_cc[ctlr];
+       if (channel < cc->num_channels) {
                int j = channel >> 5;
                unsigned int mask = BIT(channel & 0x1f);
 
@@ -962,15 +945,16 @@ EXPORT_SYMBOL(edma_start);
  * may not be resumed, and the channel's Parameter RAM should be
  * reinitialized before being reused.
  */
-void edma_stop(unsigned channel)
+void edma_stop(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel < edma_cc[ctlr]->num_channels) {
-               struct edma *cc = edma_cc[ctlr];
+       if (channel < cc->num_channels) {
                int j = channel >> 5;
                unsigned int mask = BIT(channel & 0x1f);
 
@@ -1005,15 +989,16 @@ EXPORT_SYMBOL(edma_stop);
  *
  *****************************************************************************/
 
-void edma_clean_channel(unsigned channel)
+void edma_clean_channel(struct edma *cc, unsigned channel)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel < edma_cc[ctlr]->num_channels) {
-               struct edma *cc = edma_cc[ctlr];
+       if (channel < cc->num_channels) {
                int j = (channel >> 5);
                unsigned int mask = BIT(channel & 0x1f);
 
@@ -1037,26 +1022,35 @@ EXPORT_SYMBOL(edma_clean_channel);
  *
  * Can be used to move a channel to a selected event queue.
  */
-void edma_assign_channel_eventq(unsigned channel, enum dma_event_q eventq_no)
+void edma_assign_channel_eventq(struct edma *cc, unsigned channel,
+                               enum dma_event_q eventq_no)
 {
-       unsigned ctlr;
-
-       ctlr = EDMA_CTLR(channel);
+       if (cc->id != EDMA_CTLR(channel)) {
+               dev_err(cc->dev, "%s: ID mismatch for eDMA%d: %d\n", __func__,
+                       cc->id, EDMA_CTLR(channel));
+               return;
+       }
        channel = EDMA_CHAN_SLOT(channel);
 
-       if (channel >= edma_cc[ctlr]->num_channels)
+       if (channel >= cc->num_channels)
                return;
 
        /* default to low priority queue */
        if (eventq_no == EVENTQ_DEFAULT)
-               eventq_no = edma_cc[ctlr]->default_queue;
-       if (eventq_no >= edma_cc[ctlr]->num_tc)
+               eventq_no = cc->default_queue;
+       if (eventq_no >= cc->num_tc)
                return;
 
-       map_dmach_queue(edma_cc[ctlr], channel, eventq_no);
+       map_dmach_queue(cc, channel, eventq_no);
 }
 EXPORT_SYMBOL(edma_assign_channel_eventq);
 
+struct edma *edma_get_data(struct device *edma_dev)
+{
+       return dev_get_drvdata(edma_dev);
+}
+
+
 static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
                              struct edma *edma_cc, int cc_id)
 {
@@ -1278,11 +1272,10 @@ static int edma_probe(struct platform_device *pdev)
                }
        }
 
-       edma_cc[dev_id] = devm_kzalloc(dev, sizeof(struct edma), GFP_KERNEL);
-       if (!edma_cc[dev_id])
+       cc = devm_kzalloc(dev, sizeof(struct edma), GFP_KERNEL);
+       if (!cc)
                return -ENOMEM;
 
-       cc = edma_cc[dev_id];
        cc->dev = dev;
        cc->id = dev_id;
        dev_set_drvdata(dev, cc);
index fcb4680efed7b78887767f74aed2c9f66152ddaa..53d48b2a700d98857e7d7331e747c1f69617031e 100644 (file)
@@ -119,6 +119,7 @@ struct edma_chan {
 };
 
 struct edma_cc {
+       struct edma                     *cc;
        int                             ctlr;
        struct dma_device               dma_slave;
        struct edma_chan                slave_chans[EDMA_CHANS];
@@ -150,6 +151,7 @@ static void edma_desc_free(struct virt_dma_desc *vdesc)
 /* Dispatch a queued descriptor to the controller (caller holds lock) */
 static void edma_execute(struct edma_chan *echan)
 {
+       struct edma *cc = echan->ecc->cc;
        struct virt_dma_desc *vdesc;
        struct edma_desc *edesc;
        struct device *dev = echan->vchan.chan.device->dev;
@@ -174,7 +176,7 @@ static void edma_execute(struct edma_chan *echan)
        /* Write descriptor PaRAM set(s) */
        for (i = 0; i < nslots; i++) {
                j = i + edesc->processed;
-               edma_write_slot(echan->slot[i], &edesc->pset[j].param);
+               edma_write_slot(cc, echan->slot[i], &edesc->pset[j].param);
                edesc->sg_len += edesc->pset[j].len;
                dev_vdbg(echan->vchan.chan.device->dev,
                        "\n pset[%d]:\n"
@@ -199,7 +201,7 @@ static void edma_execute(struct edma_chan *echan)
                        edesc->pset[j].param.link_bcntrld);
                /* Link to the previous slot if not the last set */
                if (i != (nslots - 1))
-                       edma_link(echan->slot[i], echan->slot[i+1]);
+                       edma_link(cc, echan->slot[i], echan->slot[i+1]);
        }
 
        edesc->processed += nslots;
@@ -211,9 +213,9 @@ static void edma_execute(struct edma_chan *echan)
         */
        if (edesc->processed == edesc->pset_nr) {
                if (edesc->cyclic)
-                       edma_link(echan->slot[nslots-1], echan->slot[1]);
+                       edma_link(cc, echan->slot[nslots-1], echan->slot[1]);
                else
-                       edma_link(echan->slot[nslots-1],
+                       edma_link(cc, echan->slot[nslots-1],
                                  echan->ecc->dummy_slot);
        }
 
@@ -224,19 +226,19 @@ static void edma_execute(struct edma_chan *echan)
                 * transfers of MAX_NR_SG
                 */
                dev_dbg(dev, "missed event on channel %d\n", echan->ch_num);
-               edma_clean_channel(echan->ch_num);
-               edma_stop(echan->ch_num);
-               edma_start(echan->ch_num);
-               edma_trigger_channel(echan->ch_num);
+               edma_clean_channel(cc, echan->ch_num);
+               edma_stop(cc, echan->ch_num);
+               edma_start(cc, echan->ch_num);
+               edma_trigger_channel(cc, echan->ch_num);
                echan->missed = 0;
        } else if (edesc->processed <= MAX_NR_SG) {
                dev_dbg(dev, "first transfer starting on channel %d\n",
                        echan->ch_num);
-               edma_start(echan->ch_num);
+               edma_start(cc, echan->ch_num);
        } else {
                dev_dbg(dev, "chan: %d: completed %d elements, resuming\n",
                        echan->ch_num, edesc->processed);
-               edma_resume(echan->ch_num);
+               edma_resume(cc, echan->ch_num);
        }
 }
 
@@ -254,10 +256,11 @@ static int edma_terminate_all(struct dma_chan *chan)
         * echan->edesc is NULL and exit.)
         */
        if (echan->edesc) {
-               edma_stop(echan->ch_num);
+               edma_stop(echan->ecc->cc, echan->ch_num);
                /* Move the cyclic channel back to default queue */
                if (echan->edesc->cyclic)
-                       edma_assign_channel_eventq(echan->ch_num,
+                       edma_assign_channel_eventq(echan->ecc->cc,
+                                                  echan->ch_num,
                                                   EVENTQ_DEFAULT);
                /*
                 * free the running request descriptor
@@ -295,7 +298,7 @@ static int edma_dma_pause(struct dma_chan *chan)
        if (!echan->edesc)
                return -EINVAL;
 
-       edma_pause(echan->ch_num);
+       edma_pause(echan->ecc->cc, echan->ch_num);
        return 0;
 }
 
@@ -303,7 +306,7 @@ static int edma_dma_resume(struct dma_chan *chan)
 {
        struct edma_chan *echan = to_edma_chan(chan);
 
-       edma_resume(echan->ch_num);
+       edma_resume(echan->ecc->cc, echan->ch_num);
        return 0;
 }
 
@@ -485,8 +488,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
        for (i = 0; i < nslots; i++) {
                if (echan->slot[i] < 0) {
                        echan->slot[i] =
-                               edma_alloc_slot(EDMA_CTLR(echan->ch_num),
-                                               EDMA_SLOT_ANY);
+                               edma_alloc_slot(echan->ecc->cc, EDMA_SLOT_ANY);
                        if (echan->slot[i] < 0) {
                                kfree(edesc);
                                dev_err(dev, "%s: Failed to allocate slot\n",
@@ -641,8 +643,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
                /* Allocate a PaRAM slot, if needed */
                if (echan->slot[i] < 0) {
                        echan->slot[i] =
-                               edma_alloc_slot(EDMA_CTLR(echan->ch_num),
-                                               EDMA_SLOT_ANY);
+                               edma_alloc_slot(echan->ecc->cc, EDMA_SLOT_ANY);
                        if (echan->slot[i] < 0) {
                                kfree(edesc);
                                dev_err(dev, "%s: Failed to allocate slot\n",
@@ -703,7 +704,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
        }
 
        /* Place the cyclic channel to highest priority queue */
-       edma_assign_channel_eventq(echan->ch_num, EVENTQ_0);
+       edma_assign_channel_eventq(echan->ecc->cc, echan->ch_num, EVENTQ_0);
 
        return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
 }
@@ -711,6 +712,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
 static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
 {
        struct edma_chan *echan = data;
+       struct edma *cc = echan->ecc->cc;
        struct device *dev = echan->vchan.chan.device->dev;
        struct edma_desc *edesc;
        struct edmacc_param p;
@@ -727,13 +729,13 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
                        } else if (edesc->processed == edesc->pset_nr) {
                                dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num);
                                edesc->residue = 0;
-                               edma_stop(echan->ch_num);
+                               edma_stop(cc, echan->ch_num);
                                vchan_cookie_complete(&edesc->vdesc);
                                echan->edesc = NULL;
                        } else {
                                dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num);
 
-                               edma_pause(echan->ch_num);
+                               edma_pause(cc, echan->ch_num);
 
                                /* Update statistics for tx_status */
                                edesc->residue -= edesc->sg_len;
@@ -744,7 +746,7 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
                }
                break;
        case EDMA_DMA_CC_ERROR:
-               edma_read_slot(EDMA_CHAN_SLOT(echan->slot[0]), &p);
+               edma_read_slot(cc, echan->slot[0], &p);
 
                /*
                 * Issue later based on missed flag which will be sure
@@ -767,10 +769,10 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
                         * missed, so its safe to issue it here.
                         */
                        dev_dbg(dev, "Error occurred but slot is non-null, TRIGGERING\n");
-                       edma_clean_channel(echan->ch_num);
-                       edma_stop(echan->ch_num);
-                       edma_start(echan->ch_num);
-                       edma_trigger_channel(echan->ch_num);
+                       edma_clean_channel(cc, echan->ch_num);
+                       edma_stop(cc, echan->ch_num);
+                       edma_start(cc, echan->ch_num);
+                       edma_trigger_channel(cc, echan->ch_num);
                }
                break;
        default:
@@ -789,8 +791,8 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
        int a_ch_num;
        LIST_HEAD(descs);
 
-       a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
-                                       echan, EVENTQ_DEFAULT);
+       a_ch_num = edma_alloc_channel(echan->ecc->cc, echan->ch_num,
+                                     edma_callback, echan, EVENTQ_DEFAULT);
 
        if (a_ch_num < 0) {
                ret = -ENODEV;
@@ -814,7 +816,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
        return 0;
 
 err_wrong_chan:
-       edma_free_channel(a_ch_num);
+       edma_free_channel(echan->ecc->cc, a_ch_num);
 err_no_chan:
        return ret;
 }
@@ -827,21 +829,21 @@ static void edma_free_chan_resources(struct dma_chan *chan)
        int i;
 
        /* Terminate transfers */
-       edma_stop(echan->ch_num);
+       edma_stop(echan->ecc->cc, echan->ch_num);
 
        vchan_free_chan_resources(&echan->vchan);
 
        /* Free EDMA PaRAM slots */
        for (i = 1; i < EDMA_MAX_SLOTS; i++) {
                if (echan->slot[i] >= 0) {
-                       edma_free_slot(echan->slot[i]);
+                       edma_free_slot(echan->ecc->cc, echan->slot[i]);
                        echan->slot[i] = -1;
                }
        }
 
        /* Free EDMA channel */
        if (echan->alloced) {
-               edma_free_channel(echan->ch_num);
+               edma_free_channel(echan->ecc->cc, echan->ch_num);
                echan->alloced = false;
        }
 
@@ -871,7 +873,8 @@ static u32 edma_residue(struct edma_desc *edesc)
         * We always read the dst/src position from the first RamPar
         * pset. That's the one which is active now.
         */
-       pos = edma_get_position(edesc->echan->slot[0], dst);
+       pos = edma_get_position(edesc->echan->ecc->cc, edesc->echan->slot[0],
+                               dst);
 
        /*
         * Cyclic is simple. Just subtract pset[0].addr from pos.
@@ -1008,8 +1011,12 @@ static int edma_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       ecc->cc = edma_get_data(pdev->dev.parent);
+       if (!ecc->cc)
+               return -ENODEV;
+
        ecc->ctlr = pdev->id;
-       ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
+       ecc->dummy_slot = edma_alloc_slot(ecc->cc, EDMA_SLOT_ANY);
        if (ecc->dummy_slot < 0) {
                dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
                return ecc->dummy_slot;
@@ -1042,7 +1049,7 @@ static int edma_probe(struct platform_device *pdev)
        return 0;
 
 err_reg1:
-       edma_free_slot(ecc->dummy_slot);
+       edma_free_slot(ecc->cc, ecc->dummy_slot);
        return ret;
 }
 
@@ -1055,7 +1062,7 @@ static int edma_remove(struct platform_device *pdev)
        if (parent_node)
                of_dma_controller_free(parent_node);
        dma_async_device_unregister(&ecc->dma_slave);
-       edma_free_slot(ecc->dummy_slot);
+       edma_free_slot(ecc->cc, ecc->dummy_slot);
 
        return 0;
 }
index c1862423b356329471b85a0435bd510670f27604..466021c031691272be8939d4c1cde7c2e1164f7c 100644 (file)
@@ -92,32 +92,40 @@ enum dma_event_q {
 
 #define EDMA_MAX_CC               2
 
+struct edma;
+
+struct edma *edma_get_data(struct device *edma_dev);
+
 /* alloc/free DMA channels and their dedicated parameter RAM slots */
-int edma_alloc_channel(int channel,
+int edma_alloc_channel(struct edma *cc, int channel,
        void (*callback)(unsigned channel, u16 ch_status, void *data),
        void *data, enum dma_event_q);
-void edma_free_channel(unsigned channel);
+void edma_free_channel(struct edma *cc, unsigned channel);
 
 /* alloc/free parameter RAM slots */
-int edma_alloc_slot(unsigned ctlr, int slot);
-void edma_free_slot(unsigned slot);
+int edma_alloc_slot(struct edma *cc, int slot);
+void edma_free_slot(struct edma *cc, unsigned slot);
 
 /* calls that operate on part of a parameter RAM slot */
-dma_addr_t edma_get_position(unsigned slot, bool dst);
-void edma_link(unsigned from, unsigned to);
+dma_addr_t edma_get_position(struct edma *cc, unsigned slot, bool dst);
+void edma_link(struct edma *cc, unsigned from, unsigned to);
 
 /* calls that operate on an entire parameter RAM slot */
-void edma_write_slot(unsigned slot, const struct edmacc_param *params);
-void edma_read_slot(unsigned slot, struct edmacc_param *params);
+void edma_write_slot(struct edma *cc, unsigned slot,
+                    const struct edmacc_param *params);
+void edma_read_slot(struct edma *cc, unsigned slot,
+                   struct edmacc_param *params);
 
 /* channel control operations */
-int edma_start(unsigned channel);
-void edma_stop(unsigned channel);
-void edma_clean_channel(unsigned channel);
-void edma_pause(unsigned channel);
-void edma_resume(unsigned channel);
+int edma_start(struct edma *cc, unsigned channel);
+void edma_stop(struct edma *cc, unsigned channel);
+void edma_clean_channel(struct edma *cc, unsigned channel);
+void edma_pause(struct edma *cc, unsigned channel);
+void edma_resume(struct edma *cc, unsigned channel);
+int edma_trigger_channel(struct edma *cc, unsigned channel);
 
-void edma_assign_channel_eventq(unsigned channel, enum dma_event_q eventq_no);
+void edma_assign_channel_eventq(struct edma *cc, unsigned channel,
+                               enum dma_event_q eventq_no);
 
 struct edma_rsv_info {
 
@@ -141,6 +149,4 @@ struct edma_soc_info {
        const s16       (*xbar_chans)[2];
 };
 
-int edma_trigger_channel(unsigned);
-
 #endif