From 5541a9bacfe54fb2038531fb276724fcec6c29c4 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 12 May 2021 16:12:51 +0200 Subject: serial: fsl_lpuart: handle break and make sysrq work Although there is already sysrq characters handling, a break condition was never detected. Add support for it. The LPUART can't distinguish between a framing error and a break condition. We assume it is a break if the received data is all zero. Signed-off-by: Michael Walle Link: https://lore.kernel.org/r/20210512141255.18277-6-michael@walle.cc Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 72caa7a193a8..baa96e61ab14 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -910,6 +910,7 @@ static void lpuart32_rxint(struct lpuart_port *sport) unsigned int flg, ignored = 0; struct tty_port *port = &sport->port.state->port; unsigned long rx, sr; + bool is_break; spin_lock(&sport->port.lock); @@ -924,14 +925,27 @@ static void lpuart32_rxint(struct lpuart_port *sport) rx = lpuart32_read(&sport->port, UARTDATA); rx &= UARTDATA_MASK; + /* + * The LPUART can't distinguish between a break and a framing error, + * thus we assume it is a break if the received data is zero. + */ + is_break = (sr & UARTSTAT_FE) && !rx; + + if (is_break && uart_handle_break(&sport->port)) + continue; + if (uart_prepare_sysrq_char(&sport->port, rx)) continue; if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) { - if (sr & UARTSTAT_PE) - sport->port.icount.parity++; - else if (sr & UARTSTAT_FE) + if (sr & UARTSTAT_PE) { + if (is_break) + sport->port.icount.brk++; + else + sport->port.icount.parity++; + } else if (sr & UARTSTAT_FE) { sport->port.icount.frame++; + } if (sr & UARTSTAT_OR) sport->port.icount.overrun++; @@ -944,15 +958,17 @@ static void lpuart32_rxint(struct lpuart_port *sport) sr &= sport->port.read_status_mask; - if (sr & UARTSTAT_PE) - flg = TTY_PARITY; - else if (sr & UARTSTAT_FE) + if (sr & UARTSTAT_PE) { + if (is_break) + flg = TTY_BREAK; + else + flg = TTY_PARITY; + } else if (sr & UARTSTAT_FE) { flg = TTY_FRAME; + } if (sr & UARTSTAT_OR) flg = TTY_OVERRUN; - - sport->port.sysrq = 0; } tty_insert_flip_char(port, rx, flg); -- cgit v1.2.3-59-g8ed1b