aboutsummaryrefslogtreecommitdiffstats
path: root/patches.at91/0182-i2c-at91-add-dt-property-for-DMA-configuration.patch
blob: 2b891ad64a4403df19c1bc602d434e483ca6ea5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
From 2fcde4a50eec3c26971c7c2095f56b6d9f21b1c7 Mon Sep 17 00:00:00 2001
From: Nicolas Ferre <nicolas.ferre@atmel.com>
Date: Mon, 22 Oct 2012 16:00:47 +0200
Subject: i2c: at91: add dt property for DMA configuration

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>

Conflicts:
	arch/arm/boot/dts/at91sam9x5.dtsi
---
 arch/arm/boot/dts/at91sam9x5.dtsi |  5 ++++
 drivers/i2c/busses/i2c-at91.c     | 56 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index fec3316..79718e7 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -103,12 +103,14 @@
 				compatible = "atmel,at91sam9g45-dma";
 				reg = <0xffffec00 0x200>;
 				interrupts = <20 4 0>;
+				#dma-cells = <1>;
 			};
 
 			dma1: dma-controller@ffffee00 {
 				compatible = "atmel,at91sam9g45-dma";
 				reg = <0xffffee00 0x200>;
 				interrupts = <21 4 0>;
+				#dma-cells = <1>;
 			};
 
 			pioA: gpio@fffff400 {
@@ -221,6 +223,7 @@
 				compatible = "atmel,at91sam9x5-i2c";
 				reg = <0xf8010000 0x100>;
 				interrupts = <9 4 6>;
+				dma = <&dma0 0x10002278>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				status = "disabled";
@@ -230,6 +233,7 @@
 				compatible = "atmel,at91sam9x5-i2c";
 				reg = <0xf8014000 0x100>;
 				interrupts = <10 4 6>;
+				dma = <&dma1 0x10002256>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				status = "disabled";
@@ -239,6 +243,7 @@
 				compatible = "atmel,at91sam9x5-i2c";
 				reg = <0xf8018000 0x100>;
 				interrupts = <11 4 6>;
+				dma = <&dma0 0x1000229A>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				status = "disabled";
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 296c430..c004b34 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -589,6 +589,55 @@ static const struct platform_device_id at91_twi_devtypes[] = {
 };
 
 #if defined(CONFIG_OF)
+static int at91_twi_of_init(struct device_node *np, struct at_dma_slave *atslave)
+{
+	struct of_phandle_args  dma_spec;
+	struct device_node      *dmac_np;
+	struct platform_device  *dmac_pdev;
+	const __be32            *nbcells;
+	int                     ret;
+
+	ret = of_parse_phandle_with_args(np, "dma", "#dma-cells", 0, &dma_spec);
+	if (ret || !dma_spec.np) {
+		pr_err("%s: can't parse dma property (%d)\n", np->full_name, ret);
+		goto err0;
+	}
+	dmac_np = dma_spec.np;
+
+	/* check property format */
+	nbcells = of_get_property(dmac_np, "#dma-cells", NULL);
+	if (!nbcells) {
+		pr_err("%s: #dma-cells property is required\n", np->full_name);
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	if (dma_spec.args_count != be32_to_cpup(nbcells)
+			|| dma_spec.args_count != 1) {
+		pr_err("%s: wrong #dma-cells for %s\n",
+				np->full_name, dmac_np->full_name);
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	dmac_pdev = of_find_device_by_node(dmac_np);
+	if (!dmac_pdev) {
+		pr_err("%s: unable to find pdev from DMA controller\n",
+				dmac_np->full_name);
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	atslave->dma_dev = &dmac_pdev->dev;
+	atslave->cfg = dma_spec.args[0];
+
+err1:
+	of_node_put(dma_spec.np);
+err0:
+	pr_debug("%s exited with status %d\n", __func__, ret);
+	return ret;
+}
+
 static const struct of_device_id atmel_twi_dt_ids[] = {
 	{
 		.compatible = "atmel,at91sam9260-i2c",
@@ -608,6 +657,10 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
 #else
+static int at91_twi_of_init(struct device_node *np, struct at_dma_slave *atslave)
+{
+	return -ENODEV;
+}
 #define atmel_twi_dt_ids NULL
 #endif
 
@@ -755,7 +808,8 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	clk_prepare_enable(dev->clk);
 
 	if (dev->pdata->has_dma_support) {
-		if (at91_twi_configure_dma(dev, phy_addr) == 0)
+		if ( at91_twi_of_init(pdev->dev.of_node, &dev->pdata->dma_slave) == 0
+		     && at91_twi_configure_dma(dev, phy_addr) == 0)
 			dev->use_dma = true;
 	}
 
-- 
1.8.0.197.g5a90748