aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2013-08-02 10:50:36 -0400
committerVinod Koul <vinod.koul@intel.com>2013-08-27 04:55:09 -0400
commit4981c4dc194efb18f0e9a02f1b43e926f2f0d2bb (patch)
tree8c8543ecbd41100bc2d16ee957537ff2e7c20592
parent2833c47e0ecc74b300716e56810143125ad7a3f1 (diff)
DMA: shdma: switch DT mode to use configuration data from a match table
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>
-rw-r--r--Documentation/devicetree/bindings/dma/shdma.txt61
-rw-r--r--drivers/dma/sh/Makefile2
-rw-r--r--drivers/dma/sh/shdma-base.c15
-rw-r--r--drivers/dma/sh/shdma-of.c3
-rw-r--r--drivers/dma/sh/shdma.h1
-rw-r--r--drivers/dma/sh/shdmac.c (renamed from drivers/dma/sh/shdma.c)30
-rw-r--r--drivers/dma/sh/sudmac.c3
-rw-r--r--include/linux/shdma-base.h2
8 files changed, 69 insertions, 48 deletions
diff --git a/Documentation/devicetree/bindings/dma/shdma.txt b/Documentation/devicetree/bindings/dma/shdma.txt
index c15994aa1939..2a3f3b8946b9 100644
--- a/Documentation/devicetree/bindings/dma/shdma.txt
+++ b/Documentation/devicetree/bindings/dma/shdma.txt
@@ -22,42 +22,51 @@ Optional properties (currently unused):
22* DMA controller 22* DMA controller
23 23
24Required properties: 24Required properties:
25- compatible: should be "renesas,shdma" 25- compatible: should be of the form "renesas,shdma-<soc>", where <soc> should
26 be replaced with the desired SoC model, e.g.
27 "renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
26 28
27Example: 29Example:
28 dmac: dma-mux0 { 30 dmac: dma-multiplexer@0 {
29 compatible = "renesas,shdma-mux"; 31 compatible = "renesas,shdma-mux";
30 #dma-cells = <1>; 32 #dma-cells = <1>;
31 dma-channels = <6>; 33 dma-channels = <20>;
32 dma-requests = <256>; 34 dma-requests = <256>;
33 reg = <0 0>; /* Needed for AUXDATA */ 35 #address-cells = <2>;
34 #address-cells = <1>; 36 #size-cells = <2>;
35 #size-cells = <1>;
36 ranges; 37 ranges;
37 38
38 dma0: shdma@fe008020 { 39 dma0: dma-controller@e6700020 {
39 compatible = "renesas,shdma"; 40 compatible = "renesas,shdma-r8a73a4";
40 reg = <0xfe008020 0x270>, 41 reg = <0 0xe6700020 0 0x89e0>;
41 <0xfe009000 0xc>;
42 interrupt-parent = <&gic>; 42 interrupt-parent = <&gic>;
43 interrupts = <0 34 4 43 interrupts = <0 220 4
44 0 28 4 44 0 200 4
45 0 29 4 45 0 201 4
46 0 30 4 46 0 202 4
47 0 31 4 47 0 203 4
48 0 32 4 48 0 204 4
49 0 33 4>; 49 0 205 4
50 0 206 4
51 0 207 4
52 0 208 4
53 0 209 4
54 0 210 4
55 0 211 4
56 0 212 4
57 0 213 4
58 0 214 4
59 0 215 4
60 0 216 4
61 0 217 4
62 0 218 4
63 0 219 4>;
50 interrupt-names = "error", 64 interrupt-names = "error",
51 "ch0", "ch1", "ch2", "ch3", 65 "ch0", "ch1", "ch2", "ch3",
52 "ch4", "ch5"; 66 "ch4", "ch5", "ch6", "ch7",
53 }; 67 "ch8", "ch9", "ch10", "ch11",
54 68 "ch12", "ch13", "ch14", "ch15",
55 dma1: shdma@fe018020 { 69 "ch16", "ch17", "ch18", "ch19";
56 ...
57 };
58
59 dma2: shdma@fe028020 {
60 ...
61 }; 70 };
62 }; 71 };
63 72
diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile
index c962138dde96..893ee095f93c 100644
--- a/drivers/dma/sh/Makefile
+++ b/drivers/dma/sh/Makefile
@@ -1,3 +1,5 @@
1obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o 1obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o
2obj-$(CONFIG_SH_DMAE) += shdma.o 2obj-$(CONFIG_SH_DMAE) += shdma.o
3shdma-y := shdmac.o
4shdma-objs := $(shdma-y)
3obj-$(CONFIG_SUDMAC) += sudmac.o 5obj-$(CONFIG_SUDMAC) += sudmac.o
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index c5ea256c2819..d94ab592cc1b 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -171,7 +171,8 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
171 return NULL; 171 return NULL;
172} 172}
173 173
174static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) 174static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
175 dma_addr_t slave_addr)
175{ 176{
176 struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); 177 struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
177 const struct shdma_ops *ops = sdev->ops; 178 const struct shdma_ops *ops = sdev->ops;
@@ -179,7 +180,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
179 180
180 if (schan->dev->of_node) { 181 if (schan->dev->of_node) {
181 match = schan->hw_req; 182 match = schan->hw_req;
182 ret = ops->set_slave(schan, match, true); 183 ret = ops->set_slave(schan, match, slave_addr, true);
183 if (ret < 0) 184 if (ret < 0)
184 return ret; 185 return ret;
185 186
@@ -194,7 +195,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
194 if (test_and_set_bit(slave_id, shdma_slave_used)) 195 if (test_and_set_bit(slave_id, shdma_slave_used))
195 return -EBUSY; 196 return -EBUSY;
196 197
197 ret = ops->set_slave(schan, match, false); 198 ret = ops->set_slave(schan, match, slave_addr, false);
198 if (ret < 0) { 199 if (ret < 0) {
199 clear_bit(slave_id, shdma_slave_used); 200 clear_bit(slave_id, shdma_slave_used);
200 return ret; 201 return ret;
@@ -236,7 +237,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
236 if (!schan->dev->of_node && match >= slave_num) 237 if (!schan->dev->of_node && match >= slave_num)
237 return false; 238 return false;
238 239
239 ret = ops->set_slave(schan, match, true); 240 ret = ops->set_slave(schan, match, 0, true);
240 if (ret < 0) 241 if (ret < 0)
241 return false; 242 return false;
242 243
@@ -259,7 +260,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
259 */ 260 */
260 if (slave) { 261 if (slave) {
261 /* Legacy mode: .private is set in filter */ 262 /* Legacy mode: .private is set in filter */
262 ret = shdma_setup_slave(schan, slave->slave_id); 263 ret = shdma_setup_slave(schan, slave->slave_id, 0);
263 if (ret < 0) 264 if (ret < 0)
264 goto esetslave; 265 goto esetslave;
265 } else { 266 } else {
@@ -680,7 +681,9 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
680 * channel, while using it... 681 * channel, while using it...
681 */ 682 */
682 config = (struct dma_slave_config *)arg; 683 config = (struct dma_slave_config *)arg;
683 ret = shdma_setup_slave(schan, config->slave_id); 684 ret = shdma_setup_slave(schan, config->slave_id,
685 config->direction == DMA_DEV_TO_MEM ?
686 config->src_addr : config->dst_addr);
684 if (ret < 0) 687 if (ret < 0)
685 return ret; 688 return ret;
686 break; 689 break;
diff --git a/drivers/dma/sh/shdma-of.c b/drivers/dma/sh/shdma-of.c
index 11bcb05cd79c..2acf7b62d6b6 100644
--- a/drivers/dma/sh/shdma-of.c
+++ b/drivers/dma/sh/shdma-of.c
@@ -45,9 +45,6 @@ static int shdma_of_probe(struct platform_device *pdev)
45 const struct of_dev_auxdata *lookup = pdev->dev.platform_data; 45 const struct of_dev_auxdata *lookup = pdev->dev.platform_data;
46 int ret; 46 int ret;
47 47
48 if (!lookup)
49 return -EINVAL;
50
51 ret = of_dma_controller_register(pdev->dev.of_node, 48 ret = of_dma_controller_register(pdev->dev.of_node,
52 shdma_of_xlate, pdev); 49 shdma_of_xlate, pdev);
53 if (ret < 0) 50 if (ret < 0)
diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
index 3d9dca177860..ff2f93b612ca 100644
--- a/drivers/dma/sh/shdma.h
+++ b/drivers/dma/sh/shdma.h
@@ -31,6 +31,7 @@ struct sh_dmae_chan {
31 void __iomem *base; 31 void __iomem *base;
32 char dev_id[16]; /* unique name per DMAC of channel */ 32 char dev_id[16]; /* unique name per DMAC of channel */
33 int pm_error; 33 int pm_error;
34 dma_addr_t slave_addr;
34}; 35};
35 36
36struct sh_dmae_device { 37struct sh_dmae_device {
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdmac.c
index 3b4bee933dd7..a47b70879e05 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdmac.c
@@ -20,6 +20,8 @@
20 20
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/of_device.h>
23#include <linux/slab.h> 25#include <linux/slab.h>
24#include <linux/interrupt.h> 26#include <linux/interrupt.h>
25#include <linux/dmaengine.h> 27#include <linux/dmaengine.h>
@@ -333,7 +335,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
333 } else { 335 } else {
334 for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) 336 for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
335 if (cfg->mid_rid == match) { 337 if (cfg->mid_rid == match) {
336 sh_chan->shdma_chan.slave_id = cfg->slave_id; 338 sh_chan->shdma_chan.slave_id = i;
337 return cfg; 339 return cfg;
338 } 340 }
339 } 341 }
@@ -342,7 +344,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
342} 344}
343 345
344static int sh_dmae_set_slave(struct shdma_chan *schan, 346static int sh_dmae_set_slave(struct shdma_chan *schan,
345 int slave_id, bool try) 347 int slave_id, dma_addr_t slave_addr, bool try)
346{ 348{
347 struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, 349 struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
348 shdma_chan); 350 shdma_chan);
@@ -350,8 +352,10 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
350 if (!cfg) 352 if (!cfg)
351 return -ENXIO; 353 return -ENXIO;
352 354
353 if (!try) 355 if (!try) {
354 sh_chan->config = cfg; 356 sh_chan->config = cfg;
357 sh_chan->slave_addr = slave_addr ? : cfg->addr;
358 }
355 359
356 return 0; 360 return 0;
357} 361}
@@ -641,7 +645,7 @@ static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
641 * This is an exclusive slave DMA operation, may only be called after a 645 * This is an exclusive slave DMA operation, may only be called after a
642 * successful slave configuration. 646 * successful slave configuration.
643 */ 647 */
644 return sh_chan->config->addr; 648 return sh_chan->slave_addr;
645} 649}
646 650
647static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i) 651static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
@@ -663,9 +667,14 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
663 .get_partial = sh_dmae_get_partial, 667 .get_partial = sh_dmae_get_partial,
664}; 668};
665 669
670static const struct of_device_id sh_dmae_of_match[] = {
671 {}
672};
673MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
674
666static int sh_dmae_probe(struct platform_device *pdev) 675static int sh_dmae_probe(struct platform_device *pdev)
667{ 676{
668 const struct sh_dmae_pdata *pdata = pdev->dev.platform_data; 677 const struct sh_dmae_pdata *pdata;
669 unsigned long irqflags = IRQF_DISABLED, 678 unsigned long irqflags = IRQF_DISABLED,
670 chan_flag[SH_DMAE_MAX_CHANNELS] = {}; 679 chan_flag[SH_DMAE_MAX_CHANNELS] = {};
671 int errirq, chan_irq[SH_DMAE_MAX_CHANNELS]; 680 int errirq, chan_irq[SH_DMAE_MAX_CHANNELS];
@@ -674,6 +683,11 @@ static int sh_dmae_probe(struct platform_device *pdev)
674 struct dma_device *dma_dev; 683 struct dma_device *dma_dev;
675 struct resource *chan, *dmars, *errirq_res, *chanirq_res; 684 struct resource *chan, *dmars, *errirq_res, *chanirq_res;
676 685
686 if (pdev->dev.of_node)
687 pdata = of_match_device(sh_dmae_of_match, &pdev->dev)->data;
688 else
689 pdata = pdev->dev.platform_data;
690
677 /* get platform data */ 691 /* get platform data */
678 if (!pdata || !pdata->channel_num) 692 if (!pdata || !pdata->channel_num)
679 return -ENODEV; 693 return -ENODEV;
@@ -902,12 +916,6 @@ static int sh_dmae_remove(struct platform_device *pdev)
902 return 0; 916 return 0;
903} 917}
904 918
905static const struct of_device_id sh_dmae_of_match[] = {
906 { .compatible = "renesas,shdma", },
907 { }
908};
909MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
910
911static struct platform_driver sh_dmae_driver = { 919static struct platform_driver sh_dmae_driver = {
912 .driver = { 920 .driver = {
913 .owner = THIS_MODULE, 921 .owner = THIS_MODULE,
diff --git a/drivers/dma/sh/sudmac.c b/drivers/dma/sh/sudmac.c
index 4808b45141b4..4600b429603e 100644
--- a/drivers/dma/sh/sudmac.c
+++ b/drivers/dma/sh/sudmac.c
@@ -150,7 +150,8 @@ static const struct sudmac_slave_config *sudmac_find_slave(
150 return NULL; 150 return NULL;
151} 151}
152 152
153static int sudmac_set_slave(struct shdma_chan *schan, int slave_id, bool try) 153static int sudmac_set_slave(struct shdma_chan *schan, int slave_id,
154 dma_addr_t slave_addr, bool try)
154{ 155{
155 struct sudmac_chan *sc = to_chan(schan); 156 struct sudmac_chan *sc = to_chan(schan);
156 const struct sudmac_slave_config *cfg = sudmac_find_slave(sc, slave_id); 157 const struct sudmac_slave_config *cfg = sudmac_find_slave(sc, slave_id);
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index 31cf89fb1d5b..f92c0a43c54c 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -96,7 +96,7 @@ struct shdma_ops {
96 dma_addr_t (*slave_addr)(struct shdma_chan *); 96 dma_addr_t (*slave_addr)(struct shdma_chan *);
97 int (*desc_setup)(struct shdma_chan *, struct shdma_desc *, 97 int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
98 dma_addr_t, dma_addr_t, size_t *); 98 dma_addr_t, dma_addr_t, size_t *);
99 int (*set_slave)(struct shdma_chan *, int, bool); 99 int (*set_slave)(struct shdma_chan *, int, dma_addr_t, bool);
100 void (*setup_xfer)(struct shdma_chan *, int); 100 void (*setup_xfer)(struct shdma_chan *, int);
101 void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); 101 void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
102 struct shdma_desc *(*embedded_desc)(void *, int); 102 struct shdma_desc *(*embedded_desc)(void *, int);