aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-08-12 04:37:16 -0400
committerMark Brown <broonie@linaro.org>2013-08-14 14:54:23 -0400
commita6e56c28a178cef5f93d1e11698a23a5482175d9 (patch)
tree89c6fd87f13ac178257e314320103e7c5f31b38c
parent970d8a7152aa884b9bab6a8db1ff148ee22df899 (diff)
ARM: pxa: ssp: add DT bindings
This patch contains an ugly hack for looking up the the DMA request number. The problem here is that the implementation as it stands will allocate the DMA channel from the user of the ssp port, and hence we cannot allocate a real channel here. Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt65
-rw-r--r--arch/arm/plat-pxa/ssp.c90
2 files changed, 134 insertions, 21 deletions
diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
new file mode 100644
index 000000000000..669b8140dd79
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
@@ -0,0 +1,65 @@
1Device tree bindings for Marvell PXA SSP ports
2
3Required properties:
4
5 - compatible: Must be one of
6 mrvl,pxa25x-ssp
7 mvrl,pxa25x-nssp
8 mrvl,pxa27x-ssp
9 mrvl,pxa3xx-ssp
10 mvrl,pxa168-ssp
11 mrvl,pxa910-ssp
12 mrvl,ce4100-ssp
13 mrvl,lpss-ssp
14
15 - reg: The memory base
16 - dmas: Two dma phandles, one for rx, one for tx
17 - dma-names: Must be "rx", "tx"
18
19
20Example for PXA3xx:
21
22 ssp0: ssp@41000000 {
23 compatible = "mrvl,pxa3xx-ssp";
24 reg = <0x41000000 0x40>;
25 ssp-id = <1>;
26 interrupts = <24>;
27 clock-names = "pxa27x-ssp.0";
28 dmas = <&dma 13
29 &dma 14>;
30 dma-names = "rx", "tx";
31 };
32
33 ssp1: ssp@41700000 {
34 compatible = "mrvl,pxa3xx-ssp";
35 reg = <0x41700000 0x40>;
36 ssp-id = <2>;
37 interrupts = <16>;
38 clock-names = "pxa27x-ssp.1";
39 dmas = <&dma 15
40 &dma 16>;
41 dma-names = "rx", "tx";
42 };
43
44 ssp2: ssp@41900000 {
45 compatibl3 = "mrvl,pxa3xx-ssp";
46 reg = <0x41900000 0x40>;
47 ssp-id = <3>;
48 interrupts = <0>;
49 clock-names = "pxa27x-ssp.2";
50 dmas = <&dma 66
51 &dma 67>;
52 dma-names = "rx", "tx";
53 };
54
55 ssp3: ssp@41a00000 {
56 compatible = "mrvl,pxa3xx-ssp";
57 reg = <0x41a00000 0x40>;
58 ssp-id = <4>;
59 interrupts = <13>;
60 clock-names = "pxa27x-ssp.3";
61 dmas = <&dma 2
62 &dma 3>;
63 dma-names = "rx", "tx";
64 };
65
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 65ba28a0e3c6..c3afcec7094c 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -30,6 +30,8 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/spi/pxa2xx_spi.h> 31#include <linux/spi/pxa2xx_spi.h>
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/of.h>
34#include <linux/of_device.h>
33 35
34#include <asm/irq.h> 36#include <asm/irq.h>
35#include <mach/hardware.h> 37#include <mach/hardware.h>
@@ -72,9 +74,23 @@ void pxa_ssp_free(struct ssp_device *ssp)
72} 74}
73EXPORT_SYMBOL(pxa_ssp_free); 75EXPORT_SYMBOL(pxa_ssp_free);
74 76
77#ifdef CONFIG_OF
78static const struct of_device_id pxa_ssp_of_ids[] = {
79 { .compatible = "mrvl,pxa25x-ssp", .data = (void *) PXA25x_SSP },
80 { .compatible = "mvrl,pxa25x-nssp", .data = (void *) PXA25x_NSSP },
81 { .compatible = "mrvl,pxa27x-ssp", .data = (void *) PXA27x_SSP },
82 { .compatible = "mrvl,pxa3xx-ssp", .data = (void *) PXA3xx_SSP },
83 { .compatible = "mvrl,pxa168-ssp", .data = (void *) PXA168_SSP },
84 { .compatible = "mrvl,pxa910-ssp", .data = (void *) PXA910_SSP },
85 { .compatible = "mrvl,ce4100-ssp", .data = (void *) CE4100_SSP },
86 { .compatible = "mrvl,lpss-ssp", .data = (void *) LPSS_SSP },
87 { },
88};
89MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
90#endif
91
75static int pxa_ssp_probe(struct platform_device *pdev) 92static int pxa_ssp_probe(struct platform_device *pdev)
76{ 93{
77 const struct platform_device_id *id = platform_get_device_id(pdev);
78 struct resource *res; 94 struct resource *res;
79 struct ssp_device *ssp; 95 struct ssp_device *ssp;
80 struct device *dev = &pdev->dev; 96 struct device *dev = &pdev->dev;
@@ -92,21 +108,42 @@ static int pxa_ssp_probe(struct platform_device *pdev)
92 goto err_free; 108 goto err_free;
93 } 109 }
94 110
95 res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 111 if (dev->of_node) {
96 if (res == NULL) { 112 struct of_phandle_args dma_spec;
97 dev_err(dev, "no SSP RX DRCMR defined\n"); 113 struct device_node *np = dev->of_node;
98 ret = -ENODEV; 114
99 goto err_free_clk; 115 /*
100 } 116 * FIXME: we should allocate the DMA channel from this
101 ssp->drcmr_rx = res->start; 117 * context and pass the channel down to the ssp users.
118 * For now, we lookup the rx and tx indices manually
119 */
120
121 /* rx */
122 of_parse_phandle_with_args(np, "dmas", "#dma-cells",
123 0, &dma_spec);
124 ssp->drcmr_rx = dma_spec.args[0];
125 of_node_put(dma_spec.np);
126
127 /* tx */
128 of_parse_phandle_with_args(np, "dmas", "#dma-cells",
129 1, &dma_spec);
130 ssp->drcmr_tx = dma_spec.args[0];
131 of_node_put(dma_spec.np);
132 } else {
133 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
134 if (res == NULL) {
135 dev_err(dev, "no SSP RX DRCMR defined\n");
136 return -ENODEV;
137 }
138 ssp->drcmr_rx = res->start;
102 139
103 res = platform_get_resource(pdev, IORESOURCE_DMA, 1); 140 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
104 if (res == NULL) { 141 if (res == NULL) {
105 dev_err(dev, "no SSP TX DRCMR defined\n"); 142 dev_err(dev, "no SSP TX DRCMR defined\n");
106 ret = -ENODEV; 143 return -ENODEV;
107 goto err_free_clk; 144 }
145 ssp->drcmr_tx = res->start;
108 } 146 }
109 ssp->drcmr_tx = res->start;
110 147
111 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 148 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
112 if (res == NULL) { 149 if (res == NULL) {
@@ -139,12 +176,22 @@ static int pxa_ssp_probe(struct platform_device *pdev)
139 goto err_free_io; 176 goto err_free_io;
140 } 177 }
141 178
142 /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id 179 if (dev->of_node) {
143 * starts from 0, do a translation here 180 const struct of_device_id *id =
144 */ 181 of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
145 ssp->port_id = pdev->id + 1; 182 ssp->type = (int) id->data;
183 } else {
184 const struct platform_device_id *id =
185 platform_get_device_id(pdev);
186 ssp->type = (int) id->driver_data;
187
188 /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
189 * starts from 0, do a translation here
190 */
191 ssp->port_id = pdev->id + 1;
192 }
193
146 ssp->use_count = 0; 194 ssp->use_count = 0;
147 ssp->type = (int)id->driver_data;
148 195
149 mutex_lock(&ssp_lock); 196 mutex_lock(&ssp_lock);
150 list_add(&ssp->node, &ssp_list); 197 list_add(&ssp->node, &ssp_list);
@@ -201,8 +248,9 @@ static struct platform_driver pxa_ssp_driver = {
201 .probe = pxa_ssp_probe, 248 .probe = pxa_ssp_probe,
202 .remove = pxa_ssp_remove, 249 .remove = pxa_ssp_remove,
203 .driver = { 250 .driver = {
204 .owner = THIS_MODULE, 251 .owner = THIS_MODULE,
205 .name = "pxa2xx-ssp", 252 .name = "pxa2xx-ssp",
253 .of_match_table = of_match_ptr(pxa_ssp_of_ids),
206 }, 254 },
207 .id_table = ssp_id_table, 255 .id_table = ssp_id_table,
208}; 256};