]> git.karo-electronics.de Git - linux-beck.git/commitdiff
DMA: shdma: switch DT mode to use configuration data from a match table
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Fri, 2 Aug 2013 14:50:36 +0000 (16:50 +0200)
committerVinod Koul <vinod.koul@intel.com>
Tue, 27 Aug 2013 08:55:09 +0000 (14:25 +0530)
This facilitates DMAC DT support by eliminating the need in AUXDATA and
avoiding creating complex DT data. This also fits well with DMAC devices,
of which SoCs often have multiple identical copies and it is perfectly
valid to use a single configuration data set for all of them.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski+renesas@gmail.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Documentation/devicetree/bindings/dma/shdma.txt
drivers/dma/sh/Makefile
drivers/dma/sh/shdma-base.c
drivers/dma/sh/shdma-of.c
drivers/dma/sh/shdma.h
drivers/dma/sh/shdmac.c [moved from drivers/dma/sh/shdma.c with 98% similarity]
drivers/dma/sh/sudmac.c
include/linux/shdma-base.h

index c15994aa19395154c5439a7c903cb9e26df9038d..2a3f3b8946b998dfde5d2f8b33523fb5e64643ad 100644 (file)
@@ -22,42 +22,51 @@ Optional properties (currently unused):
 * DMA controller
 
 Required properties:
-- compatible:  should be "renesas,shdma"
+- compatible:  should be of the form "renesas,shdma-<soc>", where <soc> should
+               be replaced with the desired SoC model, e.g.
+               "renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
 
 Example:
-       dmac: dma-mux0 {
+       dmac: dma-multiplexer@0 {
                compatible = "renesas,shdma-mux";
                #dma-cells = <1>;
-               dma-channels = <6>;
+               dma-channels = <20>;
                dma-requests = <256>;
-               reg = <0 0>;    /* Needed for AUXDATA */
-               #address-cells = <1>;
-               #size-cells = <1>;
+               #address-cells = <2>;
+               #size-cells = <2>;
                ranges;
 
-               dma0: shdma@fe008020 {
-                       compatible = "renesas,shdma";
-                       reg = <0xfe008020 0x270>,
-                               <0xfe009000 0xc>;
+               dma0: dma-controller@e6700020 {
+                       compatible = "renesas,shdma-r8a73a4";
+                       reg = <0 0xe6700020 0 0x89e0>;
                        interrupt-parent = <&gic>;
-                       interrupts = <0 34 4
-                                       0 28 4
-                                       0 29 4
-                                       0 30 4
-                                       0 31 4
-                                       0 32 4
-                                       0 33 4>;
+                       interrupts = <0 220 4
+                                       0 200 4
+                                       0 201 4
+                                       0 202 4
+                                       0 203 4
+                                       0 204 4
+                                       0 205 4
+                                       0 206 4
+                                       0 207 4
+                                       0 208 4
+                                       0 209 4
+                                       0 210 4
+                                       0 211 4
+                                       0 212 4
+                                       0 213 4
+                                       0 214 4
+                                       0 215 4
+                                       0 216 4
+                                       0 217 4
+                                       0 218 4
+                                       0 219 4>;
                        interrupt-names = "error",
                                        "ch0", "ch1", "ch2", "ch3",
-                                       "ch4", "ch5";
-               };
-
-               dma1: shdma@fe018020 {
-                       ...
-               };
-
-               dma2: shdma@fe028020 {
-                       ...
+                                       "ch4", "ch5", "ch6", "ch7",
+                                       "ch8", "ch9", "ch10", "ch11",
+                                       "ch12", "ch13", "ch14", "ch15",
+                                       "ch16", "ch17", "ch18", "ch19";
                };
        };
 
index c962138dde96fdac734b62f9b3f1cdf57bad21b1..893ee095f93c42cdf9ef326cb98228d8c063c3aa 100644 (file)
@@ -1,3 +1,5 @@
 obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o
 obj-$(CONFIG_SH_DMAE) += shdma.o
+shdma-y := shdmac.o
+shdma-objs := $(shdma-y)
 obj-$(CONFIG_SUDMAC) += sudmac.o
index c5ea256c281983a50431eee8ec13109e73e55977..d94ab592cc1bb21b92c851debe381609b599fa48 100644 (file)
@@ -171,7 +171,8 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
        return NULL;
 }
 
-static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
+static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
+                            dma_addr_t slave_addr)
 {
        struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
        const struct shdma_ops *ops = sdev->ops;
@@ -179,7 +180,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
 
        if (schan->dev->of_node) {
                match = schan->hw_req;
-               ret = ops->set_slave(schan, match, true);
+               ret = ops->set_slave(schan, match, slave_addr, true);
                if (ret < 0)
                        return ret;
 
@@ -194,7 +195,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
        if (test_and_set_bit(slave_id, shdma_slave_used))
                return -EBUSY;
 
-       ret = ops->set_slave(schan, match, false);
+       ret = ops->set_slave(schan, match, slave_addr, false);
        if (ret < 0) {
                clear_bit(slave_id, shdma_slave_used);
                return ret;
@@ -236,7 +237,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
        if (!schan->dev->of_node && match >= slave_num)
                return false;
 
-       ret = ops->set_slave(schan, match, true);
+       ret = ops->set_slave(schan, match, 0, true);
        if (ret < 0)
                return false;
 
@@ -259,7 +260,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
         */
        if (slave) {
                /* Legacy mode: .private is set in filter */
-               ret = shdma_setup_slave(schan, slave->slave_id);
+               ret = shdma_setup_slave(schan, slave->slave_id, 0);
                if (ret < 0)
                        goto esetslave;
        } else {
@@ -680,7 +681,9 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                 * channel, while using it...
                 */
                config = (struct dma_slave_config *)arg;
-               ret = shdma_setup_slave(schan, config->slave_id);
+               ret = shdma_setup_slave(schan, config->slave_id,
+                                       config->direction == DMA_DEV_TO_MEM ?
+                                       config->src_addr : config->dst_addr);
                if (ret < 0)
                        return ret;
                break;
index 11bcb05cd79c9eb6e9f6258d6d8cfcabc46bdf28..2acf7b62d6b6452302eac43e16522498c1605f5a 100644 (file)
@@ -45,9 +45,6 @@ static int shdma_of_probe(struct platform_device *pdev)
        const struct of_dev_auxdata *lookup = pdev->dev.platform_data;
        int ret;
 
-       if (!lookup)
-               return -EINVAL;
-
        ret = of_dma_controller_register(pdev->dev.of_node,
                                         shdma_of_xlate, pdev);
        if (ret < 0)
index 3d9dca177860d87ada4e56e0cc2f5007651e7df9..ff2f93b612ca186fa69ee134351b201f115bd97d 100644 (file)
@@ -31,6 +31,7 @@ struct sh_dmae_chan {
        void __iomem *base;
        char dev_id[16];                /* unique name per DMAC of channel */
        int pm_error;
+       dma_addr_t slave_addr;
 };
 
 struct sh_dmae_device {
similarity index 98%
rename from drivers/dma/sh/shdma.c
rename to drivers/dma/sh/shdmac.c
index 3b4bee933dd7aa0645f139cbd54d9ad15c971a6c..a47b70879e0579cc4d14c5f94d886f48d83be9fa 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
@@ -333,7 +335,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
        } else {
                for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
                        if (cfg->mid_rid == match) {
-                               sh_chan->shdma_chan.slave_id = cfg->slave_id;
+                               sh_chan->shdma_chan.slave_id = i;
                                return cfg;
                        }
        }
@@ -342,7 +344,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
 }
 
 static int sh_dmae_set_slave(struct shdma_chan *schan,
-                            int slave_id, bool try)
+                            int slave_id, dma_addr_t slave_addr, bool try)
 {
        struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
                                                    shdma_chan);
@@ -350,8 +352,10 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
        if (!cfg)
                return -ENXIO;
 
-       if (!try)
+       if (!try) {
                sh_chan->config = cfg;
+               sh_chan->slave_addr = slave_addr ? : cfg->addr;
+       }
 
        return 0;
 }
@@ -641,7 +645,7 @@ static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
         * This is an exclusive slave DMA operation, may only be called after a
         * successful slave configuration.
         */
-       return sh_chan->config->addr;
+       return sh_chan->slave_addr;
 }
 
 static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
