#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>
 #define UARTSFIFO_TXOF         0x02
 #define UARTSFIFO_RXUF         0x01
 
+/* 32-bit global registers only for i.MX7ULP/i.MX8x
+ * Used to reset all internal logic and registers, except the Global Register.
+ */
+#define UART_GLOBAL            0x8
+
 /* 32-bit register definition */
 #define UARTBAUD               0x00
 #define UARTSTAT               0x04
 #define UARTWATER_TXWATER_OFF  0
 #define UARTWATER_RXWATER_OFF  16
 
+#define UART_GLOBAL_RST        0x2
+#define GLOBAL_RST_MIN_US      20
+#define GLOBAL_RST_MAX_US      40
+
 /* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
 #define DMA_RX_TIMEOUT         (10)
 
                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;
 #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;
        if (ret)
                goto failed_attach_port;
 
+       ret = lpuart_global_reset(sport);
+       if (ret)
+               goto failed_reset;
+
        ret = uart_get_rs485_mode(&sport->port);
        if (ret)
                goto failed_get_rs485;
        return 0;
 
 failed_get_rs485:
+failed_reset:
+       uart_remove_one_port(&lpuart_reg, &sport->port);
 failed_attach_port:
 failed_irq_request:
        lpuart_disable_clks(sport);