*ucr2 |= UCR2_CTSC;
}
+/* called with port.lock taken and irqs off */
+static void imx_start_rx(struct uart_port *port)
+{
+ struct imx_port *sport = (struct imx_port *)port;
+ 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;
+ }
+
+ /* 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_stop_tx(struct uart_port *port)
{
imx_port_rts_active(sport, &ucr2);
else
imx_port_rts_inactive(sport, &ucr2);
- ucr2 |= UCR2_RXEN;
imx_uart_writel(sport, ucr2, UCR2);
+ imx_start_rx(port);
+
ucr4 = imx_uart_readl(sport, UCR4);
ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4);
struct imx_port *sport = (struct imx_port *)port;
u32 ucr1, ucr2;
+ ucr1 = imx_uart_readl(sport, UCR1);
ucr2 = imx_uart_readl(sport, UCR2);
- imx_uart_writel(sport, ucr2 & ~UCR2_RXEN, UCR2);
- /* disable the `Receiver Ready Interrrupt` */
- ucr1 = imx_uart_readl(sport, UCR1);
- imx_uart_writel(sport, ucr1 & ~UCR1_RRDYEN, UCR1);
+ if (sport->dma_is_enabled) {
+ ucr1 &= ~(UCR1_RXDMAEN | UCR1_ATDMAEN);
+ } else {
+ ucr1 &= ~UCR1_RRDYEN;
+ }
+ imx_uart_writel(sport, ucr1, UCR1);
+
+ ucr2 &= ~UCR2_RXEN;
+ imx_uart_writel(sport, ucr2, UCR2);
}
/* called with port.lock taken and irqs off */
imx_port_rts_active(sport, &ucr2);
else
imx_port_rts_inactive(sport, &ucr2);
- if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
- ucr2 &= ~UCR2_RXEN;
imx_uart_writel(sport, ucr2, UCR2);
+ if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
+ imx_stop_rx(port);
+
/* enable transmitter and shifter empty irq */
ucr4 = imx_uart_readl(sport, UCR4);
ucr4 |= UCR4_TCEN;
imx_uart_writel(sport, USR1_RTSD | USR1_DTRD, USR1);
imx_uart_writel(sport, USR2_ORE, USR2);
- if (dma_is_inited)
- imx_enable_dma(sport);
-
ucr1 = imx_uart_readl(sport, UCR1) & ~UCR1_RRDYEN;
- if (!sport->dma_is_enabled)
- ucr1 |= UCR1_RRDYEN;
ucr1 |= UCR1_UARTEN;
if (sport->have_rtscts)
ucr1 |= UCR1_RTSDEN;
*/
imx_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)
+ if (dma_is_inited) {
+ imx_enable_dma(sport);
start_rx_dma(sport);
+ } else {
+ ucr1 = imx_uart_readl(sport, UCR1);
+ ucr1 |= UCR1_RRDYEN;
+ imx_uart_writel(sport, ucr1, UCR1);
+ }
spin_unlock_irqrestore(&sport->port.lock, flags);
spin_lock_irqsave(&sport->port.lock, flags);
ucr1 = imx_uart_readl(sport, UCR1);
- ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+ ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN);
imx_uart_writel(sport, ucr1, UCR1);
spin_unlock_irqrestore(&sport->port.lock, flags);
spin_lock_irqsave(&sport->port.lock, flags);
+ /*
+ * 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);
+
if (is_imx1_uart(sport))
ucr1 |= IMX1_UCR1_UARTCLKEN;
- ucr1 |= UCR1_UARTEN | UCR1_RRDYEN;
- ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN);
- imx_uart_writel(sport, ucr1, UCR1);
- ucr2 = imx_uart_readl(sport, UCR2);
+ ucr1 |= UCR1_UARTEN;
+ ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN | UCR1_RRDYEN);
+
ucr2 |= UCR2_RXEN;
+
+ imx_uart_writel(sport, ucr1, UCR1);
imx_uart_writel(sport, ucr2, UCR2);
+ /* now enable irqs */
+ imx_uart_writel(sport, ucr1 | UCR1_RRDYEN, UCR1);
+
spin_unlock_irqrestore(&sport->port.lock, flags);
return 0;
/* 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) {
- ucr2 = imx_uart_readl(sport, UCR2);
- ucr2 |= UCR2_RXEN;
- imx_uart_writel(sport, ucr2, UCR2);
- }
+ rs485conf->flags & SER_RS485_RX_DURING_TX)
+ imx_start_rx(port);
port->rs485 = *rs485conf;