From: Mehmet Fide <[email protected]>
On the 8 bit register variant, the only user of which is fsl,vf610-lpuart,
_lpuart_serial_init() disables the FIFO:
/* Disable FIFO and flush buffer */
__raw_writeb(0x0, &base->upfifo);
while _lpuart_serial_tstc() asks the receive FIFO counter whether a
character arrived:
if (__raw_readb(&base->urcfifo) == 0)
return 0;
With the FIFO disabled the dataword lands in the data register and raises
S1[RDRF], but RCFIFO stays zero, so tstc() never reports a character. The
console is then output only: autoboot cannot be interrupted, ctrlc() never
fires, and anything polling for a key waits forever.
_lpuart_serial_getc() in the same driver already tests S1, and the 32 bit
variant enables its FIFO in _lpuart32_serial_init() before reading the
RXCOUNT field of WATER, so only this path is inconsistent. Test S1 the way
getc() does.
Tested on a Colibri VF50: U-Boot printed its whole log over UART0 but
accepted no input at all, neither a key during the boot delay nor Ctrl-C
during a sleep, while Linux received on the same pads with the same pin
mux. With the fix the boot delay can be interrupted, including with
bootdelay=0, where the key is already buffered when abortboot_single_key()
checks.
Signed-off-by: Mehmet Fide <[email protected]>
---
drivers/serial/serial_lpuart.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 9fdb6503085..9c02b3a77ca 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -198,10 +198,11 @@ static int _lpuart_serial_tstc(struct lpuart_serial_plat
*plat)
{
struct lpuart_fsl *base = plat->reg;
- if (__raw_readb(&base->urcfifo) == 0)
- return 0;
-
- return 1;
+ /*
+ * The receive FIFO counter stays at zero because _lpuart_serial_init()
+ * disables the FIFO, so ask the status register, the way getc() does.
+ */
+ return __raw_readb(&base->us1) & (US1_RDRF | US1_OR) ? 1 : 0;
}
/*
--
2.54.0