Hi bruce

Please help merge this patch to v5.15/standard/nxp-sdk-5.15/nxp-soc and 
v5.15/standard/preempt-rt/nxp-sdk-5.15/nxp-soc branches

thanks
xiaolei
________________________________
From: [email protected] <[email protected]> 
on behalf of Xiaolei Wang via lists.yoctoproject.org 
<[email protected]>
Sent: Monday, March 13, 2023 9:44 PM
To: [email protected] <[email protected]>
Cc: [email protected] <[email protected]>
Subject: [linux-yocto] [PATCH] tty: serial: fsl_lpuart: don't break the 
on-going transfer when global reset

From: Sherry Sun <[email protected]>

commit 76bad3f88750f8cc465c489e6846249e0bc3d8f5 from upstream.

lpuart_global_reset() shouldn't break the on-going transmit engine, need
to recover the on-going data transfer after reset.

This can help earlycon here, since commit 60f361722ad2 ("serial:
fsl_lpuart: Reset prior to registration") moved lpuart_global_reset()
before uart_add_one_port(), earlycon is writing during global reset,
as global reset will disable the TX and clear the baud rate register,
which caused the earlycon cannot work any more after reset, needs to
restore the baud rate and re-enable the transmitter to recover the
earlycon write.

Also move the lpuart_global_reset() down, then we can reuse the
lpuart32_tx_empty() without declaration.

Fixes: bd5305dcabbc ("tty: serial: fsl_lpuart: do software reset for imx7ulp 
and imx8qxp")
Signed-off-by: Sherry Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Xiaolei Wang <[email protected]>
---
 drivers/tty/serial/fsl_lpuart.c | 75 +++++++++++++++++++++------------
 1 file changed, 48 insertions(+), 27 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 3f8fe874905d..5eae048950b5 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -433,33 +433,6 @@ static unsigned int lpuart_get_baud_clk_rate(struct 
lpuart_port *sport)
 #define lpuart_enable_clks(x)   __lpuart_enable_clks(x, true)
 #define lpuart_disable_clks(x)  __lpuart_enable_clks(x, false)

-static int lpuart_global_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_imx8ulp_lpuart(sport) || 
is_imx8qxp_lpuart(sport)) {
-               global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
-               writel(UART_GLOBAL_RST, global_addr);
-               usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
-               writel(0, global_addr);
-               usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
-       }
-
-       clk_disable_unprepare(sport->ipg_clk);
-       return 0;
-}
-
 static void lpuart_stop_tx(struct uart_port *port)
 {
         unsigned char temp;
@@ -2845,6 +2818,54 @@ static int lpuart_attach_pd(struct device *dev)
         return 0;
 }

+static int lpuart_global_reset(struct lpuart_port *sport)
+{
+       struct uart_port *port = &sport->port;
+       void __iomem *global_addr;
+       unsigned long ctrl, bd;
+       unsigned int val = 0;
+       int ret;
+
+       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)) {
+               /*
+                * If the transmitter is used by earlycon, wait for transmit 
engine to
+                * complete and then reset.
+               */
+               ctrl = lpuart32_read(port, UARTCTRL);
+               if (ctrl & UARTCTRL_TE) {
+                       bd = lpuart32_read(&sport->port, UARTBAUD);
+                       if (read_poll_timeout(lpuart32_tx_empty, val, val, 1, 
100000, false,
+                               port)) {
+                               dev_warn(sport->port.dev,
+                                       "timeout waiting for transmit engine to 
complete\n");
+                               clk_disable_unprepare(sport->ipg_clk);
+                               return 0;
+                       }
+               }
+
+               global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
+               writel(UART_GLOBAL_RST, global_addr);
+               usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
+               writel(0, global_addr);
+               usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
+
+               /* Recover the transmitter for earlycon. */
+               if (ctrl & UARTCTRL_TE) {
+                       lpuart32_write(port, bd, UARTBAUD);
+                       lpuart32_write(port, ctrl, UARTCTRL);
+               }
+                                                                               
        }
+
+       clk_disable_unprepare(sport->ipg_clk);
+       return 0;
+}
+
 static int lpuart_probe(struct platform_device *pdev)
 {
         const struct lpuart_soc_data *sdata = 
of_device_get_match_data(&pdev->dev);
--
2.25.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#12255): 
https://lists.yoctoproject.org/g/linux-yocto/message/12255
Mute This Topic: https://lists.yoctoproject.org/mt/97580546/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to