[PATCH 1/2] tty: serial: lpuart: deassert RTS while reconfiguring in set_termios()

From: Sherry Sun (OSS)

Date: Wed Oct 21 2026 - 23:14:07 EST


From: Sherry Sun <sherry.sun@xxxxxxx>

Commit e98ab45ec518 ("tty: serial: lpuart: only disable CTS instead of
overwriting the whole UARTMODIR register") replaced the write of 0 to
UARTMODIR before waiting for the transmission complete flag with a
write that only masks TXCTSE. As a side effect RXRTSE is no longer
cleared there, and when CRTSCTS is requested that write even sets it
while the receiver is still enabled.

RTS therefore keeps following the receiver FIFO level during the whole
reconfiguration, so the remote side may keep sending, or start sending,
right before set_termios() disables the receiver and reprograms the
baud rate. The characters in flight are then lost or corrupted, and a
short RTS pulse can be observed on the line.

Mask RXRTSE in that first write as well, so that RTS is deasserted and
the remote side is asked to stop sending before the receiver is
disabled. The final write of the modem value restores both RXRTSE and
TXCTSE as requested by termios, and the other UARTMODIR fields are still
preserved.

Fixes: e98ab45ec518 ("tty: serial: lpuart: only disable CTS instead of overwriting the whole UARTMODIR register")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Sherry Sun <sherry.sun@xxxxxxx>
---
drivers/tty/serial/fsl_lpuart.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index c8575c965203..70b69870aaba 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2360,9 +2360,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,

/*
* disable CTS to ensure the transmit engine is not blocked by the flow
- * control when there is dirty data in TX FIFO
+ * control when there is dirty data in TX FIFO, and deassert RTS to ask
+ * the remote to stop sending before the receiver is disabled and the
+ * baud rate is changed below
*/
- lpuart32_write(port, modem & ~UARTMODIR_TXCTSE, UARTMODIR);
+ lpuart32_write(port, modem & ~(UARTMODIR_TXCTSE | UARTMODIR_RXRTSE),
+ UARTMODIR);

/*
* LPUART Transmission Complete Flag may never be set while queuing a break
@@ -2380,7 +2383,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_serial_setbrg(sport, baud);
/* restore control register */
lpuart32_write(port, ctrl, UARTCTRL);
- /* re-enable the CTS if needed */
+ /* re-enable the CTS/RTS if needed */
lpuart32_write(port, modem, UARTMODIR);

if ((ctrl & (UARTCTRL_PE | UARTCTRL_M)) == UARTCTRL_PE)

--
2.50.1