layerscape: refresh patches
[openwrt/staging/hauke.git] / target / linux / layerscape / patches-4.9 / 816-tty-serial-support-layerscape.patch
1 From 469daac0faff06209bc1d1390571b860d153a82b Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Wed, 27 Sep 2017 10:33:47 +0800
4 Subject: [PATCH] tty: serial: support layerscape
5
6 This is a integrated patch for layerscape uart support.
7
8 Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
9 Signed-off-by: Yuan Yao <yao.yuan@nxp.com>
10 Signed-off-by: Stefan Agner <stefan@agner.ch>
11 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
12 ---
13 drivers/tty/serial/fsl_lpuart.c | 66 ++++++++++++++++++++++++++++-------------
14 1 file changed, 46 insertions(+), 20 deletions(-)
15
16 --- a/drivers/tty/serial/fsl_lpuart.c
17 +++ b/drivers/tty/serial/fsl_lpuart.c
18 @@ -231,6 +231,8 @@
19 #define DEV_NAME "ttyLP"
20 #define UART_NR 6
21
22 +static DECLARE_BITMAP(linemap, UART_NR);
23 +
24 struct lpuart_port {
25 struct uart_port port;
26 struct clk *clk;
27 @@ -1348,6 +1350,18 @@ lpuart_set_termios(struct uart_port *por
28 /* ask the core to calculate the divisor */
29 baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
30
31 + /*
32 + * Need to update the Ring buffer length according to the selected
33 + * baud rate and restart Rx DMA path.
34 + *
35 + * Since timer function acqures sport->port.lock, need to stop before
36 + * acquring same lock because otherwise del_timer_sync() can deadlock.
37 + */
38 + if (old && sport->lpuart_dma_rx_use) {
39 + del_timer_sync(&sport->lpuart_timer);
40 + lpuart_dma_rx_free(&sport->port);
41 + }
42 +
43 spin_lock_irqsave(&sport->port.lock, flags);
44
45 sport->port.read_status_mask = 0;
46 @@ -1397,22 +1411,11 @@ lpuart_set_termios(struct uart_port *por
47 /* restore control register */
48 writeb(old_cr2, sport->port.membase + UARTCR2);
49
50 - /*
51 - * If new baud rate is set, we will also need to update the Ring buffer
52 - * length according to the selected baud rate and restart Rx DMA path.
53 - */
54 - if (old) {
55 - if (sport->lpuart_dma_rx_use) {
56 - del_timer_sync(&sport->lpuart_timer);
57 - lpuart_dma_rx_free(&sport->port);
58 - }
59 -
60 - if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
61 - sport->lpuart_dma_rx_use = true;
62 + if (old && sport->lpuart_dma_rx_use) {
63 + if (!lpuart_start_rx_dma(sport))
64 rx_dma_timer_init(sport);
65 - } else {
66 + else
67 sport->lpuart_dma_rx_use = false;
68 - }
69 }
70
71 spin_unlock_irqrestore(&sport->port.lock, flags);
72 @@ -1640,6 +1643,13 @@ lpuart_console_write(struct console *co,
73 {
74 struct lpuart_port *sport = lpuart_ports[co->index];
75 unsigned char old_cr2, cr2;
76 + unsigned long flags;
77 + int locked = 1;
78 +
79 + if (sport->port.sysrq || oops_in_progress)
80 + locked = spin_trylock_irqsave(&sport->port.lock, flags);
81 + else
82 + spin_lock_irqsave(&sport->port.lock, flags);
83
84 /* first save CR2 and then disable interrupts */
85 cr2 = old_cr2 = readb(sport->port.membase + UARTCR2);
86 @@ -1654,6 +1664,9 @@ lpuart_console_write(struct console *co,
87 barrier();
88
89 writeb(old_cr2, sport->port.membase + UARTCR2);
90 +
91 + if (locked)
92 + spin_unlock_irqrestore(&sport->port.lock, flags);
93 }
94
95 static void
96 @@ -1661,6 +1674,13 @@ lpuart32_console_write(struct console *c
97 {
98 struct lpuart_port *sport = lpuart_ports[co->index];
99 unsigned long old_cr, cr;
100 + unsigned long flags;
101 + int locked = 1;
102 +
103 + if (sport->port.sysrq || oops_in_progress)
104 + locked = spin_trylock_irqsave(&sport->port.lock, flags);
105 + else
106 + spin_lock_irqsave(&sport->port.lock, flags);
107
108 /* first save CR2 and then disable interrupts */
109 cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
110 @@ -1675,6 +1695,9 @@ lpuart32_console_write(struct console *c
111 barrier();
112
113 lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
114 +
115 + if (locked)
116 + spin_unlock_irqrestore(&sport->port.lock, flags);
117 }
118
119 /*
120 @@ -1899,9 +1922,13 @@ static int lpuart_probe(struct platform_
121
122 ret = of_alias_get_id(np, "serial");
123 if (ret < 0) {
124 - dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
125 - return ret;
126 + ret = find_first_zero_bit(linemap, UART_NR);
127 + if (ret >= UART_NR) {
128 + dev_err(&pdev->dev, "port line is full, add device failed\n");
129 + return ret;
130 + }
131 }
132 + set_bit(ret, linemap);
133 sport->port.line = ret;
134 sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
135
136 @@ -1983,6 +2010,7 @@ static int lpuart_remove(struct platform
137 struct lpuart_port *sport = platform_get_drvdata(pdev);
138
139 uart_remove_one_port(&lpuart_reg, &sport->port);
140 + clear_bit(sport->port.line, linemap);
141
142 clk_disable_unprepare(sport->clk);
143
144 @@ -2067,12 +2095,10 @@ static int lpuart_resume(struct device *
145
146 if (sport->lpuart_dma_rx_use) {
147 if (sport->port.irq_wake) {
148 - if (!lpuart_start_rx_dma(sport)) {
149 - sport->lpuart_dma_rx_use = true;
150 + if (!lpuart_start_rx_dma(sport))
151 rx_dma_timer_init(sport);
152 - } else {
153 + else
154 sport->lpuart_dma_rx_use = false;
155 - }
156 }
157 }
158