ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 819-uart-0008-MLK-21445-serial-fsl_lpuart-do-HW-reset-for-communic.patch
1 From d9d113c22c634219cc248a7c6dcf157e2927edad Mon Sep 17 00:00:00 2001
2 From: Fugang Duan <fugang.duan@nxp.com>
3 Date: Tue, 23 Jul 2019 11:36:22 +0800
4 Subject: [PATCH] MLK-21445 serial: fsl_lpuart: do HW reset for communication
5  port
6
7 Do HW reset for communication port after the port is registered
8 if the UART controller support the feature.
9
10 Do partition reset with LPUART's power on, LPUART registers will
11 keep the previous status, like on i.MX8QM platform,  which is not
12 expected action, so reset the HW is required.
13
14 Currently, only i.MX7ULP and i.MX8QM LPUART controllers include
15 global register that support HW reset.
16
17 Tested-by: Robin Gong <yibin.gong@nxp.com>
18 Tested-by: Peng Fan <peng.fan@nxp.com>
19 Reviewed-by: Robby Cai <robby.cai@nxp.com>
20 Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
21 (cherry picked from commit c2bc1f62ec28981462c9cb5ceac17134931ca19f)
22 Signed-off-by: Arulpandiyan Vadivel <arulpandiyan_vadivel@mentor.com>
23 Signed-off-by: Shrikant Bobade <Shrikant_Bobade@mentor.com>
24 (cherry picked from commit 9f396f540093402317c3c1b9a8fe955b91c89164)
25 ---
26  drivers/tty/serial/fsl_lpuart.c | 48 +++++++++++++++++++++++++++++++++++++++++
27  1 file changed, 48 insertions(+)
28
29 --- a/drivers/tty/serial/fsl_lpuart.c
30 +++ b/drivers/tty/serial/fsl_lpuart.c
31 @@ -11,6 +11,7 @@
32  
33  #include <linux/clk.h>
34  #include <linux/console.h>
35 +#include <linux/delay.h>
36  #include <linux/dma-mapping.h>
37  #include <linux/dmaengine.h>
38  #include <linux/dmapool.h>
39 @@ -116,6 +117,11 @@
40  #define UARTSFIFO_TXOF         0x02
41  #define UARTSFIFO_RXUF         0x01
42  
43 +/* 32-bit global registers only for i.MX7ulp/MX8x
44 + * The driver only use the reset feature to reset HW.
45 + */
46 +#define UART_GLOBAL            0x8
47 +
48  /* 32-bit register definition */
49  #define UARTBAUD               0x00
50  #define UARTSTAT               0x04
51 @@ -230,6 +236,10 @@
52  #define UARTWATER_TXWATER_OFF  0
53  #define UARTWATER_RXWATER_OFF  16
54  
55 +#define UART_GLOBAL_RST                0x2
56 +#define RST_HW_MIN_US          20
57 +#define RST_HW_MAX_US          40
58 +
59  #define UARTFIFO_RXIDEN_RDRF   0x3
60  #define UARTCTRL_IDLECFG       0x7
61  
62 @@ -335,6 +345,11 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
63  static void lpuart_dma_tx_complete(void *arg);
64  static int lpuart_sched_rx_dma(struct lpuart_port *sport);
65  
66 +static inline bool is_imx7ulp_lpuart(struct lpuart_port *sport)
67 +{
68 +       return sport->devtype == IMX7ULP_LPUART;
69 +}
70 +
71  static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
72  {
73         return sport->devtype == IMX8QXP_LPUART;
74 @@ -398,6 +413,33 @@ static unsigned int lpuart_get_baud_clk_
75  #define lpuart_enable_clks(x)  __lpuart_enable_clks(x, true)
76  #define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
77  
78 +static int lpuart_hw_reset(struct lpuart_port *sport)
79 +{
80 +       struct uart_port *port = &sport->port;
81 +       void __iomem *global_addr;
82 +       int ret;
83 +
84 +       if (uart_console(port))
85 +               return 0;
86 +
87 +       ret = clk_prepare_enable(sport->ipg_clk);
88 +       if (ret) {
89 +               dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret);
90 +               return ret;
91 +       }
92 +
93 +       if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) {
94 +               global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
95 +               writel(UART_GLOBAL_RST, global_addr);
96 +               usleep_range(RST_HW_MIN_US, RST_HW_MAX_US);
97 +               writel(0, global_addr);
98 +               usleep_range(RST_HW_MIN_US, RST_HW_MAX_US);
99 +       }
100 +
101 +       clk_disable_unprepare(sport->ipg_clk);
102 +       return 0;
103 +}
104 +
105  static void lpuart_stop_tx(struct uart_port *port)
106  {
107         unsigned char temp;
108 @@ -2704,6 +2746,10 @@ static int lpuart_probe(struct platform_
109         if (ret)
110                 goto failed_attach_port;
111  
112 +       ret = lpuart_hw_reset(sport);
113 +       if (ret)
114 +               goto failed_reset;
115 +
116         uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
117  
118         if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)
119 @@ -2727,6 +2773,8 @@ static int lpuart_probe(struct platform_
120  
121         return 0;
122  
123 +failed_reset:
124 +       uart_remove_one_port(&lpuart_reg, &sport->port);
125  failed_attach_port:
126  failed_irq_request:
127         lpuart_disable_clks(sport);