summary refs log tree commit diff
path: root/drivers/tty/serial/imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r--drivers/tty/serial/imx.c1209
1 files changed, 689 insertions, 520 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a33c685af990..91f3a1a5cb7f 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -71,12 +71,12 @@
 #define UCR1_IDEN	(1<<12) /* Idle condition interrupt */
 #define UCR1_ICD_REG(x) (((x) & 3) << 10) /* idle condition detect */
 #define UCR1_RRDYEN	(1<<9)	/* Recv ready interrupt enable */
-#define UCR1_RDMAEN	(1<<8)	/* Recv ready DMA enable */
+#define UCR1_RXDMAEN	(1<<8)	/* Recv ready DMA enable */
 #define UCR1_IREN	(1<<7)	/* Infrared interface enable */
 #define UCR1_TXMPTYEN	(1<<6)	/* Transimitter empty interrupt enable */
 #define UCR1_RTSDEN	(1<<5)	/* RTS delta interrupt enable */
 #define UCR1_SNDBRK	(1<<4)	/* Send break */
-#define UCR1_TDMAEN	(1<<3)	/* Transmitter ready DMA enable */
+#define UCR1_TXDMAEN	(1<<3)	/* Transmitter ready DMA enable */
 #define IMX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, i.mx1 only */
 #define UCR1_ATDMAEN    (1<<2)  /* Aging DMA Timer Enable */
 #define UCR1_DOZE	(1<<1)	/* Doze */
@@ -204,8 +204,14 @@ struct imx_port {
 
 	struct mctrl_gpios *gpios;
 
+	/* shadow registers */
+	unsigned int ucr1;
+	unsigned int ucr2;
+	unsigned int ucr3;
+	unsigned int ucr4;
+	unsigned int ufcr;
+
 	/* DMA fields */
-	unsigned int		dma_is_inited:1;
 	unsigned int		dma_is_enabled:1;
 	unsigned int		dma_is_rxing:1;
 	unsigned int		dma_is_txing:1;
@@ -274,27 +280,81 @@ static const struct of_device_id imx_uart_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
 
-static inline unsigned uts_reg(struct imx_port *sport)
+static void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
+{
+	switch (offset) {
+	case UCR1:
+		sport->ucr1 = val;
+		break;
+	case UCR2:
+		sport->ucr2 = val;
+		break;
+	case UCR3:
+		sport->ucr3 = val;
+		break;
+	case UCR4:
+		sport->ucr4 = val;
+		break;
+	case UFCR:
+		sport->ufcr = val;
+		break;
+	default:
+		break;
+	}
+	writel(val, sport->port.membase + offset);
+}
+
+static u32 imx_uart_readl(struct imx_port *sport, u32 offset)
+{
+	switch (offset) {
+	case UCR1:
+		return sport->ucr1;
+		break;
+	case UCR2:
+		/*
+		 * UCR2_SRST is the only bit in the cached registers that might
+		 * differ from the value that was last written. As it only
+		 * clears after being set, reread conditionally.
+		 */
+		if (sport->ucr2 & UCR2_SRST)
+			sport->ucr2 = readl(sport->port.membase + offset);
+		return sport->ucr2;
+		break;
+	case UCR3:
+		return sport->ucr3;
+		break;
+	case UCR4:
+		return sport->ucr4;
+		break;
+	case UFCR:
+		return sport->ufcr;
+		break;
+	default:
+		return readl(sport->port.membase + offset);
+	}
+}
+
+static inline unsigned imx_uart_uts_reg(struct imx_port *sport)
 {
 	return sport->devdata->uts_reg;
 }
 
-static inline int is_imx1_uart(struct imx_port *sport)
+static inline int imx_uart_is_imx1(struct imx_port *sport)
 {
 	return sport->devdata->devtype == IMX1_UART;
 }
 
-static inline int is_imx21_uart(struct imx_port *sport)
+static inline int imx_uart_is_imx21(struct imx_port *sport)
 {
 	return sport->devdata->devtype == IMX21_UART;
 }
 
-static inline int is_imx53_uart(struct imx_port *sport)
+static inline int imx_uart_is_imx53(struct imx_port *sport)
 {
 	return sport->devdata->devtype == IMX53_UART;
 }
 
-static inline int is_imx6q_uart(struct imx_port *sport)
+static inline int imx_uart_is_imx6q(struct imx_port *sport)
 {
 	return sport->devdata->devtype == IMX6Q_UART;
 }
@@ -302,26 +362,26 @@ static inline int is_imx6q_uart(struct imx_port *sport)
  * Save and restore functions for UCR1, UCR2 and UCR3 registers
  */
 #if defined(CONFIG_SERIAL_IMX_CONSOLE)
-static void imx_port_ucrs_save(struct uart_port *port,
+static void imx_uart_ucrs_save(struct imx_port *sport,
 			       struct imx_port_ucrs *ucr)
 {
 	/* save control registers */
-	ucr->ucr1 = readl(port->membase + UCR1);
-	ucr->ucr2 = readl(port->membase + UCR2);
-	ucr->ucr3 = readl(port->membase + UCR3);
+	ucr->ucr1 = imx_uart_readl(sport, UCR1);
+	ucr->ucr2 = imx_uart_readl(sport, UCR2);
+	ucr->ucr3 = imx_uart_readl(sport, UCR3);
 }
 
-static void imx_port_ucrs_restore(struct uart_port *port,
+static void imx_uart_ucrs_restore(struct imx_port *sport,
 				  struct imx_port_ucrs *ucr)
 {
 	/* restore control registers */
-	writel(ucr->ucr1, port->membase + UCR1);
-	writel(ucr->ucr2, port->membase + UCR2);
-	writel(ucr->ucr3, port->membase + UCR3);
+	imx_uart_writel(sport, ucr->ucr1, UCR1);
+	imx_uart_writel(sport, ucr->ucr2, UCR2);
+	imx_uart_writel(sport, ucr->ucr3, UCR3);
 }
 #endif
 
-static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
+static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2)
 {
 	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
 
@@ -329,7 +389,7 @@ static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl);
 }
 
-static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
+static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
 {
 	*ucr2 &= ~UCR2_CTSC;
 	*ucr2 |= UCR2_CTS;
@@ -338,75 +398,91 @@ static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl);
 }
 
-static void imx_port_rts_auto(struct imx_port *sport, unsigned long *ucr2)
+static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2)
 {
 	*ucr2 |= UCR2_CTSC;
 }
 
-/*
- * interrupts disabled on entry
- */
-static void imx_stop_tx(struct uart_port *port)
+/* called with port.lock taken and irqs off */
+static void imx_uart_start_rx(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long temp;
+	unsigned int ucr1, ucr2;
+
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr2 = imx_uart_readl(sport, UCR2);
+
+	ucr2 |= UCR2_RXEN;
+
+	if (sport->dma_is_enabled) {
+		ucr1 |= UCR1_RXDMAEN | UCR1_ATDMAEN;
+	} else {
+		ucr1 |= UCR1_RRDYEN;
+		ucr2 |= UCR2_ATEN;
+	}
+
+	/* Write UCR2 first as it includes RXEN */
+	imx_uart_writel(sport, ucr2, UCR2);
+	imx_uart_writel(sport, ucr1, UCR1);
+}
+
+/* called with port.lock taken and irqs off */
+static void imx_uart_stop_tx(struct uart_port *port)
+{
+	struct imx_port *sport = (struct imx_port *)port;
+	u32 ucr1;
 
 	/*
 	 * We are maybe in the SMP context, so if the DMA TX thread is running
 	 * on other cpu, we have to wait for it to finish.
 	 */
-	if (sport->dma_is_enabled && sport->dma_is_txing)
+	if (sport->dma_is_txing)
 		return;
 
-	temp = readl(port->membase + UCR1);
-	writel(temp & ~UCR1_TXMPTYEN, port->membase + UCR1);
+	ucr1 = imx_uart_readl(sport, UCR1);
+	imx_uart_writel(sport, ucr1 & ~UCR1_TXMPTYEN, UCR1);
 
 	/* in rs485 mode disable transmitter if shifter is empty */
 	if (port->rs485.flags & SER_RS485_ENABLED &&
-	    readl(port->membase + USR2) & USR2_TXDC) {
-		temp = readl(port->membase + UCR2);
+	    imx_uart_readl(sport, USR2) & USR2_TXDC) {
+		u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4;
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-			imx_port_rts_active(sport, &temp);
+			imx_uart_rts_active(sport, &ucr2);
 		else
-			imx_port_rts_inactive(sport, &temp);
-		temp |= UCR2_RXEN;
-		writel(temp, port->membase + UCR2);
+			imx_uart_rts_inactive(sport, &ucr2);
+		imx_uart_writel(sport, ucr2, UCR2);
+
+		imx_uart_start_rx(port);
 
-		temp = readl(port->membase + UCR4);
-		temp &= ~UCR4_TCEN;
-		writel(temp, port->membase + UCR4);
+		ucr4 = imx_uart_readl(sport, UCR4);
+		ucr4 &= ~UCR4_TCEN;
+		imx_uart_writel(sport, ucr4, UCR4);
 	}
 }
 
-/*
- * interrupts disabled on entry
- */
-static void imx_stop_rx(struct uart_port *port)
+/* called with port.lock taken and irqs off */
+static void imx_uart_stop_rx(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long temp;
+	u32 ucr1, ucr2;
 
-	if (sport->dma_is_enabled && sport->dma_is_rxing) {
-		if (sport->port.suspended) {
-			dmaengine_terminate_all(sport->dma_chan_rx);
-			sport->dma_is_rxing = 0;
-		} else {
-			return;
-		}
-	}
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr2 = imx_uart_readl(sport, UCR2);
 
-	temp = readl(sport->port.membase + UCR2);
-	writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
+	if (sport->dma_is_enabled) {
+		ucr1 &= ~(UCR1_RXDMAEN | UCR1_ATDMAEN);
+	} else {
+		ucr1 &= ~UCR1_RRDYEN;
+		ucr2 &= ~UCR2_ATEN;
+	}
+	imx_uart_writel(sport, ucr1, UCR1);
 
-	/* disable the `Receiver Ready Interrrupt` */
-	temp = readl(sport->port.membase + UCR1);
-	writel(temp & ~UCR1_RRDYEN, sport->port.membase + UCR1);
+	ucr2 &= ~UCR2_RXEN;
+	imx_uart_writel(sport, ucr2, UCR2);
 }
 
