dma: coh901318: add devicetree support
authorLinus Walleij <linus.walleij@linaro.org>
Fri, 19 Apr 2013 11:42:55 +0000 (13:42 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 17 Jun 2013 11:54:27 +0000 (13:54 +0200)
This adds support for probing the COH 901 318 DMA controller
and channels from the device tree.

Contains portions of a sketch patch from Arnd Bergmann.

Cc: Arnd Bergmann <arnd@arndb.de>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Documentation/devicetree/bindings/dma/ste-coh901318.txt [new file with mode: 0644]
drivers/dma/coh901318.c

diff --git a/Documentation/devicetree/bindings/dma/ste-coh901318.txt b/Documentation/devicetree/bindings/dma/ste-coh901318.txt
new file mode 100644 (file)
index 0000000..091ad05
--- /dev/null
@@ -0,0 +1,32 @@
+ST-Ericsson COH 901 318 DMA Controller
+
+This is a DMA controller which has begun as a fork of the
+ARM PL08x PrimeCell VHDL code.
+
+Required properties:
+- compatible: should be "stericsson,coh901318"
+- reg: register locations and length
+- interrupts: the single DMA IRQ
+- #dma-cells: must be set to <1>, as the channels on the
+  COH 901 318 are simple and identified by a single number
+- dma-channels: the number of DMA channels handled
+
+Example:
+
+dmac: dma-controller@c00020000 {
+       compatible = "stericsson,coh901318";
+       reg = <0xc0020000 0x1000>;
+       interrupt-parent = <&vica>;
+       interrupts = <2>;
+       #dma-cells = <1>;
+       dma-channels = <40>;
+};
+
+Consumers example:
+
+uart0: serial@c0013000 {
+       compatible = "...";
+       (...)
+       dmas = <&dmac 17 &dmac 18>;
+       dma-names = "tx", "rx";
+};
index 3b23061cdb41bd0e963a5160bb4fbd7edf62de2d..9bfaddd57ef1ab80c301a7d38b8c40e898e047c1 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/uaccess.h>
 #include <linux/debugfs.h>
 #include <linux/platform_data/dma-coh901318.h>
+#include <linux/of_dma.h>
 
 #include "coh901318.h"
 #include "dmaengine.h"
@@ -1788,6 +1789,35 @@ bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
 }
 EXPORT_SYMBOL(coh901318_filter_id);
 
+struct coh901318_filter_args {
+       struct coh901318_base *base;
+       unsigned int ch_nr;
+};
+
+static bool coh901318_filter_base_and_id(struct dma_chan *chan, void *data)
+{
+       struct coh901318_filter_args *args = data;
+
+       if (&args->base->dma_slave == chan->device &&
+           args->ch_nr == to_coh901318_chan(chan)->id)
+               return true;
+
+       return false;
+}
+
+static struct dma_chan *coh901318_xlate(struct of_phandle_args *dma_spec,
+                                       struct of_dma *ofdma)
+{
+       struct coh901318_filter_args args = {
+               .base = ofdma->of_dma_data,
+               .ch_nr = dma_spec->args[0],
+       };
+       dma_cap_mask_t cap;
+       dma_cap_zero(cap);
+       dma_cap_set(DMA_SLAVE, cap);
+
+       return dma_request_channel(cap, coh901318_filter_base_and_id, &args);
+}
 /*
  * DMA channel allocation
  */
@@ -2735,12 +2765,19 @@ static int __init coh901318_probe(struct platform_device *pdev)
        if (err)
                goto err_register_memcpy;
 
+       err = of_dma_controller_register(pdev->dev.of_node, coh901318_xlate,
+                                        base);
+       if (err)
+               goto err_register_of_dma;
+
        platform_set_drvdata(pdev, base);
        dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
                (u32) base->virtbase);
 
        return err;
 
+ err_register_of_dma:
+       dma_async_device_unregister(&base->dma_memcpy);
  err_register_memcpy:
        dma_async_device_unregister(&base->dma_slave);
  err_register_slave:
@@ -2752,17 +2789,23 @@ static int coh901318_remove(struct platform_device *pdev)
 {
        struct coh901318_base *base = platform_get_drvdata(pdev);
 
+       of_dma_controller_free(pdev->dev.of_node);
        dma_async_device_unregister(&base->dma_memcpy);
        dma_async_device_unregister(&base->dma_slave);
        coh901318_pool_destroy(&base->pool);
        return 0;
 }
 
+static const struct of_device_id coh901318_dt_match[] = {
+       { .compatible = "stericsson,coh901318" },
+       {},
+};
 
 static struct platform_driver coh901318_driver = {
        .remove = coh901318_remove,
        .driver = {
                .name   = "coh901318",
+               .of_match_table = coh901318_dt_match,
        },
 };