|
@@ -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 */
|
|
|
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)
|
|
|
struct dma_chan *chan;
|
|
|
dma_cap_mask_t mask;
|
|
|
|
|
|
- /* We need platform data */
|
|
|
- if (!plat || !plat->dma_filter) {
|
|
|
- dev_info(uap->port.dev, "no DMA platform data\n");
|
|
|
- return;
|
|
|
- }
|
|
|
+ chan = dma_request_slave_channel(dev, "tx");
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* We need platform data */
|
|
|
+ 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);
|
|
@@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
|
|
|
dma_chan_name(uap->dmatx.chan));
|
|
|
|
|
|
/* 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 = {
|
|
|
.src_addr = uap->port.mapbase + UART01x_DR,
|
|
|
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
|
|
@@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
|
|
|
.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);
|
|
|
uap->dmarx.chan = chan;
|
|
|
|
|
@@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
|
|
|
struct dma_uap {
|
|
|
struct list_head node;
|
|
|
struct uart_amba_port *uap;
|
|
|
+ struct device *dev;
|
|
|
};
|
|
|
|
|
|
static LIST_HEAD(pl011_dma_uarts);
|
|
@@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void)
|
|
|
|
|
|
list_for_each_safe(node, tmp, &pl011_dma_uarts) {
|
|
|
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);
|
|
|
kfree(dmau);
|
|
|
}
|
|
@@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void)
|
|
|
|
|
|
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);
|
|
|
if (dmau) {
|
|
|
dmau->uap = uap;
|
|
|
+ dmau->dev = dev;
|
|
|
list_add_tail(&dmau->node, &pl011_dma_uarts);
|
|
|
}
|
|
|
}
|
|
|
#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
|
|
|
|
|
@@ -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.flags = UPF_BOOT_AUTOCONF;
|
|
|
uap->port.line = i;
|
|
|
- pl011_dma_probe(uap);
|
|
|
+ pl011_dma_probe(&dev->dev, uap);
|
|
|
|
|
|
/* Ensure interrupts from this UART are masked and cleared */
|
|
|
writew(0, uap->port.membase + UART011_IMSC);
|