-/*
- * Set the modem control timer to fire immediately.
- */
-static void imx_enable_ms(struct uart_port *port)
+/* called with port.lock taken and irqs off */
+static void imx_uart_enable_ms(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 
@@ -415,49 +491,50 @@ static void imx_enable_ms(struct uart_port *port)
 	mctrl_gpio_enable_ms(sport->gpios);
 }
 
-static void imx_dma_tx(struct imx_port *sport);
-static inline void imx_transmit_buffer(struct imx_port *sport)
+static void imx_uart_dma_tx(struct imx_port *sport);
+
+/* called with port.lock taken and irqs off */
+static inline void imx_uart_transmit_buffer(struct imx_port *sport)
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
-	unsigned long temp;
 
 	if (sport->port.x_char) {
 		/* Send next char */
-		writel(sport->port.x_char, sport->port.membase + URTX0);
+		imx_uart_writel(sport, sport->port.x_char, URTX0);
 		sport->port.icount.tx++;
 		sport->port.x_char = 0;
 		return;
 	}
 
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-		imx_stop_tx(&sport->port);
+		imx_uart_stop_tx(&sport->port);
 		return;
 	}
 
 	if (sport->dma_is_enabled) {
+		u32 ucr1;
 		/*
 		 * We've just sent a X-char Ensure the TX DMA is enabled
 		 * and the TX IRQ is disabled.
 		 **/
-		temp = readl(sport->port.membase + UCR1);
-		temp &= ~UCR1_TXMPTYEN;
+		ucr1 = imx_uart_readl(sport, UCR1);
+		ucr1 &= ~UCR1_TXMPTYEN;
 		if (sport->dma_is_txing) {
-			temp |= UCR1_TDMAEN;
-			writel(temp, sport->port.membase + UCR1);
+			ucr1 |= UCR1_TXDMAEN;
+			imx_uart_writel(sport, ucr1, UCR1);
 		} else {
-			writel(temp, sport->port.membase + UCR1);
-			imx_dma_tx(sport);
+			imx_uart_writel(sport, ucr1, UCR1);
+			imx_uart_dma_tx(sport);
 		}
-	}
 
-	if (sport->dma_is_txing)
 		return;
+	}
 
 	while (!uart_circ_empty(xmit) &&
-	       !(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) {
+	       !(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)) {
 		/* send xmit->buf[xmit->tail]
 		 * out the port here */
-		writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
+		imx_uart_writel(sport, xmit->buf[xmit->tail], URTX0);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		sport->port.icount.tx++;
 	}
@@ -466,24 +543,24 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 		uart_write_wakeup(&sport->port);
 
 	if (uart_circ_empty(xmit))
-		imx_stop_tx(&sport->port);
+		imx_uart_stop_tx(&sport->port);
 }
 
-static void dma_tx_callback(void *data)
+static void imx_uart_dma_tx_callback(void *data)
 {
 	struct imx_port *sport = data;
 	struct scatterlist *sgl = &sport->tx_sgl[0];
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned long flags;
-	unsigned long temp;
+	u32 ucr1;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
 	dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
 
-	temp = readl(sport->port.membase + UCR1);
-	temp &= ~UCR1_TDMAEN;
-	writel(temp, sport->port.membase + UCR1);
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr1 &= ~UCR1_TXDMAEN;
+	imx_uart_writel(sport, ucr1, UCR1);
 
 	/* update the stat */
 	xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
@@ -497,24 +574,34 @@ static void dma_tx_callback(void *data)
 		uart_write_wakeup(&sport->port);
 
 	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
-		imx_dma_tx(sport);
+		imx_uart_dma_tx(sport);
+	else if (sport->port.rs485.flags & SER_RS485_ENABLED) {
+		u32 ucr4 = imx_uart_readl(sport, UCR4);
+		ucr4 |= UCR4_TCEN;
+		imx_uart_writel(sport, ucr4, UCR4);
+	}
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-static void imx_dma_tx(struct imx_port *sport)
+/* called with port.lock taken and irqs off */
+static void imx_uart_dma_tx(struct imx_port *sport)
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	struct scatterlist *sgl = sport->tx_sgl;
 	struct dma_async_tx_descriptor *desc;
 	struct dma_chan	*chan = sport->dma_chan_tx;
 	struct device *dev = sport->port.dev;
-	unsigned long temp;
+	u32 ucr1, ucr4;
 	int ret;
 
 	if (sport->dma_is_txing)
 		return;
 
+	ucr4 = imx_uart_readl(sport, UCR4);
+	ucr4 &= ~UCR4_TCEN;
+	imx_uart_writel(sport, ucr4, UCR4);
+
 	sport->tx_bytes = uart_circ_chars_pending(xmit);
 
 	if (xmit->tail < xmit->head) {
@@ -541,15 +628,15 @@ static void imx_dma_tx(struct imx_port *sport)
 		dev_err(dev, "We cannot prepare for the TX slave dma!\n");
 		return;
 	}
-	desc->callback = dma_tx_callback;
+	desc->callback = imx_uart_dma_tx_callback;
 	desc->callback_param = sport;
 
 	dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
 			uart_circ_chars_pending(xmit));
 
-	temp = readl(sport->port.membase + UCR1);
-	temp |= UCR1_TDMAEN;
-	writel(temp, sport->port.membase + UCR1);
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr1 |= UCR1_TXDMAEN;
+	imx_uart_writel(sport, ucr1, UCR1);
 
 	/* fire it */
 	sport->dma_is_txing = 1;
@@ -558,99 +645,110 @@ static void imx_dma_tx(struct imx_port *sport)
 	return;
 }
 
-/*
- * interrupts disabled on entry
- */
-static void imx_start_tx(struct uart_port *port)
+/* called with port.lock taken and irqs off */
+static void imx_uart_start_tx(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long temp;
+	u32 ucr1;
+
+	if (!sport->port.x_char && uart_circ_empty(&port->state->xmit))
+		return;
 
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		temp = readl(port->membase + UCR2);
+		u32 ucr2;
+
+		ucr2 = imx_uart_readl(sport, UCR2);
 		if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
-			imx_port_rts_active(sport, &temp);
+			imx_uart_rts_active(sport, &ucr2);
 		else
-			imx_port_rts_inactive(sport, &temp);
+			imx_uart_rts_inactive(sport, &ucr2);
+		imx_uart_writel(sport, ucr2, UCR2);
+
 		if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
-			temp &= ~UCR2_RXEN;
-		writel(temp, port->membase + UCR2);
+			imx_uart_stop_rx(port);
 
-		/* enable transmitter and shifter empty irq */
-		temp = readl(port->membase + UCR4);
-		temp |= UCR4_TCEN;
-		writel(temp, port->membase + UCR4);
+		/*
+		 * Enable transmitter and shifter empty irq only if DMA is off.
+		 * In the DMA case this is done in the tx-callback.
+		 */
+		if (!sport->dma_is_enabled) {
+			u32 ucr4 = imx_uart_readl(sport, UCR4);
+			ucr4 |= UCR4_TCEN;
+			imx_uart_writel(sport, ucr4, UCR4);
+		}
 	}
 
 	if (!sport->dma_is_enabled) {
-		temp = readl(sport->port.membase + UCR1);
-		writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
+		ucr1 = imx_uart_readl(sport, UCR1);
+		imx_uart_writel(sport, ucr1 | UCR1_TXMPTYEN, UCR1);
 	}
 
 	if (sport->dma_is_enabled) {
 		if (sport->port.x_char) {
 			/* We have X-char to send, so enable TX IRQ and
 			 * disable TX DMA to let TX interrupt to send X-char */
-			temp = readl(sport->port.membase + UCR1);
-			temp &= ~UCR1_TDMAEN;
-			temp |= UCR1_TXMPTYEN;
-			writel(temp, sport->port.membase + UCR1);
+			ucr1 = imx_uart_readl(sport, UCR1);
+			ucr1 &= ~UCR1_TXDMAEN;
+			ucr1 |= UCR1_TXMPTYEN;
+			imx_uart_writel(sport, ucr1, UCR1);
 			return;
 		}
 
 		if (!uart_circ_empty(&port->state->xmit) &&
 		    !uart_tx_stopped(port))
-			imx_dma_tx(sport);
+			imx_uart_dma_tx(sport);
 		return;
 	}
 }
 
