qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Cédric Le Goater" <clg@kaod.org>
To: David Gibson <david@gibson.dropbear.id.au>
Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org,
	"Benjamin Herrenschmidt" <benh@kernel.crashing.org>,
	"Cédric Le Goater" <clg@kaod.org>
Subject: [Qemu-devel] [PATCH for-2.10 8/8] ppc/pnv: Add support for POWER8+ LPC Controller
Date: Wed,  8 Mar 2017 11:52:51 +0100	[thread overview]
Message-ID: <1488970371-8865-9-git-send-email-clg@kaod.org> (raw)
In-Reply-To: <1488970371-8865-1-git-send-email-clg@kaod.org>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

It adds the Naples chip which supports proper LPC interrupts via the
LPC controller rather than via an external CPLD.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[clg: - updated for qemu-2.9
      - ported on latest PowerNV patchset ]
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/pnv.c             | 15 ++++++++++++++-
 hw/ppc/pnv_lpc.c         | 47 +++++++++++++++++++++++++++++++++++++++++++++--
 include/hw/ppc/pnv_lpc.h |  9 +++++++++
 3 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index ca5a078bc6c6..65dfe5b4c97b 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -376,7 +376,14 @@ static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level)
 
 static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
 {
-     /* XXX TODO */
+    PnvChip *chip = opaque;
+    PnvLpcController *lpc = &chip->lpc;
+
+    /* The Naples HW latches the 1 levels, clearing is done by SW */
+    if (level) {
+        lpc->lpc_hc_irqstat |= LPC_HC_IRQ_SERIRQ0 >> n;
+        pnv_lpc_eval_irqs(lpc);
+    }
 }
 
 static ISABus *pnv_isa_create(PnvChip *chip)
@@ -719,6 +726,12 @@ static void pnv_chip_init(Object *obj)
     object_property_add_child(obj, "occ", OBJECT(&chip->occ), NULL);
     object_property_add_const_link(OBJECT(&chip->occ), "psi",
                                    OBJECT(&chip->psi), &error_abort);
+
+    /*
+     * The LPC controller needs PSI to generate interrupts
+     */
+    object_property_add_const_link(OBJECT(&chip->lpc), "psi",
+                                   OBJECT(&chip->psi), &error_abort);
 }
 
 static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index 78db52415b11..20cbb6a0dbbd 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -250,6 +250,34 @@ static const MemoryRegionOps pnv_lpc_xscom_ops = {
     .endianness = DEVICE_BIG_ENDIAN,
 };
 
