| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- From d9d113c22c634219cc248a7c6dcf157e2927edad Mon Sep 17 00:00:00 2001
- From: Fugang Duan <[email protected]>
- Date: Tue, 23 Jul 2019 11:36:22 +0800
- Subject: [PATCH] MLK-21445 serial: fsl_lpuart: do HW reset for communication
- port
- Do HW reset for communication port after the port is registered
- if the UART controller support the feature.
- Do partition reset with LPUART's power on, LPUART registers will
- keep the previous status, like on i.MX8QM platform, which is not
- expected action, so reset the HW is required.
- Currently, only i.MX7ULP and i.MX8QM LPUART controllers include
- global register that support HW reset.
- Tested-by: Robin Gong <[email protected]>
- Tested-by: Peng Fan <[email protected]>
- Reviewed-by: Robby Cai <[email protected]>
- Signed-off-by: Fugang Duan <[email protected]>
- (cherry picked from commit c2bc1f62ec28981462c9cb5ceac17134931ca19f)
- Signed-off-by: Arulpandiyan Vadivel <[email protected]>
- Signed-off-by: Shrikant Bobade <[email protected]>
- (cherry picked from commit 9f396f540093402317c3c1b9a8fe955b91c89164)
- ---
- drivers/tty/serial/fsl_lpuart.c | 48 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 48 insertions(+)
- --- a/drivers/tty/serial/fsl_lpuart.c
- +++ b/drivers/tty/serial/fsl_lpuart.c
- @@ -11,6 +11,7 @@
-
- #include <linux/clk.h>
- #include <linux/console.h>
- +#include <linux/delay.h>
- #include <linux/dma-mapping.h>
- #include <linux/dmaengine.h>
- #include <linux/dmapool.h>
- @@ -116,6 +117,11 @@
- #define UARTSFIFO_TXOF 0x02
- #define UARTSFIFO_RXUF 0x01
-
- +/* 32-bit global registers only for i.MX7ulp/MX8x
- + * The driver only use the reset feature to reset HW.
- + */
- +#define UART_GLOBAL 0x8
- +
- /* 32-bit register definition */
- #define UARTBAUD 0x00
- #define UARTSTAT 0x04
- @@ -230,6 +236,10 @@
- #define UARTWATER_TXWATER_OFF 0
- #define UARTWATER_RXWATER_OFF 16
-
- +#define UART_GLOBAL_RST 0x2
- +#define RST_HW_MIN_US 20
- +#define RST_HW_MAX_US 40
- +
- #define UARTFIFO_RXIDEN_RDRF 0x3
- #define UARTCTRL_IDLECFG 0x7
-
- @@ -350,6 +360,11 @@ static inline bool is_layerscape_lpuart(
- sport->devtype == LS1028A_LPUART);
- }
-
- +static inline bool is_imx7ulp_lpuart(struct lpuart_port *sport)
- +{
- + return sport->devtype == IMX7ULP_LPUART;
- +}
- +
- static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
- {
- return sport->devtype == IMX8QXP_LPUART;
- @@ -413,6 +428,33 @@ static unsigned int lpuart_get_baud_clk_
- #define lpuart_enable_clks(x) __lpuart_enable_clks(x, true)
- #define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
-
- +static int lpuart_hw_reset(struct lpuart_port *sport)
- +{
- + struct uart_port *port = &sport->port;
- + void __iomem *global_addr;
- + int ret;
- +
- + if (uart_console(port))
- + return 0;
- +
- + ret = clk_prepare_enable(sport->ipg_clk);
- + if (ret) {
- + dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret);
- + return ret;
- + }
- +
- + if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) {
- + global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
- + writel(UART_GLOBAL_RST, global_addr);
- + usleep_range(RST_HW_MIN_US, RST_HW_MAX_US);
- + writel(0, global_addr);
- + usleep_range(RST_HW_MIN_US, RST_HW_MAX_US);
- + }
- +
- + clk_disable_unprepare(sport->ipg_clk);
- + return 0;
- +}
- +
- static void lpuart_stop_tx(struct uart_port *port)
- {
- unsigned char temp;
- @@ -2728,6 +2770,10 @@ static int lpuart_probe(struct platform_
- if (ret)
- goto failed_attach_port;
-
- + ret = lpuart_hw_reset(sport);
- + if (ret)
- + goto failed_reset;
- +
- uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
-
- if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)
- @@ -2751,6 +2797,8 @@ static int lpuart_probe(struct platform_
-
- return 0;
-
- +failed_reset:
- + uart_remove_one_port(&lpuart_reg, &sport->port);
- failed_attach_port:
- failed_irq_request:
- lpuart_disable_clks(sport);
|