-static irqreturn_t imx_rtsint(int irq, void *dev_id)
+static irqreturn_t imx_uart_rtsint(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
-	unsigned int val;
+	u32 usr1;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	writel(USR1_RTSD, sport->port.membase + USR1);
-	val = readl(sport->port.membase + USR1) & USR1_RTSS;
-	uart_handle_cts_change(&sport->port, !!val);
+	imx_uart_writel(sport, USR1_RTSD, USR1);
+	usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS;
+	uart_handle_cts_change(&sport->port, !!usr1);
 	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t imx_txint(int irq, void *dev_id)
+static irqreturn_t imx_uart_txint(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
-	imx_transmit_buffer(sport);
+	imx_uart_transmit_buffer(sport);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t imx_rxint(int irq, void *dev_id)
+static irqreturn_t imx_uart_rxint(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
 	unsigned int rx, flg, ignored = 0;
 	struct tty_port *port = &sport->port.state->port;
-	unsigned long flags, temp;
+	unsigned long flags;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	while (readl(sport->port.membase + USR2) & USR2_RDR) {
+	while (imx_uart_readl(sport, USR2) & USR2_RDR) {
+		u32 usr2;
+
 		flg = TTY_NORMAL;
 		sport->port.icount.rx++;
 
-		rx = readl(sport->port.membase + URXD0);
+		rx = imx_uart_readl(sport, URXD0);
 
-		temp = readl(sport->port.membase + USR2);
-		if (temp & USR2_BRCD) {
-			writel(USR2_BRCD, sport->port.membase + USR2);
+		usr2 = imx_uart_readl(sport, USR2);
+		if (usr2 & USR2_BRCD) {
+			imx_uart_writel(sport, USR2_BRCD, USR2);
 			if (uart_handle_break(&sport->port))
 				continue;
 		}
@@ -703,16 +801,16 @@ out:
 	return IRQ_HANDLED;
 }
 
-static void clear_rx_errors(struct imx_port *sport);
+static void imx_uart_clear_rx_errors(struct imx_port *sport);
 
 /*
  * We have a modem side uart, so the meanings of RTS and CTS are inverted.
  */
-static unsigned int imx_get_hwmctrl(struct imx_port *sport)
+static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
 {
 	unsigned int tmp = TIOCM_DSR;
-	unsigned usr1 = readl(sport->port.membase + USR1);
-	unsigned usr2 = readl(sport->port.membase + USR2);
+	unsigned usr1 = imx_uart_readl(sport, USR1);
+	unsigned usr2 = imx_uart_readl(sport, USR2);
 
 	if (usr1 & USR1_RTSS)
 		tmp |= TIOCM_CTS;
@@ -722,7 +820,7 @@ static unsigned int imx_get_hwmctrl(struct imx_port *sport)
 		tmp |= TIOCM_CAR;
 
 	if (sport->dte_mode)
-		if (!(readl(sport->port.membase + USR2) & USR2_RIIN))
+		if (!(imx_uart_readl(sport, USR2) & USR2_RIIN))
 			tmp |= TIOCM_RI;
 
 	return tmp;
@@ -731,11 +829,11 @@ static unsigned int imx_get_hwmctrl(struct imx_port *sport)
 /*
  * Handle any change of modem status signal since we were last called.
  */
-static void imx_mctrl_check(struct imx_port *sport)
+static void imx_uart_mctrl_check(struct imx_port *sport)
 {
 	unsigned int status, changed;
 
-	status = imx_get_hwmctrl(sport);
+	status = imx_uart_get_hwmctrl(sport);
 	changed = status ^ sport->old_status;
 
 	if (changed == 0)
@@ -755,55 +853,79 @@ static void imx_mctrl_check(struct imx_port *sport)
 	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 }
 
-static irqreturn_t imx_int(int irq, void *dev_id)
+static irqreturn_t imx_uart_int(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
-	unsigned int sts;
-	unsigned int sts2;
+	unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4;
 	irqreturn_t ret = IRQ_NONE;
 
-	sts = readl(sport->port.membase + USR1);
-	sts2 = readl(sport->port.membase + USR2);
+	usr1 = imx_uart_readl(sport, USR1);
+	usr2 = imx_uart_readl(sport, USR2);
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr2 = imx_uart_readl(sport, UCR2);
+	ucr3 = imx_uart_readl(sport, UCR3);
+	ucr4 = imx_uart_readl(sport, UCR4);
 
-	if (!sport->dma_is_enabled && (sts & (USR1_RRDY | USR1_AGTIM))) {
-		imx_rxint(irq, dev_id);
+	/*
+	 * Even if a condition is true that can trigger an irq only handle it if
+	 * the respective irq source is enabled. This prevents some undesired
+	 * actions, for example if a character that sits in the RX FIFO and that
+	 * should be fetched via DMA is tried to be fetched using PIO. Or the
+	 * receiver is currently off and so reading from URXD0 results in an
+	 * exception. So just mask the (raw) status bits for disabled irqs.
+	 */
+	if ((ucr1 & UCR1_RRDYEN) == 0)
+		usr1 &= ~USR1_RRDY;
+	if ((ucr2 & UCR2_ATEN) == 0)
+		usr1 &= ~USR1_AGTIM;
+	if ((ucr1 & UCR1_TXMPTYEN) == 0)
+		usr1 &= ~USR1_TRDY;
+	if ((ucr4 & UCR4_TCEN) == 0)
+		usr2 &= ~USR2_TXDC;
+	if ((ucr3 & UCR3_DTRDEN) == 0)
+		usr1 &= ~USR1_DTRD;
+	if ((ucr1 & UCR1_RTSDEN) == 0)
+		usr1 &= ~USR1_RTSD;
+	if ((ucr3 & UCR3_AWAKEN) == 0)
+		usr1 &= ~USR1_AWAKE;
+	if ((ucr4 & UCR4_OREN) == 0)
+		usr2 &= ~USR2_ORE;
+
+	if (usr1 & (USR1_RRDY | USR1_AGTIM)) {
+		imx_uart_rxint(irq, dev_id);
 		ret = IRQ_HANDLED;
 	}
 
-	if ((sts & USR1_TRDY &&
-	     readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
-	    (sts2 & USR2_TXDC &&
-	     readl(sport->port.membase + UCR4) & UCR4_TCEN)) {
-		imx_txint(irq, dev_id);
+	if ((usr1 & USR1_TRDY) || (usr2 & USR2_TXDC)) {
+		imx_uart_txint(irq, dev_id);
 		ret = IRQ_HANDLED;
 	}
 
-	if (sts & USR1_DTRD) {
+	if (usr1 & USR1_DTRD) {
 		unsigned long flags;
 
-		if (sts & USR1_DTRD)
-			writel(USR1_DTRD, sport->port.membase + USR1);
+		imx_uart_writel(sport, USR1_DTRD, USR1);
 
 		spin_lock_irqsave(&sport->port.lock, flags);
-		imx_mctrl_check(sport);
+		imx_uart_mctrl_check(sport);
 		spin_unlock_irqrestore(&sport->port.lock, flags);
 
 		ret = IRQ_HANDLED;
 	}
 
-	if (sts & USR1_RTSD) {
-		imx_rtsint(irq, dev_id);
+	if (usr1 & USR1_RTSD) {
+		imx_uart_rtsint(irq, dev_id);
 		ret = IRQ_HANDLED;
 	}
 
-	if (sts & USR1_AWAKE) {
-		writel(USR1_AWAKE, sport->port.membase + USR1);
+	if (usr1 & USR1_AWAKE) {
+		imx_uart_writel(sport, USR1_AWAKE, USR1);
 		ret = IRQ_HANDLED;
 	}
 
-	if (sts2 & USR2_ORE) {
+	if (usr2 & USR2_ORE) {
 		sport->port.icount.overrun++;
-		writel(USR2_ORE, sport->port.membase + USR2);
+		imx_uart_writel(sport, USR2_ORE, USR2);
 		ret = IRQ_HANDLED;
 	}
 
@@ -813,52 +935,56 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 /*
  * Return TIOCSER_TEMT when transmitter is not busy.
  */
-static unsigned int imx_tx_empty(struct uart_port *port)
+static unsigned int imx_uart_tx_empty(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned int ret;
 
-	ret = (readl(sport->port.membase + USR2) & USR2_TXDC) ?  TIOCSER_TEMT : 0;
+	ret = (imx_uart_readl(sport, USR2) & USR2_TXDC) ?  TIOCSER_TEMT : 0;
 
 	/* If the TX DMA is working, return 0. */
-	if (sport->dma_is_enabled && sport->dma_is_txing)
+	if (sport->dma_is_txing)
 		ret = 0;
 
 	return ret;
 }
 
-static unsigned int imx_get_mctrl(struct uart_port *port)
+/* called with port.lock taken and irqs off */
+static unsigned int imx_uart_get_mctrl(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned int ret = imx_get_hwmctrl(sport);
+	unsigned int ret = imx_uart_get_hwmctrl(sport);
 
 	mctrl_gpio_get(sport->gpios, &ret);
 
 	return ret;
 }
 
-static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+/* called with port.lock taken and irqs off */
+static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long temp;
+	u32 ucr3, uts;
 
 	if (!(port->rs485.flags & SER_RS485_ENABLED)) {
-		temp = readl(sport->port.membase + UCR2);
-		temp &= ~(UCR2_CTS | UCR2_CTSC);
+		u32 ucr2;
+
+		ucr2 = imx_uart_readl(sport, UCR2);
+		ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
 		if (mctrl & TIOCM_RTS)
-			temp |= UCR2_CTS | UCR2_CTSC;
-		writel(temp, sport->port.membase + UCR2);
+			ucr2 |= UCR2_CTS | UCR2_CTSC;
+		imx_uart_writel(sport, ucr2, UCR2);
 	}
 
-	temp = readl(sport->port.membase + UCR3) & ~UCR3_DSR;
+	ucr3 = imx_uart_readl(sport, UCR3) & ~UCR3_DSR;
 	if (!(mctrl & TIOCM_DTR))
-		temp |= UCR3_DSR;
-	writel(temp, sport->port.membase + UCR3);
+		ucr3 |= UCR3_DSR;
+	imx_uart_writel(sport, ucr3, UCR3);
 
-	temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
+	uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)) & ~UTS_LOOP;
 	if (mctrl & TIOCM_LOOP)
-		temp |= UTS_LOOP;
-	writel(temp, sport->port.membase + uts_reg(sport));
+		uts |= UTS_LOOP;
+	imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
 
 	mctrl_gpio_set(sport->gpios, mctrl);
 }
@@ -866,19 +992,20 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 /*
  * Interrupts always disabled.
  */
-static void imx_break_ctl(struct uart_port *port, int break_state)
+static void imx_uart_break_ctl(struct uart_port *port, int break_state)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long flags, temp;
+	unsigned long flags;
+	u32 ucr1;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK;
+	ucr1 = imx_uart_readl(sport, UCR1) & ~UCR1_SNDBRK;
 
 	if (break_state != 0)
-		temp |= UCR1_SNDBRK;
+		ucr1 |= UCR1_SNDBRK;
 
-	writel(temp, sport->port.membase + UCR1);
+	imx_uart_writel(sport, ucr1, UCR1);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
@@ -887,14 +1014,14 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
  * This is our per-port timeout handler, for checking the
  * modem status signals.
  */
-static void imx_timeout(struct timer_list *t)
+static void imx_uart_timeout(struct timer_list *t)
 {
 	struct imx_port *sport = from_timer(sport, t, timer);
 	unsigned long flags;
 
 	if (sport->port.state) {
 		spin_lock_irqsave(&sport->port.lock, flags);
-		imx_mctrl_check(sport);
+		imx_uart_mctrl_check(sport);
 		spin_unlock_irqrestore(&sport->port.lock, flags);
 
 		mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
@@ -911,7 +1038,7 @@ static void imx_timeout(struct timer_list *t)
  * 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)
+static void imx_uart_dma_rx_callback(void *data)
 {
 	struct imx_port *sport = data;
 	struct dma_chan	*chan = sport->dma_chan_rx;
@@ -927,8 +1054,7 @@ static void dma_rx_callback(void *data)
 	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 
 	if (status == DMA_ERROR) {
-		dev_err(sport->port.dev, "DMA transaction error.\n");
-		clear_rx_errors(sport);
+		imx_uart_clear_rx_errors(sport);
 		return;
 	}
 
@@ -988,7 +1114,7 @@ static void dma_rx_callback(void *data)
 /* RX DMA buffer periods */
 #define RX_DMA_PERIODS 4
 
-static int start_rx_dma(struct imx_port *sport)
+static int imx_uart_start_rx_dma(struct imx_port *sport)
 {
 	struct scatterlist *sgl = &sport->rx_sgl;
 	struct dma_chan	*chan = sport->dma_chan_rx;
@@ -1016,7 +1142,7 @@ static int start_rx_dma(struct imx_port *sport)
 		dev_err(dev, "We cannot prepare for the RX slave dma!\n");
 		return -EINVAL;
 	}
-	desc->callback = dma_rx_callback;
+	desc->callback = imx_uart_dma_rx_callback;
 	desc->callback_param = sport;
 
 	dev_dbg(dev, "RX: prepare for the DMA.\n");
@@ -1026,27 +1152,35 @@ static int start_rx_dma(struct imx_port *sport)
 	return 0;
 }
 
-static void clear_rx_errors(struct imx_port *sport)
+static void imx_uart_clear_rx_errors(struct imx_port *sport)
 {
-	unsigned int status_usr1, status_usr2;
+	struct tty_port *port = &sport->port.state->port;
+	u32 usr1, usr2;
 
-	status_usr1 = readl(sport->port.membase + USR1);
-	status_usr2 = readl(sport->port.membase + USR2);
+	usr1 = imx_uart_readl(sport, USR1);
+	usr2 = imx_uart_readl(sport, USR2);
 
-	if (status_usr2 & USR2_BRCD) {
+	if (usr2 & USR2_BRCD) {
 		sport->port.icount.brk++;
-		writel(USR2_BRCD, sport->port.membase + USR2);
-	} else if (status_usr1 & USR1_FRAMERR) {
-		sport->port.icount.frame++;
-		writel(USR1_FRAMERR, sport->port.membase + USR1);
-	} else if (status_usr1 & USR1_PARITYERR) {
-		sport->port.icount.parity++;
-		writel(USR1_PARITYERR, sport->port.membase + USR1);
+		imx_uart_writel(sport, USR2_BRCD, USR2);
+		uart_handle_break(&sport->port);
+		if (tty_insert_flip_char(port, 0, TTY_BREAK) == 0)
+			sport->port.icount.buf_overrun++;
+		tty_flip_buffer_push(port);
+	} else {
+		dev_err(sport->port.dev, "DMA transaction error.\n");
+		if (usr1 & USR1_FRAMERR) {
+			sport->port.icount.frame++;
+			imx_uart_writel(sport, USR1_FRAMERR, USR1);
+		} else if (usr1 & USR1_PARITYERR) {
+			sport->port.icount.parity++;
+			imx_uart_writel(sport, USR1_PARITYERR, USR1);
+		}
 	}
 
-	if (status_usr2 & USR2_ORE) {
+	if (usr2 & USR2_ORE) {
 		sport->port.icount.overrun++;
-		writel(USR2_ORE, sport->port.membase + USR2);
+		imx_uart_writel(sport, USR2_ORE, USR2);
 	}
 
 }
@@ -1056,15 +1190,15 @@ static void clear_rx_errors(struct imx_port *sport)
 #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)
+static void imx_uart_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 = imx_uart_readl(sport, UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
 	val |= txwl << UFCR_TXTL_SHF | rxwl;
-	writel(val, sport->port.membase + UFCR);
+	imx_uart_writel(sport, val, UFCR);
 }
 
 static void imx_uart_dma_exit(struct imx_port *sport)
@@ -1083,8 +1217,6 @@ static void imx_uart_dma_exit(struct imx_port *sport)
 		dma_release_channel(sport->dma_chan_tx);
 		sport->dma_chan_tx = NULL;
 	}
-
-	sport->dma_is_inited = 0;
 }
 
 static int imx_uart_dma_init(struct imx_port *sport)
@@ -1137,43 +1269,41 @@ static int imx_uart_dma_init(struct imx_port *sport)
 		goto err;
 	}
 
-	sport->dma_is_inited = 1;
-
 	return 0;
 err:
 	imx_uart_dma_exit(sport);
 	return ret;
 }
 
-static void imx_enable_dma(struct imx_port *sport)
+static void imx_uart_enable_dma(struct imx_port *sport)
 {
-	unsigned long temp;
+	u32 ucr1;
 
-	/* set UCR1 */
-	temp = readl(sport->port.membase + UCR1);
-	temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
-	writel(temp, sport->port.membase + UCR1);
+	imx_uart_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
 
-	imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
+	/* set UCR1 */
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr1 |= UCR1_RXDMAEN | UCR1_TXDMAEN | UCR1_ATDMAEN;
+	imx_uart_writel(sport, ucr1, UCR1);
 
 	sport->dma_is_enabled = 1;
 }
 
-static void imx_disable_dma(struct imx_port *sport)
+static void imx_uart_disable_dma(struct imx_port *sport)
 {
-	unsigned long temp;
+	u32 ucr1, ucr2;
 
 	/* clear UCR1 */
-	temp = readl(sport->port.membase + UCR1);
-	temp &= ~(UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN);
-	writel(temp, sport->port.membase + UCR1);
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr1 &= ~(UCR1_RXDMAEN | UCR1_TXDMAEN | UCR1_ATDMAEN);
+	imx_uart_writel(sport, ucr1, UCR1);
 
 	/* clear UCR2 */
-	temp = readl(sport->port.membase + UCR2);
-	temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
-	writel(temp, sport->port.membase + UCR2);
+	ucr2 = imx_uart_readl(sport, UCR2);
+	ucr2 &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
+	imx_uart_writel(sport, ucr2, UCR2);
 
-	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+	imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	sport->dma_is_enabled = 0;
 }
@@ -1181,11 +1311,13 @@ static void imx_disable_dma(struct imx_port *sport)
 /* half the RX buffer size */
 #define CTSTL 16
 
-static int imx_startup(struct uart_port *port)
+static int imx_uart_startup(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	int retval, i;
-	unsigned long flags, temp;
+	unsigned long flags;
+	int dma_is_inited = 0;
+	u32 ucr1, ucr2, ucr4;
 
 	retval = clk_prepare_enable(sport->clk_per);
 	if (retval)
@@ -1196,104 +1328,106 @@ static int imx_startup(struct uart_port *port)
 		return retval;
 	}
 
-	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+	imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	/* disable the DREN bit (Data Ready interrupt enable) before
 	 * requesting IRQs
 	 */
-	temp = readl(sport->port.membase + UCR4);
+	ucr4 = imx_uart_readl(sport, UCR4);
 
 	/* set the trigger level for CTS */
-	temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
-	temp |= CTSTL << UCR4_CTSTL_SHF;
+	ucr4 &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
+	ucr4 |= CTSTL << UCR4_CTSTL_SHF;
 
-	writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
+	imx_uart_writel(sport, ucr4 & ~UCR4_DREN, UCR4);
 
 	/* Can we enable the DMA support? */
-	if (!uart_console(port) && !sport->dma_is_inited)
-		imx_uart_dma_init(sport);
+	if (!uart_console(port) && imx_uart_dma_init(sport) == 0)
+		dma_is_inited = 1;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 	/* Reset fifo's and state machines */
 	i = 100;
 
-	temp = readl(sport->port.membase + UCR2);
-	temp &= ~UCR2_SRST;
-	writel(temp, sport->port.membase + UCR2);
+	ucr2 = imx_uart_readl(sport, UCR2);
+	ucr2 &= ~UCR2_SRST;
+	imx_uart_writel(sport, ucr2, UCR2);
 
-	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
+	while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0))
 		udelay(1);
 
 	/*
 	 * Finally, clear and enable interrupts
 	 */
-	writel(USR1_RTSD | USR1_DTRD, sport->port.membase + USR1);
-	writel(USR2_ORE, sport->port.membase + USR2);
-
-	if (sport->dma_is_inited && !sport->dma_is_enabled)
-		imx_enable_dma(sport);
+	imx_uart_writel(sport, USR1_RTSD | USR1_DTRD, USR1);
+	imx_uart_writel(sport, USR2_ORE, USR2);
 
-	temp = readl(sport->port.membase + UCR1) & ~UCR1_RRDYEN;
-	if (!sport->dma_is_enabled)
-		temp |= UCR1_RRDYEN;
-	temp |= UCR1_UARTEN;
+	ucr1 = imx_uart_readl(sport, UCR1) & ~UCR1_RRDYEN;
+	ucr1 |= UCR1_UARTEN;
 	if (sport->have_rtscts)
-			temp |= UCR1_RTSDEN;
+		ucr1 |= UCR1_RTSDEN;
 
-	writel(temp, sport->port.membase + UCR1);
+	imx_uart_writel(sport, ucr1, UCR1);
 
-	temp = readl(sport->port.membase + UCR4) & ~UCR4_OREN;
+	ucr4 = imx_uart_readl(sport, UCR4) & ~UCR4_OREN;
 	if (!sport->dma_is_enabled)
-		temp |= UCR4_OREN;
-	writel(temp, sport->port.membase + UCR4);
+		ucr4 |= UCR4_OREN;
+	imx_uart_writel(sport, ucr4, UCR4);
 
-	temp = readl(sport->port.membase + UCR2) & ~UCR2_ATEN;
-	temp |= (UCR2_RXEN | UCR2_TXEN);
+	ucr2 = imx_uart_readl(sport, UCR2) & ~UCR2_ATEN;
+	ucr2 |= (UCR2_RXEN | UCR2_TXEN);
 	if (!sport->have_rtscts)
-		temp |= UCR2_IRTS;
+		ucr2 |= UCR2_IRTS;
 	/*
 	 * make sure the edge sensitive RTS-irq is disabled,
 	 * we're using RTSD instead.
 	 */
-	if (!is_imx1_uart(sport))
-		temp &= ~UCR2_RTSEN;
-	writel(temp, sport->port.membase + UCR2);
+	if (!imx_uart_is_imx1(sport))
+		ucr2 &= ~UCR2_RTSEN;
+	imx_uart_writel(sport, ucr2, UCR2);
+
+	if (!imx_uart_is_imx1(sport)) {
+		u32 ucr3;
 
-	if (!is_imx1_uart(sport)) {
-		temp = readl(sport->port.membase + UCR3);
+		ucr3 = imx_uart_readl(sport, UCR3);
 
-		temp |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
+		ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
 
 		if (sport->dte_mode)
 			/* disable broken interrupts */
-			temp &= ~(UCR3_RI | UCR3_DCD);
+			ucr3 &= ~(UCR3_RI | UCR3_DCD);
 
-		writel(temp, sport->port.membase + UCR3);
+		imx_uart_writel(sport, ucr3, UCR3);
 	}
 
 	/*
 	 * Enable modem status interrupts
 	 */
-	imx_enable_ms(&sport->port);
+	imx_uart_enable_ms(&sport->port);
 
-	/*
-	 * Start RX DMA immediately instead of waiting for RX FIFO interrupts.
-	 * In our iMX53 the average delay for the first reception dropped from
-	 * approximately 35000 microseconds to 1000 microseconds.
-	 */
-	if (sport->dma_is_enabled)
-		start_rx_dma(sport);
+	if (dma_is_inited) {
+		imx_uart_enable_dma(sport);
+		imx_uart_start_rx_dma(sport);
+	} else {
+		ucr1 = imx_uart_readl(sport, UCR1);
+		ucr1 |= UCR1_RRDYEN;
+		imx_uart_writel(sport, ucr1, UCR1);
+
+		ucr2 = imx_uart_readl(sport, UCR2);
+		ucr2 |= UCR2_ATEN;
+		imx_uart_writel(sport, ucr2, UCR2);
+	}
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	return 0;
 }
 
-static void imx_shutdown(struct uart_port *port)
+static void imx_uart_shutdown(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long temp;
 	unsigned long flags;
+	u32 ucr1, ucr2;
 
 	if (sport->dma_is_enabled) {
 		sport->dma_is_rxing = 0;
@@ -1302,9 +1436,9 @@ static void imx_shutdown(struct uart_port *port)
 		dmaengine_terminate_sync(sport->dma_chan_rx);
 
 		spin_lock_irqsave(&sport->port.lock, flags);
-		imx_stop_tx(port);
-		imx_stop_rx(port);
-		imx_disable_dma(sport);
+		imx_uart_stop_tx(port);
+		imx_uart_stop_rx(port);
+		imx_uart_disable_dma(sport);
 		spin_unlock_irqrestore(&sport->port.lock, flags);
 		imx_uart_dma_exit(sport);
 	}
@@ -1312,9 +1446,9 @@ static void imx_shutdown(struct uart_port *port)
 	mctrl_gpio_disable_ms(sport->gpios);
 
 	spin_lock_irqsave(&sport->port.lock, flags);
-	temp = readl(sport->port.membase + UCR2);
-	temp &= ~(UCR2_TXEN);
-	writel(temp, sport->port.membase + UCR2);
+	ucr2 = imx_uart_readl(sport, UCR2);
+	ucr2 &= ~(UCR2_TXEN | UCR2_ATEN);
+	imx_uart_writel(sport, ucr2, UCR2);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	/*
@@ -1327,21 +1461,22 @@ static void imx_shutdown(struct uart_port *port)
 	 */
 
 	spin_lock_irqsave(&sport->port.lock, flags);
-	temp = readl(sport->port.membase + UCR1);
-	temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN);
 
-	writel(temp, sport->port.membase + UCR1);
+	imx_uart_writel(sport, ucr1, UCR1);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	clk_disable_unprepare(sport->clk_per);
 	clk_disable_unprepare(sport->clk_ipg);
 }
 
-static void imx_flush_buffer(struct uart_port *port)
+/* called with port.lock taken and irqs off */
+static void imx_uart_flush_buffer(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	struct scatterlist *sgl = &sport->tx_sgl[0];
-	unsigned long temp;
+	u32 ucr2;
 	int i = 100, ubir, ubmr, uts;
 
 	if (!sport->dma_chan_tx)
@@ -1350,11 +1485,13 @@ static void imx_flush_buffer(struct uart_port *port)
 	sport->tx_bytes = 0;
 	dmaengine_terminate_all(sport->dma_chan_tx);
 	if (sport->dma_is_txing) {
+		u32 ucr1;
+
 		dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents,
 			     DMA_TO_DEVICE);
-		temp = readl(sport->port.membase + UCR1);
-		temp &= ~UCR1_TDMAEN;
-		writel(temp, sport->port.membase + UCR1);
+		ucr1 = imx_uart_readl(sport, UCR1);
+		ucr1 &= ~UCR1_TXDMAEN;
+		imx_uart_writel(sport, ucr1, UCR1);
 		sport->dma_is_txing = 0;
 	}
 
@@ -1369,33 +1506,33 @@ static void imx_flush_buffer(struct uart_port *port)
 	 * UTXD. UBRC is read only, so only save/restore the other three
 	 * registers.
 	 */
-	ubir = readl(sport->port.membase + UBIR);
-	ubmr = readl(sport->port.membase + UBMR);
-	uts = readl(sport->port.membase + IMX21_UTS);
+	ubir = imx_uart_readl(sport, UBIR);
+	ubmr = imx_uart_readl(sport, UBMR);
+	uts = imx_uart_readl(sport, IMX21_UTS);
 
-	temp = readl(sport->port.membase + UCR2);
-	temp &= ~UCR2_SRST;
-	writel(temp, sport->port.membase + UCR2);
+	ucr2 = imx_uart_readl(sport, UCR2);
+	ucr2 &= ~UCR2_SRST;
+	imx_uart_writel(sport, ucr2, UCR2);
 
-	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
+	while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0))
 		udelay(1);
 
 	/* Restore the registers */
-	writel(ubir, sport->port.membase + UBIR);
-	writel(ubmr, sport->port.membase + UBMR);
-	writel(uts, sport->port.membase + IMX21_UTS);
+	imx_uart_writel(sport, ubir, UBIR);
+	imx_uart_writel(sport, ubmr, UBMR);
+	imx_uart_writel(sport, uts, IMX21_UTS);
 }
 
 static void
-imx_set_termios(struct uart_port *port, struct ktermios *termios,
-		   struct ktermios *old)
+imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
+		     struct ktermios *old)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long flags;
-	unsigned long ucr2, old_ucr1, old_ucr2;
+	u32 ucr2, old_ucr1, old_ucr2, ufcr;
 	unsigned int baud, quot;
 	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
-	unsigned long div, ufcr;
+	unsigned long div;
 	unsigned long num, denom;
 	uint64_t tdiv64;
 
@@ -1426,11 +1563,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 				 */
 				if (port->rs485.flags &
 				    SER_RS485_RTS_AFTER_SEND)
-					imx_port_rts_active(sport, &ucr2);
+					imx_uart_rts_active(sport, &ucr2);
 				else
-					imx_port_rts_inactive(sport, &ucr2);
+					imx_uart_rts_inactive(sport, &ucr2);
 			} else {
-				imx_port_rts_auto(sport, &ucr2);
+				imx_uart_rts_auto(sport, &ucr2);
 			}
 		} else {
 			termios->c_cflag &= ~CRTSCTS;
@@ -1438,9 +1575,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	} else if (port->rs485.flags & SER_RS485_ENABLED) {
 		/* disable transmitter */
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-			imx_port_rts_active(sport, &ucr2);
+			imx_uart_rts_active(sport, &ucr2);
 		else
-			imx_port_rts_inactive(sport, &ucr2);
+			imx_uart_rts_inactive(sport, &ucr2);
 	}
 
 
@@ -1495,17 +1632,18 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	/*
 	 * disable interrupts and drain transmitter
 	 */
-	old_ucr1 = readl(sport->port.membase + UCR1);
-	writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
-			sport->port.membase + UCR1);
-
-	while (!(readl(sport->port.membase + USR2) & USR2_TXDC))
+	old_ucr1 = imx_uart_readl(sport, UCR1);
+	imx_uart_writel(sport,
+			old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
+			UCR1);
+	old_ucr2 = imx_uart_readl(sport, UCR2);
+	imx_uart_writel(sport, old_ucr2 & ~UCR2_ATEN, UCR2);
+
+	while (!(imx_uart_readl(sport, USR2) & USR2_TXDC))
 		barrier();
 
 	/* then, disable everything */
