Skip to content

Commit c4c81db

Browse files
SherrySun5gregkh
authored andcommitted
tty: serial: fsl_lpuart: disable the CTS when send break signal
LPUART IP has a bug that it treats the CTS as higher priority than the break signal, which cause the break signal sending through UARTCTRL_SBK may impacted by the CTS input if the HW flow control is enabled. Add this workaround patch to fix the IP bug, we can disable CTS before asserting SBK to avoid any interference from CTS, and re-enable it when break off. Such as for the bluetooth chip power save feature, host can let the BT chip get into sleep state by sending a UART break signal, and wake it up by turning off the UART break. If the BT chip enters the sleep mode successfully, it will pull up the CTS line, if the BT chip is woken up, it will pull down the CTS line. If without this workaround patch, the UART TX pin cannot send the break signal successfully as it affected by the BT CTS pin. After adding this patch, the BT power save feature can work well. Signed-off-by: Sherry Sun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4029dfc commit c4c81db

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

drivers/tty/serial/fsl_lpuart.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,12 +1464,32 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
14641464

14651465
static void lpuart32_break_ctl(struct uart_port *port, int break_state)
14661466
{
1467-
unsigned long temp;
1467+
unsigned long temp, modem;
1468+
struct tty_struct *tty;
1469+
unsigned int cflag = 0;
1470+
1471+
tty = tty_port_tty_get(&port->state->port);
1472+
if (tty) {
1473+
cflag = tty->termios.c_cflag;
1474+
tty_kref_put(tty);
1475+
}
14681476

14691477
temp = lpuart32_read(port, UARTCTRL) & ~UARTCTRL_SBK;
1478+
modem = lpuart32_read(port, UARTMODIR);
14701479

1471-
if (break_state != 0)
1480+
if (break_state != 0) {
14721481
temp |= UARTCTRL_SBK;
1482+
/*
1483+
* LPUART CTS has higher priority than SBK, need to disable CTS before
1484+
* asserting SBK to avoid any interference if flow control is enabled.
1485+
*/
1486+
if (cflag & CRTSCTS && modem & UARTMODIR_TXCTSE)
1487+
lpuart32_write(port, modem & ~UARTMODIR_TXCTSE, UARTMODIR);
1488+
} else {
1489+
/* Re-enable the CTS when break off. */
1490+
if (cflag & CRTSCTS && !(modem & UARTMODIR_TXCTSE))
1491+
lpuart32_write(port, modem | UARTMODIR_TXCTSE, UARTMODIR);
1492+
}
14731493

14741494
lpuart32_write(port, temp, UARTCTRL);
14751495
}

0 commit comments

Comments
 (0)