diff options
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r-- | drivers/tty/serial/imx.c | 308 |
1 files changed, 157 insertions, 151 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 757825edb0cd..523f296d5747 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -210,12 +210,8 @@ struct imx_port { struct mctrl_gpios *gpios; - /* shadow registers */ - unsigned int ucr1; - unsigned int ucr2; - unsigned int ucr3; - unsigned int ucr4; - unsigned int ufcr; + /* counter to stop 0xff flood */ + int idle_counter; /* DMA fields */ unsigned int dma_is_enabled:1; @@ -273,59 +269,14 @@ static const struct of_device_id imx_uart_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, imx_uart_dt_ids); -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; - } +static inline void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset) +{ writel(val, sport->port.membase + offset); } -static u32 imx_uart_readl(struct imx_port *sport, u32 offset) +static inline 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 - * automatically becomes one after being cleared, 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); - } + return readl(sport->port.membase + offset); } static inline unsigned imx_uart_uts_reg(struct imx_port *sport) @@ -398,6 +349,41 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) } /* called with port.lock taken and irqs off */ +static void imx_uart_soft_reset(struct imx_port *sport) +{ + int i = 10; + u32 ucr2, ubir, ubmr, uts; + + /* + * According to the Reference Manual description of the UART SRST bit: + * + * "Reset the transmit and receive state machines, + * all FIFOs and register USR1, USR2, UBIR, UBMR, UBRC, URXD, UTXD + * and UTS[6-3]". + * + * We don't need to restore the old values from USR1, USR2, URXD and + * UTXD. UBRC is read only, so only save/restore the other three + * registers. + */ + ubir = imx_uart_readl(sport, UBIR); + ubmr = imx_uart_readl(sport, UBMR); + uts = imx_uart_readl(sport, IMX21_UTS); + + ucr2 = imx_uart_readl(sport, UCR2); + imx_uart_writel(sport, ucr2 & ~UCR2_SRST, UCR2); + + while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0)) + udelay(1); + + /* Restore the registers */ + imx_uart_writel(sport, ubir, UBIR); + imx_uart_writel(sport, ubmr, UBMR); + imx_uart_writel(sport, uts, IMX21_UTS); + + sport->idle_counter = 0; +} + +/* 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; @@ -476,7 +462,8 @@ static void imx_uart_stop_tx(struct uart_port *port) imx_uart_rts_inactive(sport, &ucr2); imx_uart_writel(sport, ucr2, UCR2); - imx_uart_start_rx(port); + if (!port->rs485_rx_during_tx_gpio) + imx_uart_start_rx(port); sport->tx_state = OFF; } @@ -705,7 +692,8 @@ static void imx_uart_start_tx(struct uart_port *port) imx_uart_rts_inactive(sport, &ucr2); imx_uart_writel(sport, ucr2, UCR2); - if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) && + !port->rs485_rx_during_tx_gpio) imx_uart_stop_rx(port); sport->tx_state = WAIT_AFTER_RTS; @@ -771,7 +759,7 @@ static irqreturn_t __imx_uart_rtsint(int irq, void *dev_id) imx_uart_writel(sport, USR1_RTSD, USR1); usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS; - uart_handle_cts_change(&sport->port, !!usr1); + uart_handle_cts_change(&sport->port, usr1); wake_up_interruptible(&sport->port.state->port.delta_msr_wait); return IRQ_HANDLED; @@ -801,33 +789,73 @@ static irqreturn_t imx_uart_txint(int irq, void *dev_id) return IRQ_HANDLED; } +/* Check if hardware Rx flood is in progress, and issue soft reset to stop it. + * This is to be called from Rx ISRs only when some bytes were actually + * received. + * + * A way to reproduce the flood (checked on iMX6SX) is: open iMX UART at 9600 + * 8N1, and from external source send 0xf0 char at 115200 8N1. In about 90% of + * cases this starts a flood of "receiving" of 0xff characters by the iMX6 UART + * that is terminated by any activity on RxD line, or could be stopped by + * issuing soft reset to the UART (just stop/start of RX does not help). Note + * that what we do here is sending isolated start bit about 2.4 times shorter + * than it is to be on UART configured baud rate. + */ +static void imx_uart_check_flood(struct imx_port *sport, u32 usr2) +{ + /* To detect hardware 0xff flood we monitor RxD line between RX + * interrupts to isolate "receiving" of char(s) with no activity + * on RxD line, that'd never happen on actual data transfers. + * + * We use USR2_WAKE bit to check for activity on RxD line, but we have a + * race here if we clear USR2_WAKE when receiving of a char is in + * progress, so we might get RX interrupt later with USR2_WAKE bit + * cleared. Note though that as we don't try to clear USR2_WAKE when we + * detected no activity, this race may hide actual activity only once. + * + * Yet another case where receive interrupt may occur without RxD + * activity is expiration of aging timer, so we consider this as well. + * + * We use 'idle_counter' to ensure that we got at least so many RX + * interrupts without any detected activity on RxD line. 2 cases + * described plus 1 to be on the safe side gives us a margin of 3, + * below. In practice I was not able to produce a false positive to + * induce soft reset at regular data transfers even using 1 as the + * margin, so 3 is actually very strong. + * + * We count interrupts, not chars in 'idle-counter' for simplicity. + */ + + if (usr2 & USR2_WAKE) { + imx_uart_writel(sport, USR2_WAKE, USR2); + sport->idle_counter = 0; + } else if (++sport->idle_counter > 3) { + dev_warn(sport->port.dev, "RX flood detected: soft reset."); + imx_uart_soft_reset(sport); /* also clears 'sport->idle_counter' */ + } +} + 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; + u32 usr2, rx; - while (imx_uart_readl(sport, USR2) & USR2_RDR) { - u32 usr2; + /* If we received something, check for 0xff flood */ + usr2 = imx_uart_readl(sport, USR2); + if (usr2 & USR2_RDR) + imx_uart_check_flood(sport, usr2); - flg = TTY_NORMAL; + while ((rx = imx_uart_readl(sport, URXD0)) & URXD_CHARRDY) { + unsigned int flg = TTY_NORMAL; sport->port.icount.rx++; - rx = imx_uart_readl(sport, URXD0); - - usr2 = imx_uart_readl(sport, USR2); - if (usr2 & USR2_BRCD) { - imx_uart_writel(sport, USR2_BRCD, USR2); - if (uart_handle_break(&sport->port)) - continue; - } - - if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) - continue; - if (unlikely(rx & URXD_ERR)) { - if (rx & URXD_BRK) + if (rx & URXD_BRK) { sport->port.icount.brk++; + if (uart_handle_break(&sport->port)) + continue; + } else if (rx & URXD_PRERR) sport->port.icount.parity++; else if (rx & URXD_FRMERR) @@ -835,11 +863,8 @@ static irqreturn_t __imx_uart_rxint(int irq, void *dev_id) if (rx & URXD_OVRRUN) sport->port.icount.overrun++; - if (rx & sport->port.ignore_status_mask) { - if (++ignored > 100) - goto out; + if (rx & sport->port.ignore_status_mask) continue; - } rx &= (sport->port.read_status_mask | 0xFF); @@ -853,16 +878,17 @@ static irqreturn_t __imx_uart_rxint(int irq, void *dev_id) flg = TTY_OVERRUN; sport->port.sysrq = 0; + } else if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) { + continue; } if (sport->port.ignore_status_mask & URXD_DUMMY_READ) - goto out; + continue; if (tty_insert_flip_char(port, rx, flg) == 0) sport->port.icount.buf_overrun++; } -out: tty_flip_buffer_push(port); return IRQ_HANDLED; @@ -1147,55 +1173,62 @@ static void imx_uart_dma_rx_callback(void *data) status = dmaengine_tx_status(chan, sport->rx_cookie, &state); if (status == DMA_ERROR) { + spin_lock(&sport->port.lock); imx_uart_clear_rx_errors(sport); + spin_unlock(&sport->port.lock); return; } - if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) { + /* + * The state-residue variable represents the empty space + * relative to the entire buffer. Taking this in consideration + * the head is always calculated base on the buffer total + * length - DMA transaction residue. The UART script from the + * SDMA firmware will jump to the next buffer descriptor, + * once a DMA transaction if finalized (IMX53 RM - A.4.1.2.4). + * Taking this in consideration the tail is always at the + * beginning of the buffer descriptor that contains the head. + */ - /* - * The state-residue variable represents the empty space - * relative to the entire buffer. Taking this in consideration - * the head is always calculated base on the buffer total - * length - DMA transaction residue. The UART script from the - * SDMA firmware will jump to the next buffer descriptor, - * once a DMA transaction if finalized (IMX53 RM - A.4.1.2.4). - * Taking this in consideration the tail is always at the - * beginning of the buffer descriptor that contains the head. - */ + /* Calculate the head */ + rx_ring->head = sg_dma_len(sgl) - state.residue; + + /* Calculate the tail. */ + bd_size = sg_dma_len(sgl) / sport->rx_periods; + rx_ring->tail = ((rx_ring->head-1) / bd_size) * bd_size; - /* Calculate the head */ - rx_ring->head = sg_dma_len(sgl) - state.residue; + if (rx_ring->head <= sg_dma_len(sgl) && + rx_ring->head > rx_ring->tail) { - /* Calculate the tail. */ - bd_size = sg_dma_len(sgl) / sport->rx_periods; - rx_ring->tail = ((rx_ring->head-1) / bd_size) * bd_size; + /* Move data from tail to head */ + r_bytes = rx_ring->head - rx_ring->tail; - if (rx_ring->head <= sg_dma_len(sgl) && - rx_ring->head > rx_ring->tail) { + /* If we received something, check for 0xff flood */ + spin_lock(&sport->port.lock); + imx_uart_check_flood(sport, imx_uart_readl(sport, USR2)); + spin_unlock(&sport->port.lock); - /* Move data from tail to head */ - r_bytes = rx_ring->head - rx_ring->tail; + if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) { /* CPU claims ownership of RX DMA buffer */ dma_sync_sg_for_cpu(sport->port.dev, sgl, 1, - DMA_FROM_DEVICE); + DMA_FROM_DEVICE); w_bytes = tty_insert_flip_string(port, - sport->rx_buf + rx_ring->tail, r_bytes); + sport->rx_buf + rx_ring->tail, r_bytes); /* UART retrieves ownership of RX DMA buffer */ dma_sync_sg_for_device(sport->port.dev, sgl, 1, - DMA_FROM_DEVICE); + DMA_FROM_DEVICE); if (w_bytes != r_bytes) sport->port.icount.buf_overrun++; sport->port.icount.rx += w_bytes; - } else { - WARN_ON(rx_ring->head > sg_dma_len(sgl)); - WARN_ON(rx_ring->head <= rx_ring->tail); } + } else { + WARN_ON(rx_ring->head > sg_dma_len(sgl)); + WARN_ON(rx_ring->head <= rx_ring->tail); } if (w_bytes) { @@ -1271,6 +1304,8 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport) imx_uart_writel(sport, USR2_ORE, USR2); } + sport->idle_counter = 0; + } #define TXTL_DEFAULT 2 /* reset default */ @@ -1398,7 +1433,7 @@ static void imx_uart_disable_dma(struct imx_port *sport) static int imx_uart_startup(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - int retval, i; + int retval; unsigned long flags; int dma_is_inited = 0; u32 ucr1, ucr2, ucr3, ucr4, uts; @@ -1430,15 +1465,9 @@ static int imx_uart_startup(struct uart_port *port) dma_is_inited = 1; spin_lock_irqsave(&sport->port.lock, flags); - /* Reset fifo's and state machines */ - i = 100; - ucr2 = imx_uart_readl(sport, UCR2); - ucr2 &= ~UCR2_SRST; - imx_uart_writel(sport, ucr2, UCR2); - - while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0)) - udelay(1); + /* Reset fifo's and state machines */ + imx_uart_soft_reset(sport); /* * Finally, clear and enable interrupts @@ -1564,7 +1593,8 @@ static void imx_uart_shutdown(struct uart_port *port) spin_lock_irqsave(&sport->port.lock, flags); ucr1 = imx_uart_readl(sport, UCR1); - ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_RXDMAEN | UCR1_ATDMAEN); + ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_RXDMAEN | + UCR1_ATDMAEN | UCR1_SNDBRK); /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ if (port->rs485.flags & SER_RS485_ENABLED && port->rs485.flags & SER_RS485_RTS_ON_SEND && @@ -1593,8 +1623,6 @@ 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]; - u32 ucr2; - int i = 100, ubir, ubmr, uts; if (!sport->dma_chan_tx) return; @@ -1612,32 +1640,8 @@ static void imx_uart_flush_buffer(struct uart_port *port) sport->dma_is_txing = 0; } - /* - * According to the Reference Manual description of the UART SRST bit: - * - * "Reset the transmit and receive state machines, - * all FIFOs and register USR1, USR2, UBIR, UBMR, UBRC, URXD, UTXD - * and UTS[6-3]". - * - * We don't need to restore the old values from USR1, USR2, URXD and - * UTXD. UBRC is read only, so only save/restore the other three - * registers. - */ - ubir = imx_uart_readl(sport, UBIR); - ubmr = imx_uart_readl(sport, UBMR); - uts = imx_uart_readl(sport, IMX21_UTS); - - ucr2 = imx_uart_readl(sport, UCR2); - ucr2 &= ~UCR2_SRST; - imx_uart_writel(sport, ucr2, UCR2); - - while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0)) - udelay(1); + imx_uart_soft_reset(sport); - /* Restore the registers */ - imx_uart_writel(sport, ubir, UBIR); - imx_uart_writel(sport, ubmr, UBMR); - imx_uart_writel(sport, uts, IMX21_UTS); } static void @@ -1955,6 +1959,10 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio rs485conf->flags & SER_RS485_RX_DURING_TX) imx_uart_start_rx(port); + if (port->rs485_rx_during_tx_gpio) + gpiod_set_value_cansleep(port->rs485_rx_during_tx_gpio, + !!(rs485conf->flags & SER_RS485_RX_DURING_TX)); + return 0; } @@ -2340,13 +2348,6 @@ static int imx_uart_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); - ret = uart_get_rs485_mode(&sport->port); if (ret) { clk_disable_unprepare(sport->clk_ipg); @@ -2374,6 +2375,11 @@ static int imx_uart_probe(struct platform_device *pdev) ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | UCR1_RTSDEN); imx_uart_writel(sport, ucr1, UCR1); + /* Disable Ageing Timer interrupt */ + ucr2 = imx_uart_readl(sport, UCR2); + ucr2 &= ~UCR2_ATEN; + imx_uart_writel(sport, ucr2, UCR2); + /* * In case RS485 is enabled without GPIO RTS control, the UART IP * is used to control CTS signal. Keep both the UART and Receiver |