mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 23:54:04 +08:00
tty: serial: fsl_lpuart: use UARTCTRL_TXINV to send break instead of UARTCTRL_SBK
LPUART IP now has two known bugs, one is that CTS has higher priority than the break signal, which causes the break signal sending through UARTCTRL_SBK may impacted by the CTS input if the HW flow control is enabled. It exists on all platforms we support in this driver. So we add a workaround patch for this issue: commitc4c81db5cf
("tty: serial: fsl_lpuart: disable the CTS when send break signal"). Another IP bug is i.MX8QM LPUART may have an additional break character being sent after SBK was cleared. It may need to add some delay between clearing SBK and re-enabling CTS to ensure that the SBK latch are completely cleared. But we found that during the delay period before CTS is enabled, there is still a risk that Bluetooth data in TX FIFO may be sent out during this period because of break off and CTS disabled(even if BT sets CTS line deasserted, data is still sent to BT). Due to this risk, we have to drop the CTS-disabling workaround for SBK bugs, use TXINV seems to be a better way to replace SBK feature and avoid above risk. Also need to disable the transmitter to prevent any data from being sent out during break, then invert the TX line to send break. Then disable the TXINV when turn off break and re-enable transmitter. Fixes:c4c81db5cf
("tty: serial: fsl_lpuart: disable the CTS when send break signal") Cc: stable <stable@kernel.org> Signed-off-by: Sherry Sun <sherry.sun@nxp.com> Link: https://lore.kernel.org/r/20230519094751.28948-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
134f49dec0
commit
2474e05467
@ -1495,34 +1495,36 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
|
||||
|
||||
static void lpuart32_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long temp, modem;
|
||||
struct tty_struct *tty;
|
||||
unsigned int cflag = 0;
|
||||
unsigned long temp;
|
||||
|
||||
tty = tty_port_tty_get(&port->state->port);
|
||||
if (tty) {
|
||||
cflag = tty->termios.c_cflag;
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
temp = lpuart32_read(port, UARTCTRL) & ~UARTCTRL_SBK;
|
||||
modem = lpuart32_read(port, UARTMODIR);
|
||||
temp = lpuart32_read(port, UARTCTRL);
|
||||
|
||||
/*
|
||||
* LPUART IP now has two known bugs, one is CTS has higher priority than the
|
||||
* break signal, which causes the break signal sending through UARTCTRL_SBK
|
||||
* may impacted by the CTS input if the HW flow control is enabled. It
|
||||
* exists on all platforms we support in this driver.
|
||||
* Another bug is i.MX8QM LPUART may have an additional break character
|
||||
* being sent after SBK was cleared.
|
||||
* To avoid above two bugs, we use Transmit Data Inversion function to send
|
||||
* the break signal instead of UARTCTRL_SBK.
|
||||
*/
|
||||
if (break_state != 0) {
|
||||
temp |= UARTCTRL_SBK;
|
||||
/*
|
||||
* LPUART CTS has higher priority than SBK, need to disable CTS before
|
||||
* asserting SBK to avoid any interference if flow control is enabled.
|
||||
* Disable the transmitter to prevent any data from being sent out
|
||||
* during break, then invert the TX line to send break.
|
||||
*/
|
||||
if (cflag & CRTSCTS && modem & UARTMODIR_TXCTSE)
|
||||
lpuart32_write(port, modem & ~UARTMODIR_TXCTSE, UARTMODIR);
|
||||
temp &= ~UARTCTRL_TE;
|
||||
lpuart32_write(port, temp, UARTCTRL);
|
||||
temp |= UARTCTRL_TXINV;
|
||||
lpuart32_write(port, temp, UARTCTRL);
|
||||
} else {
|
||||
/* Re-enable the CTS when break off. */
|
||||
if (cflag & CRTSCTS && !(modem & UARTMODIR_TXCTSE))
|
||||
lpuart32_write(port, modem | UARTMODIR_TXCTSE, UARTMODIR);
|
||||
/* Disable the TXINV to turn off break and re-enable transmitter. */
|
||||
temp &= ~UARTCTRL_TXINV;
|
||||
lpuart32_write(port, temp, UARTCTRL);
|
||||
temp |= UARTCTRL_TE;
|
||||
lpuart32_write(port, temp, UARTCTRL);
|
||||
}
|
||||
|
||||
lpuart32_write(port, temp, UARTCTRL);
|
||||
}
|
||||
|
||||
static void lpuart_setup_watermark(struct lpuart_port *sport)
|
||||
|
Loading…
Reference in New Issue
Block a user