diff options
-rw-r--r-- | hw/occ.c | 22 | ||||
-rw-r--r-- | hw/psi.c | 7 | ||||
-rw-r--r-- | include/chip.h | 3 | ||||
-rw-r--r-- | include/psi.h | 1 |
4 files changed, 30 insertions, 3 deletions
@@ -625,12 +625,28 @@ static struct fsp_client fsp_occ_client = { void occ_send_dummy_interrupt(void) { + struct psi *psi; + struct proc_chip *chip = get_chip(this_cpu()->chip_id); + /* Emulators and P7 doesn't do this */ if (proc_gen != proc_gen_p8 || chip_quirk(QUIRK_NO_OCC_IRQ)) return; - xscom_writeme(OCB_OCI_OCCMISC_OR, - OCB_OCI_OCIMISC_IRQ | - OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY); + + /* Find a functional PSI. This ensures an interrupt even if + * the psihb on the current chip is not configured */ + if (chip->psi) + psi = chip->psi; + else + psi = psi_find_functional_chip(); + + if (!psi) { + prlog_once(PR_WARNING, "PSI: no functional PSI HB found, " + "no self interrupts delivered\n"); + return; + } + + xscom_write(psi->chip_id, OCB_OCI_OCCMISC_OR, + OCB_OCI_OCIMISC_IRQ | OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY); } void occ_interrupt(uint32_t chip_id) @@ -885,6 +885,8 @@ static bool psi_init_psihb(struct dt_node *psihb) psi->chip_id = chip->id; psi->interrupt = get_psi_interrupt(chip->id); + chip->psi = psi; + psi_create_mm_dtnode(psi); psi_register_interrupts(psi); psi_activate_phb(psi); @@ -905,6 +907,11 @@ void psi_fsp_link_in_use(struct psi *psi __unused) } } +struct psi *psi_find_functional_chip(void) +{ + return list_top(&psis, struct psi, list); +} + void psi_init(void) { struct dt_node *np; diff --git a/include/chip.h b/include/chip.h index 0547902..1b4f4c4 100644 --- a/include/chip.h +++ b/include/chip.h @@ -157,6 +157,9 @@ struct proc_chip { /* Used by hw/p8-i2c.c */ struct list_head i2cms; + + /* Used by hw/psi.c */ + struct psi *psi; }; extern uint32_t pir_to_chip_id(uint32_t pir); diff --git a/include/psi.h b/include/psi.h index 4127242..62643aa 100644 --- a/include/psi.h +++ b/include/psi.h @@ -217,6 +217,7 @@ extern void psi_disable_link(struct psi *psi); extern void psi_reset_fsp(struct psi *psi); extern bool psi_check_link_active(struct psi *psi); extern bool psi_poll_fsp_interrupt(struct psi *psi); +extern struct psi *psi_find_functional_chip(void); /* Interrupts */ extern void psi_irq_reset(void); |