diff options
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
| -rw-r--r-- | drivers/tty/serial/amba-pl011.c | 64 | 
1 files changed, 38 insertions, 26 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index b2e9e177a35..8ab70a62091 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -267,7 +267,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; @@ -281,20 +281,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); @@ -304,7 +309,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, @@ -313,12 +329,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; @@ -360,6 +370,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); @@ -370,7 +381,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);  	} @@ -379,18 +390,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 @@ -1096,7 +1108,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)  #else  /* Blank functions if the DMA engine is not available */ -static inline void pl011_dma_probe(struct uart_amba_port *uap) +static inline void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)  {  } @@ -2155,7 +2167,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);  |