aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/lpc.c25
-rw-r--r--hw/psi.c41
-rw-r--r--hw/xive.c12
-rw-r--r--include/lpc.h3
-rw-r--r--include/xive.h4
5 files changed, 79 insertions, 6 deletions
diff --git a/hw/lpc.c b/hw/lpc.c
index c5ecc60..e86c9a3 100644
--- a/hw/lpc.c
+++ b/hw/lpc.c
@@ -944,14 +944,35 @@ void lpc_serirq(uint32_t chip_id, uint32_t index)
chip_id, irqs, rmask);
irqs &= rmask;
- /* Handle SerIRQ interrupts */
+ /*
+ * Handle SerIRQ interrupts. Don't clear the latch,
+ * it will be done in our special EOI callback if
+ * necessary on DD1
+ */
if (irqs)
- lpc_dispatch_ser_irqs(lpc, irqs, true);
+ lpc_dispatch_ser_irqs(lpc, irqs, false);
bail:
unlock(&lpc->lock);
}
+void lpc_p9_sirq_eoi(uint32_t chip_id, uint32_t index)
+{
+ struct proc_chip *chip = get_chip(chip_id);
+ struct lpcm *lpc;
+ uint32_t rmask;
+
+ /* No initialized LPC controller on that chip */
+ if (!chip || !chip->lpc)
+ return;
+ lpc = chip->lpc;
+
+ lock(&lpc->lock);
+ rmask = lpc->sirq_rmasks[index];
+ opb_write(lpc, lpc_reg_opb_base + LPC_HC_IRQSTAT, rmask, 4);
+ unlock(&lpc->lock);
+}
+
void lpc_all_interrupts(uint32_t chip_id)
{
struct proc_chip *chip = get_chip(chip_id);
diff --git a/hw/psi.c b/hw/psi.c
index 5d97fbb..93b5a75 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -657,6 +657,24 @@ static char *psi_p9_irq_name(struct irq_source *is, uint32_t isn)
return strdup(names[idx]);
}
+static void psi_p9_irq_dd1_eoi(struct irq_source *is, uint32_t isn)
+{
+ struct psi *psi = is->data;
+ unsigned int idx = isn & 0xf;
+
+ if (idx >= P9_PSI_IRQ_LPC_SIRQ0 &&
+ idx <= P9_PSI_IRQ_LPC_SIRQ3)
+ lpc_p9_sirq_eoi(psi->chip_id, idx - P9_PSI_IRQ_LPC_SIRQ0);
+ __xive_source_eoi(is, isn);
+}
+
+static const struct irq_source_ops psi_p9_dd1_irq_ops = {
+ .interrupt = psihb_p9_interrupt,
+ .attributes = psi_p9_irq_attributes,
+ .name = psi_p9_irq_name,
+ .eoi = psi_p9_irq_dd1_eoi,
+};
+
static const struct irq_source_ops psi_p9_irq_ops = {
.interrupt = psihb_p9_interrupt,
.attributes = psi_p9_irq_attributes,
@@ -797,6 +815,8 @@ static void psi_init_p8_interrupts(struct psi *psi)
static void psi_init_p9_interrupts(struct psi *psi)
{
+ struct proc_chip *c;
+ bool is_dd2;
u64 val;
/* Reset irq handling and switch to ESB mode */
@@ -829,9 +849,24 @@ static void psi_init_p9_interrupts(struct psi *psi)
out_be64(psi->regs + PSIHB_IVT_OFFSET, val);
/* Register sources */
- xive_register_hw_source(psi->interrupt, P9_PSI_NUM_IRQS,
- 12, psi->esb_mmio, XIVE_SRC_LSI,
- psi, &psi_p9_irq_ops);
+ c = next_chip(NULL);
+ is_dd2 = (c && c->ec_level >= 0x20);
+
+ if (is_dd2) {
+ prlog(PR_DEBUG,
+ "PSI[0x%03x]: Interrupts sources registered for P9 DD2.x\n",
+ psi->chip_id);
+ xive_register_hw_source(psi->interrupt, P9_PSI_NUM_IRQS,
+ 12, psi->esb_mmio, XIVE_SRC_LSI,
+ psi, &psi_p9_irq_ops);
+ } else {
+ prlog(PR_DEBUG,
+ "PSI[0x%03x]: Interrupts sources registered for P9 DD1.x\n",
+ psi->chip_id);
+ xive_register_hw_source(psi->interrupt, P9_PSI_NUM_IRQS,
+ 12, psi->esb_mmio, XIVE_SRC_LSI,
+ psi, &psi_p9_dd1_irq_ops);
+ }
}
static void psi_init_interrupts(struct psi *psi)
diff --git a/hw/xive.c b/hw/xive.c
index 784833b..909ef21 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -2371,7 +2371,7 @@ static int64_t xive_source_set_xive(struct irq_source *is, uint32_t isn,
return OPAL_SUCCESS;
}
-static void xive_source_eoi(struct irq_source *is, uint32_t isn)
+void __xive_source_eoi(struct irq_source *is, uint32_t isn)
{
struct xive_src *s = container_of(is, struct xive_src, is);
uint32_t idx = isn - s->esb_base;
@@ -2431,6 +2431,16 @@ static void xive_source_eoi(struct irq_source *is, uint32_t isn)
}
}
+static void xive_source_eoi(struct irq_source *is, uint32_t isn)
+{
+ struct xive_src *s = container_of(is, struct xive_src, is);
+
+ if (s->orig_ops && s->orig_ops->eoi)
+ s->orig_ops->eoi(is, isn);
+
+ __xive_source_eoi(is, isn);
+}
+
static void xive_source_interrupt(struct irq_source *is, uint32_t isn)
{
struct xive_src *s = container_of(is, struct xive_src, is);
diff --git a/include/lpc.h b/include/lpc.h
index 59f0779..3e92d53 100644
--- a/include/lpc.h
+++ b/include/lpc.h
@@ -98,6 +98,9 @@ extern void lpc_register_client(uint32_t chip_id, const struct lpc_client *clt);
/* Manual control of routing on P9 for use by platforms if necessary */
extern void lpc_route_serirq(uint32_t chip_id, uint32_t sirq, uint32_t psi_idx);
+/* Clear SerIRQ latch on P9 DD1 */
+extern void lpc_p9_sirq_eoi(uint32_t chip_id, uint32_t index);
+
/* Default bus accessors */
extern int64_t lpc_write(enum OpalLPCAddressType addr_type, uint32_t addr,
uint32_t data, uint32_t sz);
diff --git a/include/xive.h b/include/xive.h
index e9a01c3..58c4da9 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -460,4 +460,8 @@ void xive_cpu_callin(struct cpu_thread *cpu);
*/
void *xive_get_trigger_port(uint32_t girq);
+/* To be used by special EOI override in PSI */
+struct irq_source;
+void __xive_source_eoi(struct irq_source *is, uint32_t isn);
+
#endif /* __XIVE_H__ */