These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / tty / serial / imx.c
index 01aa52f..016e4be 100644 (file)
 #define USR1_ESCF      (1<<11) /* Escape seq interrupt flag */
 #define USR1_FRAMERR   (1<<10) /* Frame error interrupt flag */
 #define USR1_RRDY      (1<<9)   /* Receiver ready interrupt/dma flag */
+#define USR1_AGTIM     (1<<8)   /* Ageing timer interrupt flag */
 #define USR1_TIMEOUT   (1<<7)   /* Receive timeout interrupt status */
 #define USR1_RXDS       (1<<6)  /* Receiver idle interrupt flag */
 #define USR1_AIRINT     (1<<5)  /* Async IR wake interrupt flag */
@@ -216,6 +217,8 @@ struct imx_port {
        unsigned int            tx_bytes;
        unsigned int            dma_tx_nents;
        wait_queue_head_t       dma_wait;
+       unsigned int            saved_reg[10];
+       bool                    context_saved;
 };
 
 struct imx_port_ucrs {
@@ -239,7 +242,7 @@ static struct imx_uart_data imx_uart_devdata[] = {
        },
 };
 
-static struct platform_device_id imx_uart_devtype[] = {
+static const struct platform_device_id imx_uart_devtype[] = {
        {
                .name = "imx1-uart",
                .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
@@ -700,7 +703,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
                if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
                        goto out;
 
-               tty_insert_flip_char(port, rx, flg);
+               if (tty_insert_flip_char(port, rx, flg) == 0)
+                       sport->port.icount.buf_overrun++;
        }
 
 out:
@@ -725,11 +729,15 @@ static void imx_dma_rxint(struct imx_port *sport)
        if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
                sport->dma_is_rxing = 1;
 
-               /* disable the `Recerver Ready Interrrupt` */
+               /* disable the receiver ready and aging timer interrupts */
                temp = readl(sport->port.membase + UCR1);
                temp &= ~(UCR1_RRDYEN);
                writel(temp, sport->port.membase + UCR1);
 
+               temp = readl(sport->port.membase + UCR2);
+               temp &= ~(UCR2_ATEN);
+               writel(temp, sport->port.membase + UCR2);
+
                /* tell the DMA to receive the data. */
                start_rx_dma(sport);
        }
@@ -746,7 +754,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
        sts = readl(sport->port.membase + USR1);
        sts2 = readl(sport->port.membase + USR2);
 
-       if (sts & USR1_RRDY) {
+       if (sts & (USR1_RRDY | USR1_AGTIM)) {
                if (sport->dma_is_enabled)
                        imx_dma_rxint(sport);
                else
@@ -766,7 +774,6 @@ static irqreturn_t imx_int(int irq, void *dev_id)
                writel(USR1_AWAKE, sport->port.membase + USR1);
 
        if (sts2 & USR2_ORE) {
-               dev_err(sport->port.dev, "Rx FIFO overrun\n");
                sport->port.icount.overrun++;
                writel(USR2_ORE, sport->port.membase + USR2);
        }
@@ -850,20 +857,6 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
        spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-#define TXTL 2 /* reset default */
-#define RXTL 1 /* reset default */
-
-static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
-{
-       unsigned int val;
-
-       /* set receiver / transmitter trigger level */
-       val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
-       val |= TXTL << UFCR_TXTL_SHF | RXTL;
-       writel(val, sport->port.membase + UFCR);
-       return 0;
-}
-
 #define RX_BUF_SIZE    (PAGE_SIZE)
 static void imx_rx_dma_done(struct imx_port *sport)
 {
@@ -872,11 +865,15 @@ static void imx_rx_dma_done(struct imx_port *sport)
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
-       /* Enable this interrupt when the RXFIFO is empty. */
+       /* re-enable interrupts to get notified when new symbols are incoming */
        temp = readl(sport->port.membase + UCR1);
        temp |= UCR1_RRDYEN;
        writel(temp, sport->port.membase + UCR1);
 
+       temp = readl(sport->port.membase + UCR2);
+       temp |= UCR2_ATEN;
+       writel(temp, sport->port.membase + UCR2);
+
        sport->dma_is_rxing = 0;
 
        /* Is the shutdown waiting for us? */
@@ -887,14 +884,12 @@ static void imx_rx_dma_done(struct imx_port *sport)
 }
 
 /*
- * There are three kinds of RX DMA interrupts(such as in the MX6Q):
+ * There are two kinds of RX DMA interrupts(such as in the MX6Q):
  *   [1] the RX DMA buffer is full.
- *   [2] the Aging timer expires(wait for 8 bytes long)
- *   [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
+ *   [2] the aging timer expires
  *
- * The [2] is trigger when a character was been sitting in the FIFO
- * meanwhile [3] can wait for 32 bytes long when the RX line is
- * on IDLE state and RxFIFO is empty.
+ * Condition [2] is triggered when a character has been sitting in the FIFO
+ * for at least 8 byte durations.
  */
 static void dma_rx_callback(void *data)
 {
@@ -912,36 +907,32 @@ static void dma_rx_callback(void *data)
        status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
        count = RX_BUF_SIZE - state.residue;
 
-       if (readl(sport->port.membase + USR2) & USR2_IDLE) {
-               /* In condition [3] the SDMA counted up too early */
-               count--;
-
-               writel(USR2_IDLE, sport->port.membase + USR2);
-       }
-
        dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
 
        if (count) {
-               if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ))
-                       tty_insert_flip_string(port, sport->rx_buf, count);
+               if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
+                       int bytes = tty_insert_flip_string(port, sport->rx_buf,
+                                       count);
+
+                       if (bytes != count)
+                               sport->port.icount.buf_overrun++;
+               }
                tty_flip_buffer_push(port);
+               sport->port.icount.rx += count;
+       }
 
+       /*
+        * Restart RX DMA directly if more data is available in order to skip
+        * the roundtrip through the IRQ handler. If there is some data already
+        * in the FIFO, DMA needs to be restarted soon anyways.
+        *
+        * Otherwise stop the DMA and reactivate FIFO IRQs to restart DMA once
+        * data starts to arrive again.
+        */
+       if (readl(sport->port.membase + USR2) & USR2_RDR)
                start_rx_dma(sport);
-       } else if (readl(sport->port.membase + USR2) & USR2_RDR) {
-               /*
-                * start rx_dma directly once data in RXFIFO, more efficient
-                * than before:
-                *      1. call imx_rx_dma_done to stop dma if no data received
-                *      2. wait next  RDR interrupt to start dma transfer.
-                */
-               start_rx_dma(sport);
-       } else {
-               /*
-                * stop dma to prevent too many IDLE event trigged if no data
-                * in RXFIFO
-                */
+       else
                imx_rx_dma_done(sport);
-       }
 }
 
 static int start_rx_dma(struct imx_port *sport)
