kernel: bump 4.9 to 4.9.156
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.9 / 816-tty-serial-support-layerscape.patch
1 From c35aec61e5bb0faafb2847a0d750ebd7345a4b0f Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Wed, 17 Jan 2018 15:40:24 +0800
4 Subject: [PATCH 28/30] tty: serial: support layerscape
5
6 This is an 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 @@ -1351,6 +1353,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 @@ -1400,22 +1414,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 @@ -1645,6 +1648,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 @@ -1659,6 +1669,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 @@ -1666,6 +1679,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 @@ -1680,6 +1700,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 @@ -1904,13 +1927,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 - }
127 - if (ret >= ARRAY_SIZE(lpuart_ports)) {
128 - dev_err(&pdev->dev, "serial%d out of range\n", ret);
129 - return -EINVAL;
130 + ret = find_first_zero_bit(linemap, UART_NR);
131 + if (ret >= UART_NR) {
132 + dev_err(&pdev->dev, "port line is full, add device failed\n");
133 + return ret;
134 + }
135 }
136 + set_bit(ret, linemap);
137 sport->port.line = ret;
138 sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
139
140 @@ -1992,6 +2015,7 @@ static int lpuart_remove(struct platform
141 struct lpuart_port *sport = platform_get_drvdata(pdev);
142
143 uart_remove_one_port(&lpuart_reg, &sport->port);
144 + clear_bit(sport->port.line, linemap);
145
146 clk_disable_unprepare(sport->clk);
147
148 @@ -2076,12 +2100,10 @@ static int lpuart_resume(struct device *
149
150 if (sport->lpuart_dma_rx_use) {
151 if (sport->port.irq_wake) {
152 - if (!lpuart_start_rx_dma(sport)) {
153 - sport->lpuart_dma_rx_use = true;
154 + if (!lpuart_start_rx_dma(sport))
155 rx_dma_timer_init(sport);
156 - } else {
157 + else
158 sport->lpuart_dma_rx_use = false;
159 - }
160 }
161 }
162