diff options
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r-- | drivers/tty/serial/imx.c | 1209 |
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"); |