-	old_ucr2 = readl(sport->port.membase + UCR2);
-	writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
-			sport->port.membase + UCR2);
+	imx_uart_writel(sport, old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN | UCR2_ATEN), UCR2);
 	old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
 
 	/* custom-baudrate handling */
@@ -1531,29 +1669,29 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	num -= 1;
 	denom -= 1;
 
-	ufcr = readl(sport->port.membase + UFCR);
+	ufcr = imx_uart_readl(sport, UFCR);
 	ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div);
-	writel(ufcr, sport->port.membase + UFCR);
+	imx_uart_writel(sport, ufcr, UFCR);
 
-	writel(num, sport->port.membase + UBIR);
-	writel(denom, sport->port.membase + UBMR);
+	imx_uart_writel(sport, num, UBIR);
+	imx_uart_writel(sport, denom, UBMR);
 
-	if (!is_imx1_uart(sport))
-		writel(sport->port.uartclk / div / 1000,
-				sport->port.membase + IMX21_ONEMS);
+	if (!imx_uart_is_imx1(sport))
+		imx_uart_writel(sport, sport->port.uartclk / div / 1000,
+				IMX21_ONEMS);
 
-	writel(old_ucr1, sport->port.membase + UCR1);
+	imx_uart_writel(sport, old_ucr1, UCR1);
 
 	/* set the parity, stop bits and data size */
