| From c7614ff9b73a1e6fb2b1b51396da132ed22fecdb Mon Sep 17 00:00:00 2001 |
| From: Brant Merryman <brant.merryman@silabs.com> |
| Date: Fri, 26 Jun 2020 04:24:20 +0000 |
| Subject: USB: serial: cp210x: re-enable auto-RTS on open |
| |
| From: Brant Merryman <brant.merryman@silabs.com> |
| |
| commit c7614ff9b73a1e6fb2b1b51396da132ed22fecdb upstream. |
| |
| CP210x hardware disables auto-RTS but leaves auto-CTS when in hardware |
| flow control mode and UART on cp210x hardware is disabled. When |
| re-opening the port, if auto-CTS is enabled on the cp210x, then auto-RTS |
| must be re-enabled in the driver. |
| |
| Signed-off-by: Brant Merryman <brant.merryman@silabs.com> |
| Co-developed-by: Phu Luu <phu.luu@silabs.com> |
| Signed-off-by: Phu Luu <phu.luu@silabs.com> |
| Link: https://lore.kernel.org/r/ECCF8E73-91F3-4080-BE17-1714BC8818FB@silabs.com |
| [ johan: fix up tags and problem description ] |
| Fixes: 39a66b8d22a3 ("[PATCH] USB: CP2101 Add support for flow control") |
| Cc: stable <stable@vger.kernel.org> # 2.6.12 |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/serial/cp210x.c | 17 +++++++++++++++++ |
| 1 file changed, 17 insertions(+) |
| |
| --- a/drivers/usb/serial/cp210x.c |
| +++ b/drivers/usb/serial/cp210x.c |
| @@ -915,6 +915,7 @@ static void cp210x_get_termios_port(stru |
| u32 baud; |
| u16 bits; |
| u32 ctl_hs; |
| + u32 flow_repl; |
| |
| cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud); |
| |
| @@ -1015,6 +1016,22 @@ static void cp210x_get_termios_port(stru |
| ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); |
| if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) { |
| dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); |
| + /* |
| + * When the port is closed, the CP210x hardware disables |
| + * auto-RTS and RTS is deasserted but it leaves auto-CTS when |
| + * in hardware flow control mode. When re-opening the port, if |
| + * auto-CTS is enabled on the cp210x, then auto-RTS must be |
| + * re-enabled in the driver. |
| + */ |
| + flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace); |
| + flow_repl &= ~CP210X_SERIAL_RTS_MASK; |
| + flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL); |
| + flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl); |
| + cp210x_write_reg_block(port, |
| + CP210X_SET_FLOW, |
| + &flow_ctl, |
| + sizeof(flow_ctl)); |
| + |
| cflag |= CRTSCTS; |
| } else { |
| dev_dbg(dev, "%s - flow control = NONE\n", __func__); |