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