aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
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 /drivers/tty
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
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/amba-pl011.c62
1 files changed, 37 insertions, 25 deletions
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);