diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-02-03 20:51:59 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-03-03 09:40:40 +1100 |
commit | a2940770ca6da2c58081f8207aded197e45f6cd6 (patch) | |
tree | f51be7c9dbe321fa6a270d88b502bf70269c6f9d /hw/psi.c | |
parent | 95c59d192376a4360278393da5df53e21ae3fc72 (diff) | |
download | skiboot-a2940770ca6da2c58081f8207aded197e45f6cd6.zip skiboot-a2940770ca6da2c58081f8207aded197e45f6cd6.tar.gz skiboot-a2940770ca6da2c58081f8207aded197e45f6cd6.tar.bz2 |
lpc/uart: Support routing of selected LPC interrupts to Linux
Each LPC interrupt can be routed to one of 4 lines to the PSI
bridge which represent 4 different system interrupts. This
allows LPC clients to request as specific target (Linux or OPAL)
and makes the LPC core pick a route and configure it appropriately.
The UART is updated to properly forward interrupts to Linux
if necessary
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/psi.c')
-rw-r--r-- | hw/psi.c | 24 |
1 files changed, 16 insertions, 8 deletions
@@ -613,21 +613,26 @@ static uint64_t psi_p9_irq_attributes(struct irq_source *is __unused, { struct psi *psi = is->data; unsigned int idx = isn & 0xf; + bool is_lpc_serirq; + + is_lpc_serirq = + (idx == P9_PSI_IRQ_LPC_SIRQ0 || + idx == P9_PSI_IRQ_LPC_SIRQ1 || + idx == P9_PSI_IRQ_LPC_SIRQ2 || + idx == P9_PSI_IRQ_LPC_SIRQ3); /* If LPC interrupts are disabled, route them to Linux * (who will not request them since they aren't referenced * in the device tree) */ - if (psi->no_lpc_irqs && - (idx == P9_PSI_IRQ_LPC_SIRQ0 || - idx == P9_PSI_IRQ_LPC_SIRQ1 || - idx == P9_PSI_IRQ_LPC_SIRQ2 || - idx == P9_PSI_IRQ_LPC_SIRQ3 || - idx == P9_PSI_IRQ_LPCHC)) + if (is_lpc_serirq && psi->no_lpc_irqs) return IRQ_ATTR_TARGET_LINUX; - /* XXX For now, all go to OPAL, this will change */ - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_FREQUENT; + /* For serirq, check the LPC layer for policy */ + if (is_lpc_serirq) + return lpc_get_irq_policy(psi->chip_id, idx - P9_PSI_IRQ_LPC_SIRQ0); + + return IRQ_ATTR_TARGET_OPAL; } static char *psi_p9_irq_name(struct irq_source *is, uint32_t isn) @@ -940,6 +945,8 @@ static void psi_create_p9_int_map(struct psi *psi, struct dt_node *np) map[i][3] = 1; } dt_add_property(np, "interrupt-map", map, sizeof(map)); + dt_add_property_cells(np, "#address-cells", 0); + dt_add_property_cells(np, "#interrupt-cells", 1); } static void psi_create_mm_dtnode(struct psi *psi) @@ -973,6 +980,7 @@ static void psi_create_mm_dtnode(struct psi *psi) dt_add_property_cells(np, "interrupt-parent", get_ics_phandle()); dt_add_property_cells(np, "interrupts", psi->interrupt, 1); dt_add_property_cells(np, "ibm,chip-id", psi->chip_id); + psi->node = np; } static struct psi *alloc_psi(struct proc_chip *chip, uint64_t base) |