|
@@ -481,6 +481,14 @@ static void atmel_stop_tx(struct uart_port *port)
|
|
|
/* disable PDC transmit */
|
|
|
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Disable the transmitter.
|
|
|
+ * This is mandatory when DMA is used, otherwise the DMA buffer
|
|
|
+ * is fully transmitted.
|
|
|
+ */
|
|
|
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS);
|
|
|
+
|
|
|
/* Disable interrupts */
|
|
|
atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
|
|
|
|
|
@@ -513,6 +521,9 @@ static void atmel_start_tx(struct uart_port *port)
|
|
|
|
|
|
/* Enable interrupts */
|
|
|
atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
|
|
|
+
|
|
|
+ /* re-enable the transmitter */
|
|
|
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -798,6 +809,11 @@ static void atmel_complete_tx_dma(void *arg)
|
|
|
*/
|
|
|
if (!uart_circ_empty(xmit))
|
|
|
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
|
|
|
+ else if ((port->rs485.flags & SER_RS485_ENABLED) &&
|
|
|
+ !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
|
|
|
+ /* DMA done, stop TX, start RX for RS485 */
|
|
|
+ atmel_start_rx(port);
|
|
|
+ }
|
|
|
|
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
|
}
|
|
@@ -900,12 +916,6 @@ static void atmel_tx_dma(struct uart_port *port)
|
|
|
desc->callback = atmel_complete_tx_dma;
|
|
|
desc->callback_param = atmel_port;
|
|
|
atmel_port->cookie_tx = dmaengine_submit(desc);
|
|
|
-
|
|
|
- } else {
|
|
|
- if (port->rs485.flags & SER_RS485_ENABLED) {
|
|
|
- /* DMA done, stop TX, start RX for RS485 */
|
|
|
- atmel_start_rx(port);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|