diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/occ.c | 22 | ||||
-rw-r--r-- | hw/psi.c | 7 |
2 files changed, 26 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; |