From: Greg Kroah-Hartman Date: Tue, 15 Nov 2016 19:49:50 +0000 (+0100) Subject: 4.8-stable patches X-Git-Tag: v4.4.33~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2683cf92cfdab3e4363a0cd04ab6312b8a05d6fe;p=thirdparty%2Fkernel%2Fstable-queue.git 4.8-stable patches added patches: tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch --- diff --git a/queue-4.8/series b/queue-4.8/series index 938ebabf532..0cc4d78d29b 100644 --- a/queue-4.8/series +++ b/queue-4.8/series @@ -45,3 +45,4 @@ drm-i915-dp-bdw-cdclk-fix-for-dp-audio.patch drm-i915-dp-extend-bdw-dp-audio-workaround-to-gen9-platforms.patch drm-amdgpu-disable-runtime-pm-in-certain-cases.patch drm-amdgpu-fix-crash-in-acp_hw_fini.patch +tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch diff --git a/queue-4.8/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch b/queue-4.8/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch new file mode 100644 index 00000000000..490da764493 --- /dev/null +++ b/queue-4.8/tty-serial-at91-fix-hardware-handshake-on-atmel-platforms.patch @@ -0,0 +1,134 @@ +From 9bcffe7575b721d7b6d9b3090fe18809d9806e78 Mon Sep 17 00:00:00 2001 +From: Richard Genoud +Date: Thu, 27 Oct 2016 18:04:06 +0200 +Subject: tty/serial: at91: fix hardware handshake on Atmel platforms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Richard Genoud + +commit 9bcffe7575b721d7b6d9b3090fe18809d9806e78 upstream. + +After commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management +when hardware handshake is enabled"), the hardware handshake wasn't +functional anymore on Atmel platforms (beside SAMA5D2). + +To understand why, one has to understand the flag ATMEL_US_USMODE_HWHS +first: +Before commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management +when hardware handshake is enabled"), this flag was never set. +Thus, the CTS/RTS where only handled by serial_core (and everything +worked just fine). + +This commit introduced the use of the ATMEL_US_USMODE_HWHS flag, +enabling it for all boards when the user space enables flow control. + +When the ATMEL_US_USMODE_HWHS is set, the Atmel USART controller +handles a part of the flow control job: +- disable the transmitter when the CTS pin gets high. +- drive the RTS pin high when the DMA buffer transfer is completed or + PDC RX buffer full or RX FIFO is beyond threshold. (depending on the + controller version). + +NB: This feature is *not* mandatory for the flow control to work. +(Nevertheless, it's very useful if low latencies are needed.) + +Now, the specifics of the ATMEL_US_USMODE_HWHS flag: + +- For platforms with DMAC and no FIFOs (sam9x25, sam9x35, sama5D3, +sama5D4, sam9g15, sam9g25, sam9g35)* this feature simply doesn't work. +( source: https://lkml.org/lkml/2016/9/7/598 ) +Tested it on sam9g35, the RTS pins always stays up, even when RXEN=1 +or a new DMA transfer descriptor is set. +=> ATMEL_US_USMODE_HWHS must not be used for those platforms + +- For platforms with a PDC (sam926{0,1,3}, sam9g10, sam9g20, sam9g45, +sam9g46)*, there's another kind of problem. Once the flag +ATMEL_US_USMODE_HWHS is set, the RTS pin can't be driven anymore via +RTSEN/RTSDIS in USART Control Register. The RTS pin can only be driven +by enabling/disabling the receiver or setting RCR=RNCR=0 in the PDC +(Receive (Next) Counter Register). +=> Doing this is beyond the scope of this patch and could add other +bugs, so the original (and working) behaviour should be set for those +platforms (meaning ATMEL_US_USMODE_HWHS flag should be unset). + +- For platforms with a FIFO (sama5d2)*, the RTS pin is driven according +to the RX FIFO thresholds, and can be also driven by RTSEN/RTSDIS in +USART Control Register. No problem here. +(This was the use case of commit 1cf6e8fc8341 ("tty/serial: at91: fix +RTS line management when hardware handshake is enabled")) +NB: If the CTS pin declared as a GPIO in the DTS, (for instance +cts-gpios = <&pioA PIN_PB31 GPIO_ACTIVE_LOW>), the transmitter will be +disabled. +=> ATMEL_US_USMODE_HWHS flag can be set for this platform ONLY IF the +CTS pin is not a GPIO. + +So, the only case when ATMEL_US_USMODE_HWHS can be enabled is when +(atmel_use_fifo(port) && + !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) + +Tested on all Atmel USART controller flavours: +AT91SAM9G35-CM (DMAC flavour), AT91SAM9G20-EK (PDC flavour), +SAMA5D2xplained (FIFO flavour). + +* the list may not be exhaustive + +Fixes: 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when hardware handshake is enabled") +Signed-off-by: Richard Genoud +Acked-by: Alexandre Belloni +Acked-by: Cyrille Pitchen +Acked-by: Uwe Kleine-König +[nicolas.ferre@atmel.com: adapt to 4.4.x kernel for stable by adding +the atmel_port variable declaration which was missing] +Signed-off-by: Nicolas Ferre +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/atmel_serial.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -2026,6 +2026,7 @@ static void atmel_serial_pm(struct uart_ + static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) + { ++ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + unsigned long flags; + unsigned int old_mode, mode, imr, quot, baud; + +@@ -2129,11 +2130,29 @@ static void atmel_set_termios(struct uar + mode |= ATMEL_US_USMODE_RS485; + } else if (termios->c_cflag & CRTSCTS) { + /* RS232 with hardware handshake (RTS/CTS) */ +- if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) { +- dev_info(port->dev, "not enabling hardware flow control because DMA is used"); +- termios->c_cflag &= ~CRTSCTS; +- } else { ++ if (atmel_use_fifo(port) && ++ !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) { ++ /* ++ * with ATMEL_US_USMODE_HWHS set, the controller will ++ * be able to drive the RTS pin high/low when the RX ++ * FIFO is above RXFTHRES/below RXFTHRES2. ++ * It will also disable the transmitter when the CTS ++ * pin is high. ++ * This mode is not activated if CTS pin is a GPIO ++ * because in this case, the transmitter is always ++ * disabled (there must be an internal pull-up ++ * responsible for this behaviour). ++ * If the RTS pin is a GPIO, the controller won't be ++ * able to drive it according to the FIFO thresholds, ++ * but it will be handled by the driver. ++ */ + mode |= ATMEL_US_USMODE_HWHS; ++ } else { ++ /* ++ * For platforms without FIFO, the flow control is ++ * handled by the driver. ++ */ ++ mode |= ATMEL_US_USMODE_NORMAL; + } + } else { + /* RS232 without hadware handshake */