The current SCIF error handling is broken for the RZ/G2L. After a break
condition has been triggered, the current code is unable to clear the
error and serial port output never resumes.
The RZ/G2L datasheet says that most error conditions are cleared by
resetting the relevant error bits in the FSR & LSR registers to zero.
To clear framing errors on SCIF ports, the invalid data also needs to be
read out of the receive FIFO.
After reviewing datasheets for RZ/G2{H,M,N,E}, R-Car Gen4, R-Car Gen3
and even SH7751 SoCs, it's clear that this is the way to clear errors
for all of these SoCs.
While we're here, annotate the handle_error() function with a couple of
comments as the reads and writes themselves don't immediately make it
clear what we're doing.
Signed-off-by: Paul Barker <paul.barker.ct@bp.renesas.com>
Tested-by: Chris Paterson <chris.paterson2@renesas.com> # HiHope RZ/G2M board
Tested-by: Marek Vasut <marek.vasut+renesas@mailbox.org> # R-Car H3 Salvator-XS
static void handle_error(struct uart_port *port)
{
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ /*
+ * Most errors are cleared by resetting the relevant error bits to zero
+ * in the FSR & LSR registers. For each register, a read followed by a
+ * write is needed according to the relevant datasheets.
+ */
+ unsigned short status = sci_in(port, SCxSR);
+ sci_out(port, SCxSR, status & ~SCxSR_ERRORS(port));
sci_in(port, SCLSR);
sci_out(port, SCLSR, 0x00);
+
+ /*
+ * To clear framing errors, we also need to read and discard a
+ * character.
+ */
+ if ((port->type != PORT_SCI) && (status & SCIF_FER))
+ sci_in(port, SCxRDR);
}
static int serial_raw_putc(struct uart_port *port, const char c)