-	writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
+	imx_uart_writel(sport, ucr2 | old_ucr2, UCR2);
 
 	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
-		imx_enable_ms(&sport->port);
+		imx_uart_enable_ms(&sport->port);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-static const char *imx_type(struct uart_port *port)
+static const char *imx_uart_type(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 
@@ -1563,7 +1701,7 @@ static const char *imx_type(struct uart_port *port)
 /*
  * Configure/autoconfigure the port.
  */
-static void imx_config_port(struct uart_port *port, int flags)
+static void imx_uart_config_port(struct uart_port *port, int flags)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 
@@ -1577,7 +1715,7 @@ static void imx_config_port(struct uart_port *port, int flags)
  * even then only between PORT_IMX and PORT_UNKNOWN
  */
 static int
-imx_verify_port(struct uart_port *port, struct serial_struct *ser)
+imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	int ret = 0;
@@ -1601,11 +1739,11 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
 
 #if defined(CONFIG_CONSOLE_POLL)
 
-static int imx_poll_init(struct uart_port *port)
+static int imx_uart_poll_init(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long flags;
-	unsigned long temp;
+	u32 ucr1, ucr2;
 	int retval;
 
 	retval = clk_prepare_enable(sport->clk_ipg);
@@ -1615,58 +1753,76 @@ static int imx_poll_init(struct uart_port *port)
 	if (retval)
 		clk_disable_unprepare(sport->clk_ipg);
 
-	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+	imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	temp = readl(sport->port.membase + UCR1);
-	if (is_imx1_uart(sport))
-		temp |= IMX1_UCR1_UARTCLKEN;
-	temp |= UCR1_UARTEN | UCR1_RRDYEN;
-	temp &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN);
-	writel(temp, sport->port.membase + UCR1);
+	/*
+	 * Be careful about the order of enabling bits here. First enable the
+	 * receiver (UARTEN + RXEN) and only then the corresponding irqs.
+	 * This prevents that a character that already sits in the RX fifo is
+	 * triggering an irq but the try to fetch it from there results in an
+	 * exception because UARTEN or RXEN is still off.
+	 */
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr2 = imx_uart_readl(sport, UCR2);
 
-	temp = readl(sport->port.membase + UCR2);
-	temp |= UCR2_RXEN;
-	writel(temp, sport->port.membase + UCR2);
+	if (imx_uart_is_imx1(sport))
+		ucr1 |= IMX1_UCR1_UARTCLKEN;
+
+	ucr1 |= UCR1_UARTEN;
+	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN | UCR1_RRDYEN);
+
+	ucr2 |= UCR2_RXEN;
+	ucr2 &= ~UCR2_ATEN;
+
+	imx_uart_writel(sport, ucr1, UCR1);
+	imx_uart_writel(sport, ucr2, UCR2);
+
+	/* now enable irqs */
+	imx_uart_writel(sport, ucr1 | UCR1_RRDYEN, UCR1);
+	imx_uart_writel(sport, ucr2 | UCR2_ATEN, UCR2);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	return 0;
 }
 