@@ -974,6 +965,22 @@ static int start_rx_dma(struct imx_port *sport)
        return 0;
 }
 
+#define TXTL_DEFAULT 2 /* reset default */
+#define RXTL_DEFAULT 1 /* reset default */
+#define TXTL_DMA 8 /* DMA burst setting */
+#define RXTL_DMA 9 /* DMA burst setting */
+
+static void imx_setup_ufcr(struct imx_port *sport,
+                         unsigned char txwl, unsigned char rxwl)
+{
+       unsigned int val;
+
+       /* set receiver / transmitter trigger level */
+       val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+       val |= txwl << UFCR_TXTL_SHF | rxwl;
+       writel(val, sport->port.membase + UFCR);
+}
+
 static void imx_uart_dma_exit(struct imx_port *sport)
 {
        if (sport->dma_chan_rx) {
@@ -1009,7 +1016,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
        slave_config.direction = DMA_DEV_TO_MEM;
        slave_config.src_addr = sport->port.mapbase + URXD0;
        slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-       slave_config.src_maxburst = RXTL;
+       /* one byte less than the watermark level to enable the aging timer */
+       slave_config.src_maxburst = RXTL_DMA - 1;
        ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
        if (ret) {
                dev_err(dev, "error in RX dma configuration.\n");
@@ -1033,7 +1041,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
        slave_config.direction = DMA_MEM_TO_DEV;
        slave_config.dst_addr = sport->port.mapbase + URTX0;
        slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-       slave_config.dst_maxburst = TXTL;
+       slave_config.dst_maxburst = TXTL_DMA;
        ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
        if (ret) {
                dev_err(dev, "error in TX dma configuration.");
@@ -1056,15 +1064,14 @@ static void imx_enable_dma(struct imx_port *sport)
 
        /* set UCR1 */
        temp = readl(sport->port.membase + UCR1);
-       temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
-               /* wait for 32 idle frames for IDDMA interrupt */
-               UCR1_ICD_REG(3);
+       temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
        writel(temp, sport->port.membase + UCR1);
 
-       /* set UCR4 */
-       temp = readl(sport->port.membase + UCR4);
-       temp |= UCR4_IDDMAEN;
-       writel(temp, sport->port.membase + UCR4);
+       temp = readl(sport->port.membase + UCR2);
+       temp |= UCR2_ATEN;
+       writel(temp, sport->port.membase + UCR2);
+
+       imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
 
        sport->dma_is_enabled = 1;
 }
@@ -1080,13 +1087,10 @@ static void imx_disable_dma(struct imx_port *sport)
 
        /* clear UCR2 */
        temp = readl(sport->port.membase + UCR2);
-       temp &= ~(UCR2_CTSC | UCR2_CTS);
+       temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
        writel(temp, sport->port.membase + UCR2);
 
-       /* clear UCR4 */
-       temp = readl(sport->port.membase + UCR4);
-       temp &= ~UCR4_IDDMAEN;
-       writel(temp, sport->port.membase + UCR4);
+       imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
        sport->dma_is_enabled = 0;
 }
@@ -1109,7 +1113,7 @@ static int imx_startup(struct uart_port *port)
                return retval;
        }
 
-       imx_setup_ufcr(sport, 0);
+       imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
        /* disable the DREN bit (Data Ready interrupt enable) before
         * requesting IRQs
@@ -1122,6 +1126,12 @@ static int imx_startup(struct uart_port *port)
 
        writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
+       /* Can we enable the DMA support? */
+       if (is_imx6q_uart(sport) && !uart_console(port) &&
+           !sport->dma_is_inited)
+               imx_uart_dma_init(sport);
+
+       spin_lock_irqsave(&sport->port.lock, flags);
        /* Reset fifo's and state machines */
        i = 100;
 
@@ -1132,14 +1142,15 @@ static int imx_startup(struct uart_port *port)
        while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
                udelay(1);
 
-       spin_lock_irqsave(&sport->port.lock, flags);
-
        /*
         * Finally, clear and enable interrupts
         */
        writel(USR1_RTSD, sport->port.membase + USR1);
        writel(USR2_ORE, sport->port.membase + USR2);
 
+       if (sport->dma_is_inited && !sport->dma_is_enabled)
+               imx_enable_dma(sport);
+
        temp = readl(sport->port.membase + UCR1);
        temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 
@@ -1273,7 +1284,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long flags;
-       unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
+       unsigned int ucr2, old_ucr1, old_ucr2, baud, quot;
        unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
        unsigned int div, ufcr;
        unsigned long num, denom;
@@ -1310,11 +1321,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
                        } else {
                                ucr2 |= UCR2_CTSC;
                        }
-
-                       /* Can we enable the DMA support? */
-                       if (is_imx6q_uart(sport) && !uart_console(port)
-                               && !sport->dma_is_inited)
-                               imx_uart_dma_init(sport);
                } else {
                        termios->c_cflag &= ~CRTSCTS;
                }
@@ -1382,10 +1388,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
                barrier();
 
        /* then, disable everything */
-       old_txrxen = readl(sport->port.membase + UCR2);
-       writel(old_txrxen & ~(UCR2_TXEN | UCR2_RXEN),
+       old_ucr2 = readl(sport->port.membase + UCR2);
+       writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
                        sport->port.membase + UCR2);
-       old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
+       old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
 
        /* custom-baudrate handling */
        div = sport->port.uartclk / (baud * 16);
@@ -1426,13 +1432,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        writel(old_ucr1, sport->port.membase + UCR1);
 
        /* set the parity, stop bits and data size */
-       writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
+       writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
 
        if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
                imx_enable_ms(&sport->port);
 
-       if (sport->dma_is_inited && !sport->dma_is_enabled)
-               imx_enable_dma(sport);
        spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
@@ -1498,7 +1502,7 @@ static int imx_poll_init(struct uart_port *port)
        if (retval)
                clk_disable_unprepare(sport->clk_ipg);
 
