Commit 787b0c1f authored by Arnd Bergmann's avatar Arnd Bergmann

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: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Acked-by: default avatarGreg 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
parent dc715452
...@@ -16,14 +16,31 @@ Optional properties: ...@@ -16,14 +16,31 @@ Optional properties:
- clocks : From common clock binding. First clock is phandle to clock for apb - clocks : From common clock binding. First clock is phandle to clock for apb
pclk. Additional clocks are optional and specific to those peripherals. pclk. Additional clocks are optional and specific to those peripherals.
- clock-names : From common clock binding. Shall be "apb_pclk" for first clock. - clock-names : From common clock binding. Shall be "apb_pclk" for first clock.
- dmas : From common DMA binding. If present, refers to one or more dma channels.
- dma-names : From common DMA binding, needs to match the 'dmas' property.
Devices with exactly one receive and transmit channel shall name
these "rx" and "tx", respectively.
- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
- pinctrl-names : Names corresponding to the numbered pinctrl states
- interrupts : one or more interrupt specifiers
- interrupt-names : names corresponding to the interrupts properties
Example: Example:
serial@fff36000 { serial@fff36000 {
compatible = "arm,pl011", "arm,primecell"; compatible = "arm,pl011", "arm,primecell";
arm,primecell-periphid = <0x00341011>; arm,primecell-periphid = <0x00341011>;
clocks = <&pclk>; clocks = <&pclk>;
clock-names = "apb_pclk"; clock-names = "apb_pclk";
dmas = <&dma-controller 4>, <&dma-controller 5>;
dma-names = "rx", "tx";
pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
pinctrl-1 = <&uart0_sleep_mode>;
pinctrl-names = "default","sleep";
interrupts = <0 11 0x4>;
}; };
* ARM AMBA Primecell PL011 serial UART
Required properties:
- compatible: must be "arm,primecell", "arm,pl011"
- reg: exactly one register range with length 0x1000
- interrupts: exactly one interrupt specifier
Optional properties:
- pinctrl: When present, must have one state named "sleep"
and one state named "default"
- clocks: When present, must refer to exactly one clock named
"apb_pclk"
- dmas: When present, may have one or two dma channels.
The first one must be named "rx", the second one
must be named "tx".
See also bindings/arm/primecell.txt
...@@ -245,7 +245,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg, ...@@ -245,7 +245,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
} }
} }
static void pl011_dma_probe_initcall(struct uart_amba_port *uap) static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
{ {
/* DMA is the sole user of the platform data right now */ /* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = uap->port.dev->platform_data; 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,20 +259,25 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_chan *chan; struct dma_chan *chan;
dma_cap_mask_t mask; dma_cap_mask_t mask;
/* We need platform data */ chan = dma_request_slave_channel(dev, "tx");
if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
return;
}
/* Try to acquire a generic DMA engine slave TX channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
if (!chan) { if (!chan) {
dev_err(uap->port.dev, "no TX DMA channel!\n"); /* We need platform data */
return; if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
return;
}
/* Try to acquire a generic DMA engine slave TX channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, plat->dma_filter,
plat->dma_tx_param);
if (!chan) {
dev_err(uap->port.dev, "no TX DMA channel!\n");
return;
}
} }
dmaengine_slave_config(chan, &tx_conf); dmaengine_slave_config(chan, &tx_conf);
...@@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) ...@@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
dma_chan_name(uap->dmatx.chan)); dma_chan_name(uap->dmatx.chan));
/* Optionally make use of an RX channel as well */ /* Optionally make use of an RX channel as well */
if (plat->dma_rx_param) { chan = dma_request_slave_channel(dev, "rx");
if (!chan && plat->dma_rx_param) {
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
if (!chan) {
dev_err(uap->port.dev, "no RX DMA channel!\n");
return;
}
}
if (chan) {
struct dma_slave_config rx_conf = { struct dma_slave_config rx_conf = {
.src_addr = uap->port.mapbase + UART01x_DR, .src_addr = uap->port.mapbase + UART01x_DR,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
...@@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) ...@@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
.device_fc = false, .device_fc = false,
}; };
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
if (!chan) {
dev_err(uap->port.dev, "no RX DMA channel!\n");
return;
}
dmaengine_slave_config(chan, &rx_conf); dmaengine_slave_config(chan, &rx_conf);
uap->dmarx.chan = chan; uap->dmarx.chan = chan;
...@@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) ...@@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_uap { struct dma_uap {
struct list_head node; struct list_head node;
struct uart_amba_port *uap; struct uart_amba_port *uap;
struct device *dev;
}; };
static LIST_HEAD(pl011_dma_uarts); static LIST_HEAD(pl011_dma_uarts);
...@@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void) ...@@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void)
list_for_each_safe(node, tmp, &pl011_dma_uarts) { list_for_each_safe(node, tmp, &pl011_dma_uarts) {
struct dma_uap *dmau = list_entry(node, struct dma_uap, node); struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
pl011_dma_probe_initcall(dmau->uap); pl011_dma_probe_initcall(dmau->dev, dmau->uap);
list_del(node); list_del(node);
kfree(dmau); kfree(dmau);
} }
...@@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void) ...@@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void)
device_initcall(pl011_dma_initcall); device_initcall(pl011_dma_initcall);
static void pl011_dma_probe(struct uart_amba_port *uap) static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{ {
struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL); struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
if (dmau) { if (dmau) {
dmau->uap = uap; dmau->uap = uap;
dmau->dev = dev;
list_add_tail(&dmau->node, &pl011_dma_uarts); list_add_tail(&dmau->node, &pl011_dma_uarts);
} }
} }
#else #else
static void pl011_dma_probe(struct uart_amba_port *uap) static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{ {
pl011_dma_probe_initcall(uap); pl011_dma_probe_initcall(dev, uap);
} }
#endif #endif
...@@ -2020,7 +2032,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -2020,7 +2032,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.ops = &amba_pl011_pops; uap->port.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i; uap->port.line = i;
pl011_dma_probe(uap); pl011_dma_probe(&dev->dev, uap);
/* Ensure interrupts from this UART are masked and cleared */ /* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC); writew(0, uap->port.membase + UART011_IMSC);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment