Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: serial: ch341: add hardware flow control RTS/CTS

This adds support for enabling and disabling RTS/CTS hardware flow
control.

Tested using CH341A and CH340E.

Fixes part of the following bug report:
Link: https://bugzilla.kernel.org/show_bug.cgi?id=197109

Signed-off-by: Lode Willems <me@lodewillems.com>
[ johan: prepare index argument once, drop casts ]
Signed-off-by: Johan Hovold <johan@kernel.org>

authored by

Lode Willems and committed by
Johan Hovold
35478bc3 4bbf9020

+28
+28
drivers/usb/serial/ch341.c
··· 63 63 #define CH341_REG_DIVISOR 0x13 64 64 #define CH341_REG_LCR 0x18 65 65 #define CH341_REG_LCR2 0x25 66 + #define CH341_REG_FLOW_CTL 0x27 66 67 67 68 #define CH341_NBREAK_BITS 0x01 68 69 ··· 77 76 #define CH341_LCR_CS7 0x02 78 77 #define CH341_LCR_CS6 0x01 79 78 #define CH341_LCR_CS5 0x00 79 + 80 + #define CH341_FLOW_CTL_NONE 0x00 81 + #define CH341_FLOW_CTL_RTSCTS 0x01 80 82 81 83 #define CH341_QUIRK_LIMITED_PRESCALER BIT(0) 82 84 #define CH341_QUIRK_SIMULATE_BREAK BIT(1) ··· 482 478 return r; 483 479 } 484 480 481 + static void ch341_set_flow_control(struct tty_struct *tty, 482 + struct usb_serial_port *port, 483 + const struct ktermios *old_termios) 484 + { 485 + u16 flow_ctl; 486 + int r; 487 + 488 + if (C_CRTSCTS(tty)) 489 + flow_ctl = CH341_FLOW_CTL_RTSCTS; 490 + else 491 + flow_ctl = CH341_FLOW_CTL_NONE; 492 + 493 + r = ch341_control_out(port->serial->dev, 494 + CH341_REQ_WRITE_REG, 495 + (CH341_REG_FLOW_CTL << 8) | CH341_REG_FLOW_CTL, 496 + (flow_ctl << 8) | flow_ctl); 497 + if (r < 0 && old_termios) { 498 + tty->termios.c_cflag &= ~CRTSCTS; 499 + tty->termios.c_cflag |= (old_termios->c_cflag & CRTSCTS); 500 + } 501 + } 502 + 485 503 /* Old_termios contains the original termios settings and 486 504 * tty->termios contains the new setting to be used. 487 505 */ ··· 572 546 spin_unlock_irqrestore(&priv->lock, flags); 573 547 574 548 ch341_set_handshake(port->serial->dev, priv->mcr); 549 + 550 + ch341_set_flow_control(tty, port, old_termios); 575 551 } 576 552 577 553 /*