-       imx_setup_ufcr(sport, 0);
+       imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
@@ -1768,7 +1772,7 @@ imx_console_setup(struct console *co, char *options)
        else
                imx_console_get_options(sport, &baud, &parity, &bits);
 
-       imx_setup_ufcr(sport, 0);
+       imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
        retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
@@ -1798,6 +1802,38 @@ static struct console imx_console = {
 };
 
 #define IMX_CONSOLE    &imx_console
+
+#ifdef CONFIG_OF
+static void imx_console_early_putchar(struct uart_port *port, int ch)
+{
+       while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
+               cpu_relax();
+
+       writel_relaxed(ch, port->membase + URTX0);
+}
+
+static void imx_console_early_write(struct console *con, const char *s,
+                                   unsigned count)
+{
+       struct earlycon_device *dev = con->data;
+
+       uart_console_write(&dev->port, s, count, imx_console_early_putchar);
+}
+
+static int __init
+imx_console_early_setup(struct earlycon_device *dev, const char *opt)
+{
+       if (!dev->port.membase)
+               return -ENODEV;
+
+       dev->con->write = imx_console_early_write;
+
+       return 0;
+}
+OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
+OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
+#endif
+
 #else
 #define IMX_CONSOLE    NULL
 #endif
@@ -1812,36 +1848,6 @@ static struct uart_driver imx_reg = {
        .cons           = IMX_CONSOLE,
 };
 