-static int imx_poll_get_char(struct uart_port *port)
+static int imx_uart_poll_get_char(struct uart_port *port)
 {
-	if (!(readl_relaxed(port->membase + USR2) & USR2_RDR))
+	struct imx_port *sport = (struct imx_port *)port;
+	if (!(imx_uart_readl(sport, USR2) & USR2_RDR))
 		return NO_POLL_CHAR;
 
-	return readl_relaxed(port->membase + URXD0) & URXD_RX_DATA;
+	return imx_uart_readl(sport, URXD0) & URXD_RX_DATA;
 }
 
-static void imx_poll_put_char(struct uart_port *port, unsigned char c)
+static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
 {
+	struct imx_port *sport = (struct imx_port *)port;
 	unsigned int status;
 
 	/* drain */
 	do {
-		status = readl_relaxed(port->membase + USR1);
+		status = imx_uart_readl(sport, USR1);
 	} while (~status & USR1_TRDY);
 
 	/* write */
-	writel_relaxed(c, port->membase + URTX0);
+	imx_uart_writel(sport, c, URTX0);
 
 	/* flush */
 	do {
-		status = readl_relaxed(port->membase + USR2);
+		status = imx_uart_readl(sport, USR2);
 	} while (~status & USR2_TXDC);
 }
 #endif
 
-static int imx_rs485_config(struct uart_port *port,
-			    struct serial_rs485 *rs485conf)
+/* called with port.lock taken and irqs off or from .probe without locking */
+static int imx_uart_rs485_config(struct uart_port *port,
+				 struct serial_rs485 *rs485conf)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	unsigned long temp;
+	u32 ucr2;
 
 	/* unimplemented */
 	rs485conf->delay_rts_before_send = 0;
@@ -1678,70 +1834,67 @@ static int imx_rs485_config(struct uart_port *port,
 
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 		/* disable transmitter */
-		temp = readl(sport->port.membase + UCR2);
+		ucr2 = imx_uart_readl(sport, UCR2);
 		if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
-			imx_port_rts_active(sport, &temp);
+			imx_uart_rts_active(sport, &ucr2);
 		else
-			imx_port_rts_inactive(sport, &temp);
-		writel(temp, sport->port.membase + UCR2);
+			imx_uart_rts_inactive(sport, &ucr2);
+		imx_uart_writel(sport, ucr2, UCR2);
 	}
 
 	/* Make sure Rx is enabled in case Tx is active with Rx disabled */
 	if (!(rs485conf->flags & SER_RS485_ENABLED) ||
-	    rs485conf->flags & SER_RS485_RX_DURING_TX) {
-		temp = readl(sport->port.membase + UCR2);
-		temp |= UCR2_RXEN;
-		writel(temp, sport->port.membase + UCR2);
-	}
+	    rs485conf->flags & SER_RS485_RX_DURING_TX)
+		imx_uart_start_rx(port);
 
 	port->rs485 = *rs485conf;
 
 	return 0;
 }
 
-static const struct uart_ops imx_pops = {
-	.tx_empty	= imx_tx_empty,
-	.set_mctrl	= imx_set_mctrl,
-	.get_mctrl	= imx_get_mctrl,
-	.stop_tx	= imx_stop_tx,
-	.start_tx	= imx_start_tx,
-	.stop_rx	= imx_stop_rx,
-	.enable_ms	= imx_enable_ms,
-	.break_ctl	= imx_break_ctl,
-	.startup	= imx_startup,
-	.shutdown	= imx_shutdown,
-	.flush_buffer	= imx_flush_buffer,
-	.set_termios	= imx_set_termios,
-	.type		= imx_type,
-	.config_port	= imx_config_port,
-	.verify_port	= imx_verify_port,
+static const struct uart_ops imx_uart_pops = {
+	.tx_empty	= imx_uart_tx_empty,
+	.set_mctrl	= imx_uart_set_mctrl,
+	.get_mctrl	= imx_uart_get_mctrl,
+	.stop_tx	= imx_uart_stop_tx,
+	.start_tx	= imx_uart_start_tx,
+	.stop_rx	= imx_uart_stop_rx,
+	.enable_ms	= imx_uart_enable_ms,
+	.break_ctl	= imx_uart_break_ctl,
+	.startup	= imx_uart_startup,
+	.shutdown	= imx_uart_shutdown,
+	.flush_buffer	= imx_uart_flush_buffer,
+	.set_termios	= imx_uart_set_termios,
+	.type		= imx_uart_type,
+	.config_port	= imx_uart_config_port,
+	.verify_port	= imx_uart_verify_port,
 #if defined(CONFIG_CONSOLE_POLL)
-	.poll_init      = imx_poll_init,
-	.poll_get_char  = imx_poll_get_char,
-	.poll_put_char  = imx_poll_put_char,
+	.poll_init      = imx_uart_poll_init,
+	.poll_get_char  = imx_uart_poll_get_char,
+	.poll_put_char  = imx_uart_poll_put_char,
 #endif
 };
 
-static struct imx_port *imx_ports[UART_NR];
+static struct imx_port *imx_uart_ports[UART_NR];
 
 #ifdef CONFIG_SERIAL_IMX_CONSOLE
-static void imx_console_putchar(struct uart_port *port, int ch)
+static void imx_uart_console_putchar(struct uart_port *port, int ch)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 
-	while (readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)
+	while (imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)
 		barrier();
 
-	writel(ch, sport->port.membase + URTX0);
+	imx_uart_writel(sport, ch, URTX0);
 }
 
 /*
  * Interrupts are disabled on entering
  */
 static void
