summaryrefslogtreecommitdiffstats
path: root/hw/psi.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-02-03 20:51:59 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-03-03 09:40:40 +1100
commita2940770ca6da2c58081f8207aded197e45f6cd6 (patch)
treef51be7c9dbe321fa6a270d88b502bf70269c6f9d /hw/psi.c
parent95c59d192376a4360278393da5df53e21ae3fc72 (diff)
downloadblackbird-skiboot-a2940770ca6da2c58081f8207aded197e45f6cd6.tar.gz
blackbird-skiboot-a2940770ca6da2c58081f8207aded197e45f6cd6.zip
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.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/hw/psi.c b/hw/psi.c
index 93b5a75c..089f4296 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -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)
OpenPOWER on IntegriCloud