dd28ef6c04edac39d3be538d98b302787e9a5481
[oweals/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 @@ -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,13 +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 -       }
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 @@ -1987,6 +2010,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 @@ -2071,12 +2095,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