-imx_console_write(struct console *co, const char *s, unsigned int count)
+imx_uart_console_write(struct console *co, const char *s, unsigned int count)
 {
-	struct imx_port *sport = imx_ports[co->index];
+	struct imx_port *sport = imx_uart_ports[co->index];
 	struct imx_port_ucrs old_ucr;
 	unsigned int ucr1;
 	unsigned long flags = 0;
@@ -1767,27 +1920,27 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 	/*
 	 *	First, save UCR1/2/3 and then disable interrupts
 	 */
-	imx_port_ucrs_save(&sport->port, &old_ucr);
+	imx_uart_ucrs_save(sport, &old_ucr);
 	ucr1 = old_ucr.ucr1;
 
-	if (is_imx1_uart(sport))
+	if (imx_uart_is_imx1(sport))
 		ucr1 |= IMX1_UCR1_UARTCLKEN;
 	ucr1 |= UCR1_UARTEN;
 	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
 
-	writel(ucr1, sport->port.membase + UCR1);
+	imx_uart_writel(sport, ucr1, UCR1);
 
-	writel(old_ucr.ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
+	imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
 
-	uart_console_write(&sport->port, s, count, imx_console_putchar);
+	uart_console_write(&sport->port, s, count, imx_uart_console_putchar);
 
 	/*
 	 *	Finally, wait for transmitter to become empty
 	 *	and restore UCR1/2/3
 	 */
-	while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
+	while (!(imx_uart_readl(sport, USR2) & USR2_TXDC));
 
-	imx_port_ucrs_restore(&sport->port, &old_ucr);
+	imx_uart_ucrs_restore(sport, &old_ucr);
 
 	if (locked)
 		spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1801,17 +1954,17 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
  * try to determine the current setup.
  */
 static void __init
-imx_console_get_options(struct imx_port *sport, int *baud,
-			   int *parity, int *bits)
+imx_uart_console_get_options(struct imx_port *sport, int *baud,
+			     int *parity, int *bits)
 {
 
-	if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) {
+	if (imx_uart_readl(sport, UCR1) & UCR1_UARTEN) {
 		/* ok, the port was enabled */
 		unsigned int ucr2, ubir, ubmr, uartclk;
 		unsigned int baud_raw;
 		unsigned int ucfr_rfdiv;
 
-		ucr2 = readl(sport->port.membase + UCR2);
+		ucr2 = imx_uart_readl(sport, UCR2);
 
 		*parity = 'n';
 		if (ucr2 & UCR2_PREN) {
@@ -1826,10 +1979,10 @@ imx_console_get_options(struct imx_port *sport, int *baud,
 		else
 			*bits = 7;
 
-		ubir = readl(sport->port.membase + UBIR) & 0xffff;
-		ubmr = readl(sport->port.membase + UBMR) & 0xffff;
+		ubir = imx_uart_readl(sport, UBIR) & 0xffff;
+		ubmr = imx_uart_readl(sport, UBMR) & 0xffff;
 
-		ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7;
+		ucfr_rfdiv = (imx_uart_readl(sport, UFCR) & UFCR_RFDIV) >> 7;
 		if (ucfr_rfdiv == 6)
 			ucfr_rfdiv = 7;
 		else
@@ -1860,7 +2013,7 @@ imx_console_get_options(struct imx_port *sport, int *baud,
 }
 
 static int __init
-imx_console_setup(struct console *co, char *options)
+imx_uart_console_setup(struct console *co, char *options)
 {
 	struct imx_port *sport;
 	int baud = 9600;
@@ -1874,9 +2027,9 @@ imx_console_setup(struct console *co, char *options)
 	 * if so, search for the first available port that does have
 	 * console support.
 	 */
-	if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports))
+	if (co->index == -1 || co->index >= ARRAY_SIZE(imx_uart_ports))
 		co->index = 0;
-	sport = imx_ports[co->index];
+	sport = imx_uart_ports[co->index];
 	if (sport == NULL)
 		return -ENODEV;
 
@@ -1888,9 +2041,9 @@ imx_console_setup(struct console *co, char *options)
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
-		imx_console_get_options(sport, &baud, &parity, &bits);
+		imx_uart_console_get_options(sport, &baud, &parity, &bits);
 
-	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+	imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
@@ -1908,34 +2061,36 @@ error_console:
 	return retval;
 }
 
-static struct uart_driver imx_reg;
-static struct console imx_console = {
+static struct uart_driver imx_uart_uart_driver;
+static struct console imx_uart_console = {
 	.name		= DEV_NAME,
-	.write		= imx_console_write,
+	.write		= imx_uart_console_write,
 	.device		= uart_console_device,
-	.setup		= imx_console_setup,
+	.setup		= imx_uart_console_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
-	.data		= &imx_reg,
+	.data		= &imx_uart_uart_driver,
 };
 
-#define IMX_CONSOLE	&imx_console
+#define IMX_CONSOLE	&imx_uart_console
 
 #ifdef CONFIG_OF
-static void imx_console_early_putchar(struct uart_port *port, int ch)
+static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
 {
-	while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
+	struct imx_port *sport = (struct imx_port *)port;
+
+	while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL)
 		cpu_relax();
 
-	writel_relaxed(ch, port->membase + URTX0);
+	imx_uart_writel(sport, ch, URTX0);
 }
 
-static void imx_console_early_write(struct console *con, const char *s,
-				    unsigned count)
+static void imx_uart_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);
+	uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
 }
 
 static int __init
@@ -1944,7 +2099,7 @@ imx_console_early_setup(struct earlycon_device *dev, const char *opt)
 	if (!dev->port.membase)
 		return -ENODEV;
 
-	dev->con->write = imx_console_early_write;
+	dev->con->write = imx_uart_console_early_write;
 
 	return 0;
 }
@@ -1956,13 +2111,13 @@ OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
 #define IMX_CONSOLE	NULL
 #endif
 
-static struct uart_driver imx_reg = {
+static struct uart_driver imx_uart_uart_driver = {
 	.owner          = THIS_MODULE,
 	.driver_name    = DRIVER_NAME,
 	.dev_name       = DEV_NAME,
 	.major          = SERIAL_IMX_MAJOR,
 	.minor          = MINOR_START,
-	.nr             = ARRAY_SIZE(imx_ports),
+	.nr             = ARRAY_SIZE(imx_uart_ports),
 	.cons           = IMX_CONSOLE,
 };
 
@@ -1971,8 +2126,8 @@ static struct uart_driver imx_reg = {
  * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
  * could successfully get all information from dt or a negative errno.
  */
-static int serial_imx_probe_dt(struct imx_port *sport,
-		struct platform_device *pdev)
+static int imx_uart_probe_dt(struct imx_port *sport,
+			     struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	int ret;
@@ -2002,15 +2157,15 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 	return 0;
 }
 #else
-static inline int serial_imx_probe_dt(struct imx_port *sport,
-		struct platform_device *pdev)
+static inline int imx_uart_probe_dt(struct imx_port *sport,
+				    struct platform_device *pdev)
 {
 	return 1;
 }
 #endif
 
-static void serial_imx_probe_pdata(struct imx_port *sport,
-		struct platform_device *pdev)
+static void imx_uart_probe_pdata(struct imx_port *sport,
+				 struct platform_device *pdev)
 {
 	struct imxuart_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
@@ -2024,11 +2179,12 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
 		sport->have_rtscts = 1;
 }
 
-static int serial_imx_probe(struct platform_device *pdev)
+static int imx_uart_probe(struct platform_device *pdev)
 {
 	struct imx_port *sport;
 	void __iomem *base;
-	int ret = 0, reg;
+	int ret = 0;
+	u32 ucr1;
 	struct resource *res;
 	int txirq, rxirq, rtsirq;
 
@@ -2036,12 +2192,18 @@ static int serial_imx_probe(struct platform_device *pdev)
 	if (!sport)
 		return -ENOMEM;
 
-	ret = serial_imx_probe_dt(sport, pdev);
+	ret = imx_uart_probe_dt(sport, pdev);
 	if (ret > 0)
-		serial_imx_probe_pdata(sport, pdev);
+		imx_uart_probe_pdata(sport, pdev);
 	else if (ret < 0)
 		return ret;
 
+	if (sport->port.line >= ARRAY_SIZE(imx_uart_ports)) {
+		dev_err(&pdev->dev, "serial%d out of range\n",
+			sport->port.line);
+		return -EINVAL;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base))
@@ -2058,10 +2220,10 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->port.iotype = UPIO_MEM;
 	sport->port.irq = rxirq;
 	sport->port.fifosize = 32;
-	sport->port.ops = &imx_pops;
-	sport->port.rs485_config = imx_rs485_config;
+	sport->port.ops = &imx_uart_pops;
+	sport->port.rs485_config = imx_uart_rs485_config;
 	sport->port.flags = UPF_BOOT_AUTOCONF;
-	timer_setup(&sport->timer, imx_timeout, 0);
+	timer_setup(&sport->timer, imx_uart_timeout, 0);
 
 	sport->gpios = mctrl_gpio_init(&sport->port, 0);
 	if (IS_ERR(sport->gpios))
@@ -2090,49 +2252,56 @@ static int serial_imx_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/* initialize shadow register values */
+	sport->ucr1 = readl(sport->port.membase + UCR1);
+	sport->ucr2 = readl(sport->port.membase + UCR2);
+	sport->ucr3 = readl(sport->port.membase + UCR3);
+	sport->ucr4 = readl(sport->port.membase + UCR4);
+	sport->ufcr = readl(sport->port.membase + UFCR);
+
 	uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
 
 	if (sport->port.rs485.flags & SER_RS485_ENABLED &&
 	    (!sport->have_rtscts && !sport->have_rtsgpio))
 		dev_err(&pdev->dev, "no RTS control, disabling rs485\n");
 
-	imx_rs485_config(&sport->port, &sport->port.rs485);
+	imx_uart_rs485_config(&sport->port, &sport->port.rs485);
 
 	/* Disable interrupts before requesting them */
-	reg = readl_relaxed(sport->port.membase + UCR1);
-	reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
+	ucr1 = imx_uart_readl(sport, UCR1);
+	ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
 		 UCR1_TXMPTYEN | UCR1_RTSDEN);
-	writel_relaxed(reg, sport->port.membase + UCR1);
+	imx_uart_writel(sport, ucr1, UCR1);
 
-	if (!is_imx1_uart(sport) && sport->dte_mode) {
+	if (!imx_uart_is_imx1(sport) && sport->dte_mode) {
 		/*
 		 * The DCEDTE bit changes the direction of DSR, DCD, DTR and RI
 		 * and influences if UCR3_RI and UCR3_DCD changes the level of RI
 		 * and DCD (when they are outputs) or enables the respective
 		 * irqs. So set this bit early, i.e. before requesting irqs.
 		 */
-		reg = readl(sport->port.membase + UFCR);
-		if (!(reg & UFCR_DCEDTE))
-			writel(reg | UFCR_DCEDTE, sport->port.membase + UFCR);
+		u32 ufcr = imx_uart_readl(sport, UFCR);
+		if (!(ufcr & UFCR_DCEDTE))
+			imx_uart_writel(sport, ufcr | UFCR_DCEDTE, UFCR);
 
 		/*
 		 * Disable UCR3_RI and UCR3_DCD irqs. They are also not
 		 * enabled later because they cannot be cleared
 		 * (confirmed on i.MX25) which makes them unusable.
 		 */
-		writel(IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP | UCR3_DSR,
-		       sport->port.membase + UCR3);
+		imx_uart_writel(sport,
+				IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP | UCR3_DSR,
+				UCR3);
 
 	} else {
-		unsigned long ucr3 = UCR3_DSR;
-
-		reg = readl(sport->port.membase + UFCR);
-		if (reg & UFCR_DCEDTE)
-			writel(reg & ~UFCR_DCEDTE, sport->port.membase + UFCR);
+		u32 ucr3 = UCR3_DSR;
+		u32 ufcr = imx_uart_readl(sport, UFCR);
+		if (ufcr & UFCR_DCEDTE)
+			imx_uart_writel(sport, ufcr & ~UFCR_DCEDTE, UFCR);
 
-		if (!is_imx1_uart(sport))
+		if (!imx_uart_is_imx1(sport))
 			ucr3 |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP;
-		writel(ucr3, sport->port.membase + UCR3);
+		imx_uart_writel(sport, ucr3, UCR3);
 	}
 
 	clk_disable_unprepare(sport->clk_ipg);
@@ -2142,7 +2311,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 	 * chips only have one interrupt.
 	 */
 	if (txirq > 0) {
-		ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
+		ret = devm_request_irq(&pdev->dev, rxirq, imx_uart_rxint, 0,
 				       dev_name(&pdev->dev), sport);
 		if (ret) {
 			dev_err(&pdev->dev, "failed to request rx irq: %d\n",
@@ -2150,7 +2319,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 			return ret;
 		}
 
-		ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
+		ret = devm_request_irq(&pdev->dev, txirq, imx_uart_txint, 0,
 				       dev_name(&pdev->dev), sport);
 		if (ret) {
 			dev_err(&pdev->dev, "failed to request tx irq: %d\n",
@@ -2158,7 +2327,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 			return ret;
 		}
 	} else {
-		ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
+		ret = devm_request_irq(&pdev->dev, rxirq, imx_uart_int, 0,
 				       dev_name(&pdev->dev), sport);
 		if (ret) {
 			dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
@@ -2166,90 +2335,90 @@ static int serial_imx_probe(struct platform_device *pdev)
 		}
 	}
 
-	imx_ports[sport->port.line] = sport;
+	imx_uart_ports[sport->port.line] = sport;
 
 	platform_set_drvdata(pdev, sport);
 
-	return uart_add_one_port(&imx_reg, &sport->port);
+	return uart_add_one_port(&imx_uart_uart_driver, &sport->port);
 }
 
-static int serial_imx_remove(struct platform_device *pdev)
+static int imx_uart_remove(struct platform_device *pdev)
 {
 	struct imx_port *sport = platform_get_drvdata(pdev);
 
-	return uart_remove_one_port(&imx_reg, &sport->port);
+	return uart_remove_one_port(&imx_uart_uart_driver, &sport->port);
 }
 
-static void serial_imx_restore_context(struct imx_port *sport)
+static void imx_uart_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);
+	imx_uart_writel(sport, sport->saved_reg[4], UFCR);
+	imx_uart_writel(sport, sport->saved_reg[5], UESC);
+	imx_uart_writel(sport, sport->saved_reg[6], UTIM);
+	imx_uart_writel(sport, sport->saved_reg[7], UBIR);
+	imx_uart_writel(sport, sport->saved_reg[8], UBMR);
+	imx_uart_writel(sport, sport->saved_reg[9], IMX21_UTS);
+	imx_uart_writel(sport, sport->saved_reg[0], UCR1);
+	imx_uart_writel(sport, sport->saved_reg[1] | UCR2_SRST, UCR2);
+	imx_uart_writel(sport, sport->saved_reg[2], UCR3);
+	imx_uart_writel(sport, sport->saved_reg[3], UCR4);
 	sport->context_saved = false;
 }
 
-static void serial_imx_save_context(struct imx_port *sport)
+static void imx_uart_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->saved_reg[0] = imx_uart_readl(sport, UCR1);
+	sport->saved_reg[1] = imx_uart_readl(sport, UCR2);
+	sport->saved_reg[2] = imx_uart_readl(sport, UCR3);
+	sport->saved_reg[3] = imx_uart_readl(sport, UCR4);
+	sport->saved_reg[4] = imx_uart_readl(sport, UFCR);
+	sport->saved_reg[5] = imx_uart_readl(sport, UESC);
+	sport->saved_reg[6] = imx_uart_readl(sport, UTIM);
+	sport->saved_reg[7] = imx_uart_readl(sport, UBIR);
+	sport->saved_reg[8] = imx_uart_readl(sport, UBMR);
+	sport->saved_reg[9] = imx_uart_readl(sport, IMX21_UTS);
 	sport->context_saved = true;
 }
 
-static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
+static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
 {
-	unsigned int val;
+	u32 ucr3;
 
-	val = readl(sport->port.membase + UCR3);
+	ucr3 = imx_uart_readl(sport, UCR3);
 	if (on) {
-		writel(USR1_AWAKE, sport->port.membase + USR1);
-		val |= UCR3_AWAKEN;
+		imx_uart_writel(sport, USR1_AWAKE, USR1);
+		ucr3 |= UCR3_AWAKEN;
+	} else {
+		ucr3 &= ~UCR3_AWAKEN;
 	}
-	else
-		val &= ~UCR3_AWAKEN;
-	writel(val, sport->port.membase + UCR3);
+	imx_uart_writel(sport, ucr3, UCR3);
 
 	if (sport->have_rtscts) {
-		val = readl(sport->port.membase + UCR1);
+		u32 ucr1 = imx_uart_readl(sport, UCR1);
 		if (on)
-			val |= UCR1_RTSDEN;
+			ucr1 |= UCR1_RTSDEN;
 		else
-			val &= ~UCR1_RTSDEN;
-		writel(val, sport->port.membase + UCR1);
+			ucr1 &= ~UCR1_RTSDEN;
+		imx_uart_writel(sport, ucr1, UCR1);
 	}
 }
 
-static int imx_serial_port_suspend_noirq(struct device *dev)
+static int imx_uart_suspend_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_port *sport = platform_get_drvdata(pdev);
 
-	serial_imx_save_context(sport);
+	imx_uart_save_context(sport);
 
 	clk_disable(sport->clk_ipg);
 
 	return 0;
 }
 
