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

Reply via email to