summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorRichard Genoud <richard.genoud@gmail.com>2016-12-13 17:27:56 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-19 20:17:21 +0100
commit075f493a974e390ba7664cef0b17994999705150 (patch)
tree68a70f484ab803430f8c28b8d0b6d5d2f49ef8bf /drivers/tty
parent4a6716f165179679ee418b79445aa4031118ecd1 (diff)
tty/serial: atmel_serial: BUG: stop DMA from transmitting in stop_tx
commit 89d8232411a85b9a6b12fd5da4d07d8a138a8e0c upstream. If we don't disable the transmitter in atmel_stop_tx, the DMA buffer continues to send data until it is emptied. This cause problems with the flow control (CTS is asserted and data are still sent). So, disabling the transmitter in atmel_stop_tx is a sane thing to do. Tested on at91sam9g35-cm(DMA) Tested for regressions on sama5d2-xplained(Fifo) and at91sam9g20ek(PDC) Signed-off-by: Richard Genoud <richard.genoud@gmail.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/atmel_serial.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index e0b89b961e1b..a0f911641b04 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -470,6 +470,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);
@@ -502,6 +510,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);
}
/*