summaryrefslogtreecommitdiffstats
path: root/configs/platform-energymicro-efm32gg-dk3750/patches/linux-3.8-rc5/0008-serial-efm32-parse-location-property.patch
blob: 76bf1c128e598564bc137fb13ea8f29670ed69cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Date: Mon, 21 Jan 2013 14:04:47 +0100
Subject: [PATCH] serial/efm32: parse location property
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The non-dt probing allowed passing the location via platform data from
the beginning. So make up leeway for device tree probing.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Applied-Upstream: next-20130128, commit:c098020d0368ded1c6ba8d7b612feffe067509a6
---
 .../devicetree/bindings/tty/serial/efm32-uart.txt  |    6 ++++
 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 6588b69..8e080b8 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 a8cbb26..67ff23b 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...)			\
@@ -300,13 +301,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");
@@ -315,7 +311,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,
@@ -674,11 +672,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);
@@ -738,10 +749,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;