From: Simon Goldschmidt Date: Thu, 9 Aug 2018 19:04:19 +0000 (+0200) Subject: serial: ns16550: fix debug uart putc called before init X-Git-Tag: v2019.01-rc1~33^2~16 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6f57c34473d37b8da5e6a3764d0d377d748aeef1;p=oweals%2Fu-boot.git serial: ns16550: fix debug uart putc called before init If _debug_uart_putc() is called before _debug_uart_init(), the ns16550 debug uart driver hangs in a tight loop waiting for the tx FIFO to get empty. As this can happen via a printf sneaking in before the port calls debug_uart_init(), let's rather ignore characters before the debug uart is initialized. This is done by reading the baudrate divisor and aborting if is zero. Tested on socfpga_cyclone5_socrates. Signed-off-by: Simon Goldschmidt Acked-by: Simon Glass --- diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index f9041aa626..04b604fa2c 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -267,12 +267,26 @@ static inline void _debug_uart_init(void) serial_dout(&com_port->lcr, UART_LCRVAL); } +static inline int NS16550_read_baud_divisor(struct NS16550 *com_port) +{ + int ret; + + serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); + ret = serial_din(&com_port->dll) & 0xff; + ret |= (serial_din(&com_port->dlm) & 0xff) << 8; + serial_dout(&com_port->lcr, UART_LCRVAL); + + return ret; +} + static inline void _debug_uart_putc(int ch) { struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; - while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) - ; + while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) { + if (!NS16550_read_baud_divisor(com_port)) + return; + } serial_dout(&com_port->thr, ch); }