-static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct imx_port *sport = platform_get_drvdata(dev);
-       unsigned int val;
-
-       /* enable wakeup from i.MX UART */
-       val = readl(sport->port.membase + UCR3);
-       val |= UCR3_AWAKEN;
-       writel(val, sport->port.membase + UCR3);
-
-       uart_suspend_port(&imx_reg, &sport->port);
-
-       return 0;
-}
-
-static int serial_imx_resume(struct platform_device *dev)
-{
-       struct imx_port *sport = platform_get_drvdata(dev);
-       unsigned int val;
-
-       /* disable wakeup from i.MX UART */
-       val = readl(sport->port.membase + UCR3);
-       val &= ~UCR3_AWAKEN;
-       writel(val, sport->port.membase + UCR3);
-
-       uart_resume_port(&imx_reg, &sport->port);
-
-       return 0;
-}
-
 #ifdef CONFIG_OF
 /*
  * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
@@ -1903,7 +1909,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 {
        struct imx_port *sport;
        void __iomem *base;
-       int ret = 0;
+       int ret = 0, reg;
        struct resource *res;
        int txirq, rxirq, rtsirq;
 
@@ -1958,6 +1964,19 @@ static int serial_imx_probe(struct platform_device *pdev)
 
        sport->port.uartclk = clk_get_rate(sport->clk_per);
 
+       /* For register access, we only need to enable the ipg clock. */
+       ret = clk_prepare_enable(sport->clk_ipg);
+       if (ret)
+               return ret;
+
+       /* Disable interrupts before requesting them */
+       reg = readl_relaxed(sport->port.membase + UCR1);
+       reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
+                UCR1_TXMPTYEN | UCR1_RTSDEN);
+       writel_relaxed(reg, sport->port.membase + UCR1);
+
+       clk_disable_unprepare(sport->clk_ipg);
+
        /*
         * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
         * chips only have one interrupt.
@@ -1993,16 +2012,135 @@ static int serial_imx_remove(struct platform_device *pdev)
        return uart_remove_one_port(&imx_reg, &sport->port);
 }
 
+static void serial_imx_restore_context(struct imx_port *sport)
+{
+       if (!sport->context_saved)
+               return;
+
+       writel(sport->saved_reg[4], sport->port.membase + UFCR);
+       writel(sport->saved_reg[5], sport->port.membase + UESC);
+       writel(sport->saved_reg[6], sport->port.membase + UTIM);
+       writel(sport->saved_reg[7], sport->port.membase + UBIR);
+       writel(sport->saved_reg[8], sport->port.membase + UBMR);
+       writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
+       writel(sport->saved_reg[0], sport->port.membase + UCR1);
+       writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
+       writel(sport->saved_reg[2], sport->port.membase + UCR3);
+       writel(sport->saved_reg[3], sport->port.membase + UCR4);
+       sport->context_saved = false;
+}
+
+static void serial_imx_save_context(struct imx_port *sport)
+{
+       /* Save necessary regs */
+       sport->saved_reg[0] = readl(sport->port.membase + UCR1);
+       sport->saved_reg[1] = readl(sport->port.membase + UCR2);
+       sport->saved_reg[2] = readl(sport->port.membase + UCR3);
+       sport->saved_reg[3] = readl(sport->port.membase + UCR4);
+       sport->saved_reg[4] = readl(sport->port.membase + UFCR);
+       sport->saved_reg[5] = readl(sport->port.membase + UESC);
+       sport->saved_reg[6] = readl(sport->port.membase + UTIM);
+       sport->saved_reg[7] = readl(sport->port.membase + UBIR);
+       sport->saved_reg[8] = readl(sport->port.membase + UBMR);
+       sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
+       sport->context_saved = true;
+}
+
+static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
+{
+       unsigned int val;
+
+       val = readl(sport->port.membase + UCR3);
+       if (on)
+               val |= UCR3_AWAKEN;
+       else
+               val &= ~UCR3_AWAKEN;
+       writel(val, sport->port.membase + UCR3);
+
+       val = readl(sport->port.membase + UCR1);
+       if (on)
+               val |= UCR1_RTSDEN;
+       else
+               val &= ~UCR1_RTSDEN;
+       writel(val, sport->port.membase + UCR1);
+}
+
+static int imx_serial_port_suspend_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = clk_enable(sport->clk_ipg);
+       if (ret)
+               return ret;
+
+       serial_imx_save_context(sport);
+
+       clk_disable(sport->clk_ipg);
+
+       return 0;
+}
+
+static int imx_serial_port_resume_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = clk_enable(sport->clk_ipg);
+       if (ret)
+               return ret;
+
+       serial_imx_restore_context(sport);
+
+       clk_disable(sport->clk_ipg);
+
+       return 0;
+}
+
+static int imx_serial_port_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+
+       /* enable wakeup from i.MX UART */
+       serial_imx_enable_wakeup(sport, true);
+
+       uart_suspend_port(&imx_reg, &sport->port);
+
+       return 0;
+}
+
+static int imx_serial_port_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+
+       /* disable wakeup from i.MX UART */
+       serial_imx_enable_wakeup(sport, false);
+
+       uart_resume_port(&imx_reg, &sport->port);
+
+       return 0;
+}
+
+static const struct dev_pm_ops imx_serial_port_pm_ops = {
+       .suspend_noirq = imx_serial_port_suspend_noirq,
+       .resume_noirq = imx_serial_port_resume_noirq,
+       .suspend = imx_serial_port_suspend,
+       .resume = imx_serial_port_resume,
+};
+
 static struct platform_driver serial_imx_driver = {
        .probe          = serial_imx_probe,
        .remove         = serial_imx_remove,
 
-       .suspend        = serial_imx_suspend,
-       .resume         = serial_imx_resume,
        .id_table       = imx_uart_devtype,
        .driver         = {
                .name   = "imx-uart",
                .of_match_table = imx_uart_dt_ids,
+               .pm     = &imx_serial_port_pm_ops,
        },
 };