#include <linux/dmaengine.h>
 #include <linux/dmapool.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #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_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;
        /* delay_rts_* and RX_DURING_TX are not supported */
 };
 
+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);