-static int imx_serial_port_resume_noirq(struct device *dev)
+static int imx_uart_resume_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_port *sport = platform_get_drvdata(pdev);
@@ -2259,18 +2428,18 @@ static int imx_serial_port_resume_noirq(struct device *dev)
 	if (ret)
 		return ret;
 
-	serial_imx_restore_context(sport);
+	imx_uart_restore_context(sport);
 
 	return 0;
 }
 
-static int imx_serial_port_suspend(struct device *dev)
+static int imx_uart_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_port *sport = platform_get_drvdata(pdev);
 	int ret;
 
-	uart_suspend_port(&imx_reg, &sport->port);
+	uart_suspend_port(&imx_uart_uart_driver, &sport->port);
 	disable_irq(sport->port.irq);
 
 	ret = clk_prepare_enable(sport->clk_ipg);
@@ -2278,20 +2447,20 @@ static int imx_serial_port_suspend(struct device *dev)
 		return ret;
 
 	/* enable wakeup from i.MX UART */
-	serial_imx_enable_wakeup(sport, true);
+	imx_uart_enable_wakeup(sport, true);
 
 	return 0;
 }
 
-static int imx_serial_port_resume(struct device *dev)
+static int imx_uart_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);
+	imx_uart_enable_wakeup(sport, false);
 
-	uart_resume_port(&imx_reg, &sport->port);
+	uart_resume_port(&imx_uart_uart_driver, &sport->port);
 	enable_irq(sport->port.irq);
 
 	clk_disable_unprepare(sport->clk_ipg);
@@ -2299,74 +2468,74 @@ static int imx_serial_port_resume(struct device *dev)
 	return 0;
 }
 
-static int imx_serial_port_freeze(struct device *dev)
+static int imx_uart_freeze(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_port *sport = platform_get_drvdata(pdev);
 
-	uart_suspend_port(&imx_reg, &sport->port);
+	uart_suspend_port(&imx_uart_uart_driver, &sport->port);
 
 	return clk_prepare_enable(sport->clk_ipg);
 }
 
-static int imx_serial_port_thaw(struct device *dev)
+static int imx_uart_thaw(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_port *sport = platform_get_drvdata(pdev);
 
-	uart_resume_port(&imx_reg, &sport->port);
+	uart_resume_port(&imx_uart_uart_driver, &sport->port);
 
 	clk_disable_unprepare(sport->clk_ipg);
 
 	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,
-	.freeze_noirq = imx_serial_port_suspend_noirq,
-	.restore_noirq = imx_serial_port_resume_noirq,
-	.suspend = imx_serial_port_suspend,
-	.resume = imx_serial_port_resume,
-	.freeze = imx_serial_port_freeze,
-	.thaw = imx_serial_port_thaw,
-	.restore = imx_serial_port_thaw,
+static const struct dev_pm_ops imx_uart_pm_ops = {
+	.suspend_noirq = imx_uart_suspend_noirq,
+	.resume_noirq = imx_uart_resume_noirq,
+	.freeze_noirq = imx_uart_suspend_noirq,
+	.restore_noirq = imx_uart_resume_noirq,
+	.suspend = imx_uart_suspend,
+	.resume = imx_uart_resume,
+	.freeze = imx_uart_freeze,
+	.thaw = imx_uart_thaw,
+	.restore = imx_uart_thaw,
 };
 
-static struct platform_driver serial_imx_driver = {
-	.probe		= serial_imx_probe,
-	.remove		= serial_imx_remove,
+static struct platform_driver imx_uart_platform_driver = {
+	.probe = imx_uart_probe,
+	.remove = imx_uart_remove,
 
-	.id_table	= imx_uart_devtype,
-	.driver		= {
-		.name	= "imx-uart",
+	.id_table = imx_uart_devtype,
+	.driver = {
+		.name = "imx-uart",
 		.of_match_table = imx_uart_dt_ids,
-		.pm	= &imx_serial_port_pm_ops,
+		.pm = &imx_uart_pm_ops,
 	},
 };
 
-static int __init imx_serial_init(void)
+static int __init imx_uart_init(void)
 {
-	int ret = uart_register_driver(&imx_reg);
+	int ret = uart_register_driver(&imx_uart_uart_driver);
 
 	if (ret)
 		return ret;
 
-	ret = platform_driver_register(&serial_imx_driver);
+	ret = platform_driver_register(&imx_uart_platform_driver);
 	if (ret != 0)
-		uart_unregister_driver(&imx_reg);
+		uart_unregister_driver(&imx_uart_uart_driver);
 
 	return ret;
 }
 
-static void __exit imx_serial_exit(void)
+static void __exit imx_uart_exit(void)
 {
-	platform_driver_unregister(&serial_imx_driver);
-	uart_unregister_driver(&imx_reg);
+	platform_driver_unregister(&imx_uart_platform_driver);
+	uart_unregister_driver(&imx_uart_uart_driver);
 }
 
-module_init(imx_serial_init);
-module_exit(imx_serial_exit);
+module_init(imx_uart_init);
+module_exit(imx_uart_exit);
 
 MODULE_AUTHOR("Sascha Hauer");
 MODULE_DESCRIPTION("IMX generic serial port driver");