aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-01-28 11:24:37 -0500
committerArnd Bergmann <arnd@arndb.de>2013-03-12 12:56:09 -0400
commit787b0c1f8e1975157fe73104e67cac18f955281b (patch)
tree4668c8a2a16baec67e71844840b85bea03cb5566
parentdc715452e9145156840b09df765ea2ede4851eda (diff)
serial: pl011: use generic DMA slave configuration if possible
With the new OF DMA binding, it is possible to completely avoid the need for platform_data for configuring a DMA channel. In cases where the platform has already been converted, calling dma_request_slave_channel should get all the necessary information from the device tree. This also adds a binding document specific to the pl011 controller, and extends the generic primecell binding to mention "dmas" and other common properties. Like the patch that converts the dw_dma controller, this is completely untested and is looking for someone to try it out. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Viresh Kumar <viresh.kumar@linaro.org> Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-arm-kernel@lists.infradead.org
-rw-r--r--Documentation/devicetree/bindings/arm/primecell.txt19
-rw-r--r--Documentation/devicetree/bindings/serial/pl011.txt17
-rw-r--r--drivers/tty/serial/amba-pl011.c62
3 files changed, 72 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
index 64fc82bc8928..0df6acacfaea 100644
--- a/Documentation/devicetree/bindings/arm/primecell.txt
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -16,14 +16,31 @@ Optional properties:
16- clocks : From common clock binding. First clock is phandle to clock for apb 16- clocks : From common clock binding. First clock is phandle to clock for apb
17 pclk. Additional clocks are optional and specific to those peripherals. 17 pclk. Additional clocks are optional and specific to those peripherals.
18- clock-names : From common clock binding. Shall be "apb_pclk" for first clock. 18- clock-names : From common clock binding. Shall be "apb_pclk" for first clock.
19- dmas : From common DMA binding. If present, refers to one or more dma channels.
20- dma-names : From common DMA binding, needs to match the 'dmas' property.
21 Devices with exactly one receive and transmit channel shall name
22 these "rx" and "tx", respectively.
23- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
24- pinctrl-names : Names corresponding to the numbered pinctrl states
25- interrupts : one or more interrupt specifiers
26- interrupt-names : names corresponding to the interrupts properties
19 27
20Example: 28Example:
21 29
22serial@fff36000 { 30serial@fff36000 {
23 compatible = "arm,pl011", "arm,primecell"; 31 compatible = "arm,pl011", "arm,primecell";
24 arm,primecell-periphid = <0x00341011>; 32 arm,primecell-periphid = <0x00341011>;
33
25 clocks = <&pclk>; 34 clocks = <&pclk>;
26 clock-names = "apb_pclk"; 35 clock-names = "apb_pclk";
27 36
37 dmas = <&dma-controller 4>, <&dma-controller 5>;
38 dma-names = "rx", "tx";
39
40 pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
41 pinctrl-1 = <&uart0_sleep_mode>;
42 pinctrl-names = "default","sleep";
43
44 interrupts = <0 11 0x4>;
28}; 45};
29 46
diff --git a/Documentation/devicetree/bindings/serial/pl011.txt b/Documentation/devicetree/bindings/serial/pl011.txt
new file mode 100644
index 000000000000..5d2e840ae65c
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/pl011.txt
@@ -0,0 +1,17 @@
1* ARM AMBA Primecell PL011 serial UART
2
3Required properties:
4- compatible: must be "arm,primecell", "arm,pl011"
5- reg: exactly one register range with length 0x1000
6- interrupts: exactly one interrupt specifier
7
8Optional properties:
9- pinctrl: When present, must have one state named "sleep"
10 and one state named "default"
11- clocks: When present, must refer to exactly one clock named
12 "apb_pclk"
13- dmas: When present, may have one or two dma channels.
14 The first one must be named "rx", the second one
15 must be named "tx".
16
17See also bindings/arm/primecell.txt
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 3ea5408fcbeb..c25b00ef9dbb 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -245,7 +245,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
245 } 245 }
246} 246}
247 247
248static void pl011_dma_probe_initcall(struct uart_amba_port *uap) 248static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
249{ 249{
250 /* DMA is the sole user of the platform data right now */ 250 /* DMA is the sole user of the platform data right now */
251 struct amba_pl011_data *plat = uap->port.dev->platform_data; 251 struct amba_pl011_data *plat = uap->port.dev->platform_data;
@@ -259,20 +259,25 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
259 struct dma_chan *chan; 259 struct dma_chan *chan;
260 dma_cap_mask_t mask; 260 dma_cap_mask_t mask;
261 261
262 /* We need platform data */ 262 chan = dma_request_slave_channel(dev, "tx");
263 if (!plat || !plat->dma_filter) {
264 dev_info(uap->port.dev, "no DMA platform data\n");
265 return;
266 }
267 263
268 /* Try to acquire a generic DMA engine slave TX channel */
269 dma_cap_zero(mask);
270 dma_cap_set(DMA_SLAVE, mask);
271
272 chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
273 if (!chan) { 264 if (!chan) {
274 dev_err(uap->port.dev, "no TX DMA channel!\n"); 265 /* We need platform data */
275 return; 266 if (!plat || !plat->dma_filter) {
267 dev_info(uap->port.dev, "no DMA platform data\n");
268 return;
269 }
270
271 /* Try to acquire a generic DMA engine slave TX channel */
272 dma_cap_zero(mask);
273 dma_cap_set(DMA_SLAVE, mask);
274
275 chan = dma_request_channel(mask, plat->dma_filter,
276 plat->dma_tx_param);
277 if (!chan) {
278 dev_err(uap->port.dev, "no TX DMA channel!\n");
279 return;
280 }
276 } 281 }
277 282
278 dmaengine_slave_config(chan, &tx_conf); 283 dmaengine_slave_config(chan, &tx_conf);
@@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
282 dma_chan_name(uap->dmatx.chan)); 287 dma_chan_name(uap->dmatx.chan));
283 288
284 /* Optionally make use of an RX channel as well */ 289 /* Optionally make use of an RX channel as well */
285 if (plat->dma_rx_param) { 290 chan = dma_request_slave_channel(dev, "rx");
291
292 if (!chan && plat->dma_rx_param) {
293 chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
294
295 if (!chan) {
296 dev_err(uap->port.dev, "no RX DMA channel!\n");
297 return;
298 }
299 }
300
301 if (chan) {
286 struct dma_slave_config rx_conf = { 302 struct dma_slave_config rx_conf = {
287 .src_addr = uap->port.mapbase + UART01x_DR, 303 .src_addr = uap->port.mapbase + UART01x_DR,
288 .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, 304 .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
291 .device_fc = false, 307 .device_fc = false,
292 }; 308 };
293 309
294 chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
295 if (!chan) {
296 dev_err(uap->port.dev, "no RX DMA channel!\n");
297 return;
298 }
299
300 dmaengine_slave_config(chan, &rx_conf); 310 dmaengine_slave_config(chan, &rx_conf);
301 uap->dmarx.chan = chan; 311 uap->dmarx.chan = chan;
302 312
@@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
315struct dma_uap { 325struct dma_uap {
316 struct list_head node; 326 struct list_head node;
317 struct uart_amba_port *uap; 327 struct uart_amba_port *uap;
328 struct device *dev;
318}; 329};
319 330
320static LIST_HEAD(pl011_dma_uarts); 331static LIST_HEAD(pl011_dma_uarts);
@@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void)
325 336
326 list_for_each_safe(node, tmp, &pl011_dma_uarts) { 337 list_for_each_safe(node, tmp, &pl011_dma_uarts) {
327 struct dma_uap *dmau = list_entry(node, struct dma_uap, node); 338 struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
328 pl011_dma_probe_initcall(dmau->uap); 339 pl011_dma_probe_initcall(dmau->dev, dmau->uap);
329 list_del(node); 340 list_del(node);
330 kfree(dmau); 341 kfree(dmau);
331 } 342 }
@@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void)
334 345
335device_initcall(pl011_dma_initcall); 346device_initcall(pl011_dma_initcall);
336 347
337static void pl011_dma_probe(struct uart_amba_port *uap) 348static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
338{ 349{
339 struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL); 350 struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
340 if (dmau) { 351 if (dmau) {
341 dmau->uap = uap; 352 dmau->uap = uap;
353 dmau->dev = dev;
342 list_add_tail(&dmau->node, &pl011_dma_uarts); 354 list_add_tail(&dmau->node, &pl011_dma_uarts);
343 } 355 }
344} 356}
345#else 357#else
346static void pl011_dma_probe(struct uart_amba_port *uap) 358static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
347{ 359{
348 pl011_dma_probe_initcall(uap); 360 pl011_dma_probe_initcall(dev, uap);
349} 361}
350#endif 362#endif
351 363
@@ -2020,7 +2032,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
2020 uap->port.ops = &amba_pl011_pops; 2032 uap->port.ops = &amba_pl011_pops;
2021 uap->port.flags = UPF_BOOT_AUTOCONF; 2033 uap->port.flags = UPF_BOOT_AUTOCONF;
2022 uap->port.line = i; 2034 uap->port.line = i;
2023 pl011_dma_probe(uap); 2035 pl011_dma_probe(&dev->dev, uap);
2024 2036
2025 /* Ensure interrupts from this UART are masked and cleared */ 2037 /* Ensure interrupts from this UART are masked and cleared */
2026 writew(0, uap->port.membase + UART011_IMSC); 2038 writew(0, uap->port.membase + UART011_IMSC);