diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-06-15 10:00:14 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-06-19 15:12:57 +1000 |
commit | 35b433b79bb41f2cdb45e18ea1d20d326fefb344 (patch) | |
tree | b029d8bb3476d29bc2dcc3de7ce7f691eba61cf3 /hw/lpc-uart.c | |
parent | a921764eed0a38670cacc47fa3aa9d5e87e1ab6b (diff) | |
download | skiboot-35b433b79bb41f2cdb45e18ea1d20d326fefb344.zip skiboot-35b433b79bb41f2cdb45e18ea1d20d326fefb344.tar.gz skiboot-35b433b79bb41f2cdb45e18ea1d20d326fefb344.tar.bz2 |
Support for Naples LPC serial interrupts
This adds support for the HW SerIRQ deserializer of the P8 LPC
bridge which is properly wired up on Naples. It also adds support
for detecting and reporting LPC error interrupts on all P8s.
On most platforms (Rhesus is the exception here due to the way it
lets Linux handle the UART interrupts directly), we modify the
device-tree to properly represent the LPC controller as a cascaded
interrupt-controller and the "interrupts" property of LPC devices
to contain the actual LPC interrupt number for the device.
We add a mechanism for drivers to register specific LPC interrupts,
and a "workaround" for pre-Naples P8 which platforms can use to call
all of them for when the external FPGA based deserializer is used.
There's also a callback on LPC resets which isn't used yet, we need
a bit more work on the general LPC error handling, but it can be
done a separate patches.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/lpc-uart.c')
-rw-r--r-- | hw/lpc-uart.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index 7c3190e..a4c0086 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -25,6 +25,7 @@ #include <trace.h> #include <timebase.h> #include <cpu.h> +#include <chip.h> DEFINE_LOG_ENTRY(OPAL_RC_UART_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_UART, OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL, @@ -365,7 +366,7 @@ static void uart_console_poll(void *data __unused) __uart_do_poll(TRACE_UART_CTX_POLL); } -void uart_irq(void) +static void uart_irq(uint32_t chip_id __unused, uint32_t irq_mask __unused) { if (!irq_ok) { prlog(PR_DEBUG, "UART: IRQ functional !\n"); @@ -464,12 +465,16 @@ static bool uart_init_hw(unsigned int speed, unsigned int clock) return false; } -void uart_init(bool enable_interrupt) +static struct lpc_client uart_lpc_client = { + .interrupt = uart_irq, +}; + +void uart_init(bool use_interrupt) { const struct dt_property *prop; struct dt_node *n; char *path __unused; - uint32_t irqchip, irq; + uint32_t chip_id, irq; if (!lpc_present()) return; @@ -504,6 +509,7 @@ void uart_init(bool enable_interrupt) dt_add_property_strings(n, "status", "bad"); return; } + chip_id = dt_get_chip_id(uart_node); /* * Mark LPC used by the console (will mark the relevant @@ -514,13 +520,16 @@ void uart_init(bool enable_interrupt) /* Install console backend for printf() */ set_console(&uart_con_driver); - /* Setup the interrupts properties since HB couldn't do it */ - irqchip = dt_prop_get_u32(n, "ibm,irq-chip-id"); - irq = get_psi_interrupt(irqchip) + P8_IRQ_PSI_HOST_ERR; - prlog(PR_DEBUG, "UART: IRQ connected to chip %d, irq# is 0x%x\n", irqchip, irq); - has_irq = enable_interrupt; - if (has_irq) { - dt_add_property_cells(n, "interrupts", irq); - dt_add_property_cells(n, "interrupt-parent", get_ics_phandle()); - } + /* On Naples, use the SerIRQ, which Linux will have to share with + * OPAL as we don't really play the cascaded interrupt game at this + * point... + */ + if (use_interrupt) { + irq = dt_prop_get_u32(n, "interrupts"); + uart_lpc_client.interrupts = LPC_IRQ(irq); + lpc_register_client(chip_id, &uart_lpc_client); + has_irq = true; + prlog(PR_DEBUG, "UART: Using LPC IRQ %d\n", irq); + } else + has_irq = false; } |