diff options
| -rw-r--r-- | Documentation/devicetree/bindings/tty/serial/efm32-uart.txt | 6 | ||||
| -rw-r--r-- | drivers/tty/serial/efm32-uart.c | 31 | 
2 files changed, 30 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/tty/serial/efm32-uart.txt b/Documentation/devicetree/bindings/tty/serial/efm32-uart.txt index 6588b6950a7..8e080b893b4 100644 --- a/Documentation/devicetree/bindings/tty/serial/efm32-uart.txt +++ b/Documentation/devicetree/bindings/tty/serial/efm32-uart.txt @@ -5,10 +5,16 @@ Required properties:  - reg : Address and length of the register set  - interrupts : Should contain uart interrupt +Optional properties: +- location : Decides the location of the USART I/O pins. +  Allowed range : [0 .. 5] +  Default: 0 +  Example:  uart@0x4000c400 {  	compatible = "efm32,uart";  	reg = <0x4000c400 0x400>;  	interrupts = <15>; +	location = <0>;  }; diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index de14bd7dce1..7d199c8e1a7 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -81,6 +81,7 @@ struct efm32_uart_port {  	struct uart_port port;  	unsigned int txirq;  	struct clk *clk; +	struct efm32_uart_pdata pdata;  };  #define to_efm_port(_port) container_of(_port, struct efm32_uart_port, port)  #define efm_debug(efm_port, format, arg...)			\ @@ -293,13 +294,8 @@ static irqreturn_t efm32_uart_txirq(int irq, void *data)  static int efm32_uart_startup(struct uart_port *port)  {  	struct efm32_uart_port *efm_port = to_efm_port(port); -	u32 location = 0; -	struct efm32_uart_pdata *pdata = dev_get_platdata(port->dev);  	int ret; -	if (pdata) -		location = UARTn_ROUTE_LOCATION(pdata->location); -  	ret = clk_enable(efm_port->clk);  	if (ret) {  		efm_debug(efm_port, "failed to enable clk\n"); @@ -308,7 +304,9 @@ static int efm32_uart_startup(struct uart_port *port)  	port->uartclk = clk_get_rate(efm_port->clk);  	/* Enable pins at configured location */ -	efm32_uart_write32(efm_port, location | UARTn_ROUTE_RXPEN | UARTn_ROUTE_TXPEN, +	efm32_uart_write32(efm_port, +			UARTn_ROUTE_LOCATION(efm_port->pdata.location) | +			UARTn_ROUTE_RXPEN | UARTn_ROUTE_TXPEN,  			UARTn_ROUTE);  	ret = request_irq(port->irq, efm32_uart_rxirq, 0, @@ -667,11 +665,24 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,  		struct efm32_uart_port *efm_port)  {  	struct device_node *np = pdev->dev.of_node; +	u32 location;  	int ret;  	if (!np)  		return 1; +	ret = of_property_read_u32(np, "location", &location); +	if (!ret) { +		if (location > 5) { +			dev_err(&pdev->dev, "invalid location\n"); +			return -EINVAL; +		} +		efm_debug(efm_port, "using location %u\n", location); +		efm_port->pdata.location = location; +	} else { +		efm_debug(efm_port, "fall back to location 0\n"); +	} +  	ret = of_alias_get_id(np, "serial");  	if (ret < 0) {  		dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); @@ -731,10 +742,16 @@ static int efm32_uart_probe(struct platform_device *pdev)  	efm_port->port.flags = UPF_BOOT_AUTOCONF;  	ret = efm32_uart_probe_dt(pdev, efm_port); -	if (ret > 0) +	if (ret > 0) {  		/* not created by device tree */ +		const struct efm32_uart_pdata *pdata = dev_get_platdata(&pdev->dev); +  		efm_port->port.line = pdev->id; +		if (pdata) +			efm_port->pdata = *pdata; +	} +  	if (efm_port->port.line >= 0 &&  			efm_port->port.line < ARRAY_SIZE(efm32_uart_ports))  		efm32_uart_ports[efm_port->port.line] = efm_port;  |