@@ -663,9 +667,14 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
        .get_partial = sh_dmae_get_partial,
 };
 
+static const struct of_device_id sh_dmae_of_match[] = {
+       {}
+};
+MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
+
 static int sh_dmae_probe(struct platform_device *pdev)
 {
-       const struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
+       const struct sh_dmae_pdata *pdata;
        unsigned long irqflags = IRQF_DISABLED,
                chan_flag[SH_DMAE_MAX_CHANNELS] = {};
        int errirq, chan_irq[SH_DMAE_MAX_CHANNELS];
@@ -674,6 +683,11 @@ static int sh_dmae_probe(struct platform_device *pdev)
        struct dma_device *dma_dev;
        struct resource *chan, *dmars, *errirq_res, *chanirq_res;
 
+       if (pdev->dev.of_node)
+               pdata = of_match_device(sh_dmae_of_match, &pdev->dev)->data;
+       else
+               pdata = pdev->dev.platform_data;
+
        /* get platform data */
        if (!pdata || !pdata->channel_num)
                return -ENODEV;
@@ -902,12 +916,6 @@ static int sh_dmae_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id sh_dmae_of_match[] = {
-       { .compatible = "renesas,shdma", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
-
 static struct platform_driver sh_dmae_driver = {
        .driver         = {
                .owner  = THIS_MODULE,
index 4808b45141b4b65a1dfa933278f509ae781f11c1..4600b429603e378540e969fa745b7d1ac433d266 100644 (file)
@@ -150,7 +150,8 @@ static const struct sudmac_slave_config *sudmac_find_slave(
        return NULL;
 }
 
-static int sudmac_set_slave(struct shdma_chan *schan, int slave_id, bool try)
+static int sudmac_set_slave(struct shdma_chan *schan, int slave_id,
+                           dma_addr_t slave_addr, bool try)
 {
        struct sudmac_chan *sc = to_chan(schan);
        const struct sudmac_slave_config *cfg = sudmac_find_slave(sc, slave_id);
index 31cf89fb1d5bebb9d76c3ca7590e9adc88ae3fcc..f92c0a43c54cb9ee2465e8e4c726cc1a1e630096 100644 (file)
@@ -96,7 +96,7 @@ struct shdma_ops {
        dma_addr_t (*slave_addr)(struct shdma_chan *);
        int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
                          dma_addr_t, dma_addr_t, size_t *);
-       int (*set_slave)(struct shdma_chan *, int, bool);
+       int (*set_slave)(struct shdma_chan *, int, dma_addr_t, bool);
        void (*setup_xfer)(struct shdma_chan *, int);
        void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
        struct shdma_desc *(*embedded_desc)(void *, int);