diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-10-24 10:06:49 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-10-24 10:07:19 +1100 |
commit | 531bdefda91102cb3240e4e3289900af0a50e78b (patch) | |
tree | cc95231a4ce4a0ae05e7d123eaac4bd9beedef2d /hw/occ.c | |
parent | bed82938878cff16c539c1c6b3887b2cf65b4f57 (diff) | |
download | skiboot-531bdefda91102cb3240e4e3289900af0a50e78b.zip skiboot-531bdefda91102cb3240e4e3289900af0a50e78b.tar.gz skiboot-531bdefda91102cb3240e4e3289900af0a50e78b.tar.bz2 |
irq/occ/opal: Add self-sent dummy interrupt
This makes OPAL use the OCC interrupt facility to send itself an interrupt
whenever the OPAL event bit is set as a result of an OPAL call that wasn't
itself opal_handle_interrupt() or opal_handle_hmi() (both of which we know
the OS will already deal with appropriately).
This ensures that OPAL event changes are notified to Linux via its
interrupt path which is necessary for it to properly broadcast the state
change to its various clients.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw/occ.c')
-rw-r--r-- | hw/occ.c | 42 |
1 files changed, 42 insertions, 0 deletions
@@ -480,6 +480,48 @@ static struct fsp_client fsp_occ_client = { .message = fsp_occ_msg, }; +#define OCB_OCI_OCCMISC 0x6a020 +#define OCB_OCI_OCCMISC_AND 0x6a021 +#define OCB_OCI_OCCMISC_OR 0x6a022 +#define OCB_OCI_OCIMISC_IRQ PPC_BIT(0) +#define OCB_OCI_OCIMISC_IRQ_TMGT PPC_BIT(1) +#define OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY PPC_BIT(15) + +void occ_send_dummy_interrupt(void) +{ + xscom_writeme(OCB_OCI_OCCMISC_OR, + OCB_OCI_OCIMISC_IRQ | + OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY); +} + +static void occ_tmgt_interrupt(void) +{ + /* Not currently expected */ + printf("OCC: TMGT interrupt !\n"); +} + +void occ_interrupt(void) +{ + uint64_t ireg; + int64_t rc; + + /* The OCC interrupt is used to mux up to 15 different sources */ + rc = xscom_readme(OCB_OCI_OCCMISC, &ireg); + if (rc) { + prerror("OCC: Failed to read interrupt status !\n"); + /* Should we mask it in the XIVR ? */ + return; + } + prlog(PR_TRACE, "OCC: IRQ received: %04llx\n", ireg >> 48); + + /* Clear the bits */ + xscom_writeme(OCB_OCI_OCCMISC_AND, ~ireg); + + /* Dispatch */ + if (ireg & OCB_OCI_OCIMISC_IRQ_TMGT) + occ_tmgt_interrupt(); +} + void occ_fsp_init(void) { /* OCC is P8 only */ |