diff options
author | Simon Goldschmidt | 2018-08-09 14:04:19 -0500 |
---|---|---|
committer | Simon Glass | 2018-11-14 11:16:28 -0600 |
commit | 6f57c34473d37b8da5e6a3764d0d377d748aeef1 (patch) | |
tree | d6ab8dab8076d0dc5e7f7ad64b7d8dfb9be7a025 | |
parent | 81f351d6e7ebb371de8ea849fc21dd07dc2eff24 (diff) | |
download | u-boot-6f57c34473d37b8da5e6a3764d0d377d748aeef1.tar.gz u-boot-6f57c34473d37b8da5e6a3764d0d377d748aeef1.tar.xz u-boot-6f57c34473d37b8da5e6a3764d0d377d748aeef1.zip |
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 <simon.k.r.goldschmidt@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | drivers/serial/ns16550.c | 18 |
1 files changed, 16 insertions, 2 deletions
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) | |||
267 | serial_dout(&com_port->lcr, UART_LCRVAL); | 267 | serial_dout(&com_port->lcr, UART_LCRVAL); |
268 | } | 268 | } |
269 | 269 | ||
270 | static inline int NS16550_read_baud_divisor(struct NS16550 *com_port) | ||
271 | { | ||
272 | int ret; | ||
273 | |||
274 | serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); | ||
275 | ret = serial_din(&com_port->dll) & 0xff; | ||
276 | ret |= (serial_din(&com_port->dlm) & 0xff) << 8; | ||
277 | serial_dout(&com_port->lcr, UART_LCRVAL); | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
270 | static inline void _debug_uart_putc(int ch) | 282 | static inline void _debug_uart_putc(int ch) |
271 | { | 283 | { |
272 | struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; | 284 | struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; |
273 | 285 | ||
274 | while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) | 286 | while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) { |
275 | ; | 287 | if (!NS16550_read_baud_divisor(com_port)) |
288 | return; | ||
289 | } | ||
276 | serial_dout(&com_port->thr, ch); | 290 | serial_dout(&com_port->thr, ch); |
277 | } | 291 | } |
278 | 292 | ||