aboutsummaryrefslogtreecommitdiff
path: root/hw/lpc.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-02-03 20:51:58 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-02-07 14:16:03 +1100
commit7d252cdeb5f5f85d4a386859e0c87613162bcf31 (patch)
treeb0defc9d54750cdc509171eb2b5f3db3bc8bb77d /hw/lpc.c
parentdcffe14d4075ac9e8bfce6eb1c53401630a6582f (diff)
downloadskiboot-7d252cdeb5f5f85d4a386859e0c87613162bcf31.zip
skiboot-7d252cdeb5f5f85d4a386859e0c87613162bcf31.tar.gz
skiboot-7d252cdeb5f5f85d4a386859e0c87613162bcf31.tar.bz2
xive/psi/lpc: Handle proper clearing of LPC SerIRQ latch on DD1
On DD1, the LPC SerIRQ are latched to 1 in HW but never back to 0, we need an explicit clear after running the handler. (Not before as they are level interrupts, they will be latched again if they are still pending). For now we do that in lpc_dispatch_ser_irqs() but that only works for interrupts routed to OPAL. In order to support routing LPC interrutps to Linux, we need a custom EOI handler that does the clearing of the latch before we do the EOI in the ESB. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/lpc.c')
-rw-r--r--hw/lpc.c25
1 files changed, 23 insertions, 2 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);