From 4d4e25f2ef77bbbeca9050596b7cecf89ec89e78 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 13 Oct 2014 11:14:34 +1100 Subject: uart: Keep synchronous console flush when IRQ not working Some boards are missing an EC for interrupts (or might not have the FPGA properly flashed). In that case the serial interrupt isn't working. We attempt to detect this by enabling all interrupts by default and when the first one occurs, we mark interrupts as "functional". Until they are detected as such, we keep all output flushes fully synchronous. Signed-off-by: Benjamin Herrenschmidt --- hw/lpc-uart.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'hw/lpc-uart.c') diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index 51f744d..7f0909a 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -57,11 +57,12 @@ DEFINE_LOG_ENTRY(OPAL_RC_UART_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_UART, #define IER_RX 0x01 #define IER_THRE 0x02 +#define IER_ALL 0x0f static struct lock uart_lock = LOCK_UNLOCKED; static struct dt_node *uart_node; static uint32_t uart_base; -static bool has_irq, rx_full, tx_full; +static bool has_irq, irq_ok, rx_full, tx_full; static uint8_t tx_room; static uint8_t cached_ier; @@ -110,6 +111,13 @@ static void uart_update_ier(void) if (!has_irq) return; + /* If we have never got an interrupt, enable them all, + * the first interrupt received will tell us if interrupts + * are functional (some boards are missing an EC or FPGA + * programming causing LPC interrupts not to work). + */ + if (!irq_ok) + ier = IER_ALL; if (!rx_full) ier |= IER_RX; if (tx_full) @@ -182,8 +190,18 @@ static void uart_flush_out(void) bool tx_was_full = tx_full; while(out_buf_prod != out_buf_cons) { - if (tx_room == 0) - uart_check_tx_room(); + if (tx_room == 0) { + /* + * If the interrupt is not functional, + * we force a full synchronous flush, + * otherwise the Linux console isn't + * usable (too slow). + */ + if (irq_ok) + uart_check_tx_room(); + else + uart_wait_tx_room(); + } if (tx_room == 0) { tx_full = true; break; @@ -345,6 +363,10 @@ static void uart_console_poll(void *data __unused) void uart_irq(void) { + if (!irq_ok) { + printf("UART: IRQ functional !\n"); + irq_ok = true; + } __uart_do_poll(TRACE_UART_CTX_IRQ); } -- cgit v1.1