Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux.git] / drivers / dma / mmp_tdma.c
index 33f96aaa80c759aff2f8098e2135dd6f1b67b90a..724f7f4c9720dba720691911a3eb96d68fbe76a0 100644 (file)
@@ -22,6 +22,7 @@
 #include <mach/regs-icu.h>
 #include <linux/platform_data/dma-mmp_tdma.h>
 #include <linux/of_device.h>
+#include <linux/of_dma.h>
 
 #include "dmaengine.h"
 
@@ -541,6 +542,45 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
        return 0;
 }
 
+struct mmp_tdma_filter_param {
+       struct device_node *of_node;
+       unsigned int chan_id;
+};
+
+static bool mmp_tdma_filter_fn(struct dma_chan *chan, void *fn_param)
+{
+       struct mmp_tdma_filter_param *param = fn_param;
+       struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+       struct dma_device *pdma_device = tdmac->chan.device;
+
+       if (pdma_device->dev->of_node != param->of_node)
+               return false;
+
+       if (chan->chan_id != param->chan_id)
+               return false;
+
+       return true;
+}
+
+struct dma_chan *mmp_tdma_xlate(struct of_phandle_args *dma_spec,
+                              struct of_dma *ofdma)
+{
+       struct mmp_tdma_device *tdev = ofdma->of_dma_data;
+       dma_cap_mask_t mask = tdev->device.cap_mask;
+       struct mmp_tdma_filter_param param;
+
+       if (dma_spec->args_count != 1)
+               return NULL;
+
+       param.of_node = ofdma->of_node;
+       param.chan_id = dma_spec->args[0];
+
+       if (param.chan_id >= TDMA_CHANNEL_NUM)
+               return NULL;
+
+       return dma_request_channel(mask, mmp_tdma_filter_fn, &param);
+}
+
 static struct of_device_id mmp_tdma_dt_ids[] = {
        { .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA},
        { .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU},
@@ -631,6 +671,16 @@ static int mmp_tdma_probe(struct platform_device *pdev)
                return ret;
        }
 
+       if (pdev->dev.of_node) {
+               ret = of_dma_controller_register(pdev->dev.of_node,
+                                                       mmp_tdma_xlate, tdev);
+               if (ret) {
+                       dev_err(tdev->device.dev,
+                               "failed to register controller\n");
+                       dma_async_device_unregister(&tdev->device);
+               }
+       }
+
        dev_info(tdev->device.dev, "initialized\n");
        return 0;
 }