3ff77bcea97d45b0fb1a7bc1379a8688b0b3ba45
[openwrt/staging/rmilecki.git] / target / linux / bcm27xx / patches-5.4 / 950-0741-sc16is7xx-Fix-for-hardware-flow-control.patch
1 From 41ed4262b7398a3170399af81cf78cb8d7dd8b8d Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Wed, 13 May 2020 20:10:15 +0100
4 Subject: [PATCH] sc16is7xx: Fix for hardware flow control
5
6 The SC16IS7XX hardware flow control is mishandled by the driver in
7 a number of ways:
8
9 1. The set_baud method accidentally clears it when setting EFR bit.
10 2. Even though hardware flow control is enabled, it isn't indicated
11 back to the serial framework.
12 3. Applying the flow control clears the EFR bit.
13 4. The CTS support is not indicated in the return from
14 sc16is7xx_get_mctrl.
15
16 Address all of those issues using a mixture of patches found on the
17 linked pages.
18
19 See: https://github.com/raspberrypi/linux/issues/2542
20 See: https://www.spinics.net/lists/linux-serial/msg21794.html
21
22 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
23 ---
24 drivers/tty/serial/sc16is7xx.c | 14 ++++++++++----
25 1 file changed, 10 insertions(+), 4 deletions(-)
26
27 --- a/drivers/tty/serial/sc16is7xx.c
28 +++ b/drivers/tty/serial/sc16is7xx.c
29 @@ -523,8 +523,9 @@ static int sc16is7xx_set_baud(struct uar
30
31 /* Enable enhanced features */
32 regcache_cache_bypass(s->regmap, true);
33 - sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
34 - SC16IS7XX_EFR_ENABLE_BIT);
35 + sc16is7xx_port_update(port, SC16IS7XX_EFR_REG,
36 + SC16IS7XX_EFR_ENABLE_BIT,
37 + SC16IS7XX_EFR_ENABLE_BIT);
38 regcache_cache_bypass(s->regmap, false);
39
40 /* Put LCR back to the normal mode */
41 @@ -846,7 +847,7 @@ static unsigned int sc16is7xx_get_mctrl(
42 /* DCD and DSR are not wired and CTS/RTS is handled automatically
43 * so just indicate DSR and CAR asserted
44 */
45 - return TIOCM_DSR | TIOCM_CAR;
46 + return TIOCM_DSR | TIOCM_CAR | TIOCM_RI | TIOCM_CTS;
47 }
48
49 static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
50 @@ -933,14 +934,19 @@ static void sc16is7xx_set_termios(struct
51 regcache_cache_bypass(s->regmap, true);
52 sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]);
53 sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]);
54 - if (termios->c_cflag & CRTSCTS)
55 + if (termios->c_cflag & CRTSCTS) {
56 flow |= SC16IS7XX_EFR_AUTOCTS_BIT |
57 SC16IS7XX_EFR_AUTORTS_BIT;
58 + port->status |= UPSTAT_AUTOCTS;
59 + };
60 if (termios->c_iflag & IXON)
61 flow |= SC16IS7XX_EFR_SWFLOW3_BIT;
62 if (termios->c_iflag & IXOFF)
63 flow |= SC16IS7XX_EFR_SWFLOW1_BIT;
64
65 + /* Always set enable enhanced */
66 + flow |= SC16IS7XX_EFR_ENABLE_BIT;
67 +
68 sc16is7xx_port_write(port, SC16IS7XX_EFR_REG, flow);
69 regcache_cache_bypass(s->regmap, false);
70