+void pnv_lpc_eval_irqs(PnvLpcController *lpc)
+{
+    bool lpc_to_opb_irq = false;
+
+    /* Update LPC controller to OPB line */
+    if (lpc->lpc_hc_irqser_ctrl & LPC_HC_IRQSER_EN) {
+        uint32_t irqs;
+
+        irqs = lpc->lpc_hc_irqstat & lpc->lpc_hc_irqmask;
+        lpc_to_opb_irq = (irqs != 0);
+    }
+
+    /* We don't honor the polarity register, it's pointless and unused
+     * anyway
+     */
+    if (lpc_to_opb_irq) {
+        lpc->opb_irq_input |= OPB_MASTER_IRQ_LPC;
+    } else {
+        lpc->opb_irq_input &= ~OPB_MASTER_IRQ_LPC;
+    }
+
+    /* Update OPB internal latch */
+    lpc->opb_irq_stat |= lpc->opb_irq_input & lpc->opb_irq_mask;
+
+    /* Reflect the interrupt */
+    pnv_psi_irq_set(lpc->psi, PSIHB_IRQ_LPC_I2C, lpc->opb_irq_stat != 0);
+}
+
 static uint64_t lpc_hc_read(void *opaque, hwaddr addr, unsigned size)
 {
     PnvLpcController *lpc = opaque;
@@ -300,12 +328,15 @@ static void lpc_hc_write(void *opaque, hwaddr addr, uint64_t val,
         break;
     case LPC_HC_IRQSER_CTRL:
         lpc->lpc_hc_irqser_ctrl = val;
+        pnv_lpc_eval_irqs(lpc);
         break;
     case LPC_HC_IRQMASK:
         lpc->lpc_hc_irqmask = val;
+        pnv_lpc_eval_irqs(lpc);
         break;
     case LPC_HC_IRQSTAT:
         lpc->lpc_hc_irqstat &= ~val;
+        pnv_lpc_eval_irqs(lpc);
         break;
     case LPC_HC_ERROR_ADDRESS:
         break;
@@ -363,14 +394,15 @@ static void opb_master_write(void *opaque, hwaddr addr,
     switch (addr) {
     case OPB_MASTER_LS_IRQ_STAT:
         lpc->opb_irq_stat &= ~val;
+        pnv_lpc_eval_irqs(lpc);
         break;
     case OPB_MASTER_LS_IRQ_MASK:
-        /* XXX Filter out reserved bits */
         lpc->opb_irq_mask = val;
+        pnv_lpc_eval_irqs(lpc);
         break;
     case OPB_MASTER_LS_IRQ_POL:
-        /* XXX Filter out reserved bits */
         lpc->opb_irq_pol = val;
+        pnv_lpc_eval_irqs(lpc);
         break;
     case OPB_MASTER_LS_IRQ_INPUT:
         /* Read only */
@@ -398,6 +430,8 @@ static const MemoryRegionOps opb_master_ops = {
 static void pnv_lpc_realize(DeviceState *dev, Error **errp)
 {
     PnvLpcController *lpc = PNV_LPC(dev);
+    Object *obj;
+    Error *error = NULL;
 
     /* Reg inits */
     lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B;
@@ -441,6 +475,15 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp)
     pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(dev),
                           &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
                           PNV_XSCOM_LPC_SIZE);
+
+    /* get PSI object from chip */
+    obj = object_property_get_link(OBJECT(dev), "psi", &error);
+    if (!obj) {
+        error_setg(errp, "%s: required link 'psi' not found: %s",
+                   __func__, error_get_pretty(error));
+        return;
+    }
+    lpc->psi = PNV_PSI(obj);
 }
 
 static void pnv_lpc_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
index 38e5506975aa..53040026c37b 100644
--- a/include/hw/ppc/pnv_lpc.h
+++ b/include/hw/ppc/pnv_lpc.h
@@ -23,6 +23,8 @@
 #define PNV_LPC(obj) \
      OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC)
 
+typedef struct PnvPsi PnvPsi;
+
 typedef struct PnvLpcController {
     DeviceState parent;
 
@@ -62,6 +64,13 @@ typedef struct PnvLpcController {
 
     /* XSCOM registers */
     MemoryRegion xscom_regs;
+
+    /* PSI to generate interrupts */
+    PnvPsi *psi;
 } PnvLpcController;
 
+#define   LPC_HC_IRQ_SERIRQ0            0x80000000 /* all bits down to ... */
+
+void pnv_lpc_eval_irqs(PnvLpcController *lpc);
+
 #endif /* _PPC_PNV_LPC_H */
-- 
2.7.4

      parent reply	other threads:[~2017-03-08 10:53 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-08 10:52 [Qemu-devel] [PATCH for-2.10 0/8] ppc/pnv: interrupt controller (POWER8) Cédric Le Goater
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 1/8] ppc/xics: add a xics_get_cpu_index_by_pir() helper Cédric Le Goater
2017-03-14  5:38   ` David Gibson
2017-03-14  8:11     ` Cédric Le Goater
2017-03-14 17:00     ` Cédric Le Goater
2017-03-15  4:53       ` David Gibson
2017-03-15 10:04         ` Cédric Le Goater
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 2/8] ppc/xics: add an ics_eoi() handler to XICSFabric Cédric Le Goater
2017-03-14  5:40   ` David Gibson
2017-03-14  8:12     ` Cédric Le Goater
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 3/8] ppc/pnv: create the ICP and ICS objects under the machine Cédric Le Goater
2017-03-14  5:45   ` David Gibson
2017-03-14  9:47     ` Cédric Le Goater
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 4/8] ppc/pnv: add memory regions for the ICP registers Cédric Le Goater
2017-03-08 11:24   ` Philippe Mathieu-Daudé
2017-03-08 13:33     ` Cédric Le Goater
2017-03-14  5:49   ` David Gibson
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 5/8] ppc/pnv: map the ICP memory regions Cédric Le Goater
2017-03-14  5:52   ` David Gibson
2017-03-14 10:02     ` Cédric Le Goater
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 6/8] ppc/pnv: Add cut down PSI bridge model and hookup external interrupt Cédric Le Goater
2017-03-15  6:16   ` David Gibson
2017-03-15  9:38     ` Benjamin Herrenschmidt
2017-03-16 13:52     ` Cédric Le Goater
2017-03-17  2:00       ` David Gibson
2017-03-17  8:27         ` Cédric Le Goater
2017-03-21 13:36       ` Cédric Le Goater
2017-03-08 10:52 ` [Qemu-devel] [PATCH for-2.10 7/8] ppc/pnv: Add OCC model stub with interrupt support Cédric Le Goater
2017-03-08 10:52 ` Cédric Le Goater [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1488970371-8865-9-git-send-email-clg@kaod.org \
    --to=clg@kaod.org \
    --cc=benh@kernel.crashing.org \
    --cc=david@gibson.dropbear.id.au \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).