[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 43/77] ppc/pnv: Add OCC model stub with interrupt su
From: |
Benjamin Herrenschmidt |
Subject: |
[Qemu-devel] [PATCH 43/77] ppc/pnv: Add OCC model stub with interrupt support |
Date: |
Wed, 11 Nov 2015 11:27:56 +1100 |
The OCC is an on-chip microcontroller based on a ppc405 core used
for various power management tasks. It comes with a pile of additional
hardware sitting on the PIB (aka XSCOM bus). At this point we don't
emulate it (nor plan to do so). However there is one facility which
is provided by the surrounding hardware that we do need, which is the
interrupt generation facility. OPAL uses it to send itself interrupts
under some circumstances and there are other uses around the corner.
So this implement just enough to support this.
Signed-off-by: Benjamin Herrenschmidt <address@hidden>
---
hw/ppc/Makefile.objs | 2 +-
hw/ppc/pnv.c | 3 ++
hw/ppc/pnv_occ.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/ppc/pnv.h | 3 ++
4 files changed, 132 insertions(+), 1 deletion(-)
create mode 100644 hw/ppc/pnv_occ.c
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index a5b3ce6..a795b1c 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -5,7 +5,7 @@ obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
# IBM PowerNV
-obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o pnv_psi.o
+obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_lpc.o pnv_psi.o pnv_occ.o
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
obj-y += spapr_pci_vfio.o
endif
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index a10fa60..ae6efbd 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -542,6 +542,9 @@ static void pnv_create_chip(PnvSystem *sys, unsigned int
chip_no,
chip->psi, 16));
}
}
+
+ /* Create the simplified OCC model */
+ pnv_occ_create(chip);
}
static void ppc_powernv_init(MachineState *machine)
diff --git a/hw/ppc/pnv_occ.c b/hw/ppc/pnv_occ.c
new file mode 100644
index 0000000..a759c6d
--- /dev/null
+++ b/hw/ppc/pnv_occ.c
@@ -0,0 +1,125 @@
+/*
+ * Emulation of a few OCC related registers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright IBM Corp. 2014
+ */
+#include "hw/hw.h"
+#include "hw/ppc/pnv.h"
+#include "hw/ppc/pnv_xscom.h"
+
+struct PnvOCCState {
+ XScomDevice xd;
+ PnvPsiController *psi;
+
+ /* OCC Misc interrupt */
+ uint64_t occmisc;
+};
+
+#define TYPE_PNV_OCC "pnv-occ"
+#define PNV_OCC(obj) OBJECT_CHECK(PnvOCCState, (obj), TYPE_PNV_OCC)
+
+static void pnv_occ_set_misc(PnvOCCState *occ, uint64_t val)
+{
+ bool irq_state;
+
+ val &= 0xffff000000000000ull;
+
+ occ->occmisc = val;
+ irq_state = !!(val >> 63);
+ pnv_psi_irq_set(occ->psi, PSIHB_IRQ_OCC, irq_state);
+}
+
+static bool pnv_occ_xscom_read(XScomDevice *dev, uint32_t range,
+ uint32_t offset, uint64_t *out_val)
+{
+ PnvOCCState *occ = PNV_OCC(dev);
+ uint32_t pcb_addr = dev->ranges[range].addr + offset;
+
+ switch(pcb_addr) {
+ case 0x6a020:
+ *out_val = occ->occmisc;
+ return true;
+ }
+ return false;
+}
+
+static bool pnv_occ_xscom_write(XScomDevice *dev, uint32_t range,
+ uint32_t offset, uint64_t val)
+{
+ PnvOCCState *occ = PNV_OCC(dev);
+ uint32_t pcb_addr = dev->ranges[range].addr + offset;
+
+ switch(pcb_addr) {
+ default:
+ case 0x6a020:
+ pnv_occ_set_misc(occ, val);
+ return true;
+ case 0x6a021:
+ pnv_occ_set_misc(occ, occ->occmisc & val);
+ return true;
+ case 0x6a022:
+ pnv_occ_set_misc(occ, occ->occmisc | val);
+ return true;
+ }
+ return false;
+}
+
+static void pnv_occ_realize(DeviceState *dev, Error **errp)
+{
+ PnvOCCState *occ = PNV_OCC(dev);
+ XScomDevice *xd = XSCOM_DEVICE(dev);
+
+ xd->ranges[0].addr = 0x66000;
+ xd->ranges[0].size = 0x6000;
+
+ occ->occmisc = 0;
+}
+
+static void pnv_occ_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ XScomDeviceClass *k = XSCOM_DEVICE_CLASS(klass);
+
+ k->read = pnv_occ_xscom_read;
+ k->write = pnv_occ_xscom_write;
+
+ dc->realize = pnv_occ_realize;
+}
+
+static const TypeInfo pnv_occ_type_info = {
+ .name = TYPE_PNV_OCC,
+ .parent = TYPE_XSCOM_DEVICE,
+ .instance_size = sizeof(PnvOCCState),
+ .class_init = pnv_occ_class_init,
+};
+
+static void pnv_occ_register_types(void)
+{
+ type_register_static(&pnv_occ_type_info);
+}
+
+type_init(pnv_occ_register_types)
+
+void pnv_occ_create(PnvChip *chip)
+{
+ struct DeviceState *dev;
+ PnvOCCState *occ;
+
+ dev = qdev_create(&chip->xscom->bus, TYPE_PNV_OCC);
+ occ = PNV_OCC(dev);
+ occ->psi = chip->psi;
+ qdev_init_nofail(dev);
+ chip->occ = occ;
+}
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 73bbef9..c488f12 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -25,6 +25,7 @@ typedef struct ISABus ISABus;
typedef struct PnvLpcController PnvLpcController;
typedef struct PnvPsiController PnvPsiController;
typedef struct XICSState XICSState;
+typedef struct PnvOCCState PnvOCCState;
/* Should we turn that into a QOjb of some sort ? */
typedef struct PnvChip {
@@ -33,6 +34,7 @@ typedef struct PnvChip {
PnvLpcController *lpc;
ISABus *lpc_bus;
PnvPsiController *psi;
+ PnvOCCState *occ;
} PnvChip;
typedef struct PnvSystem {
@@ -44,6 +46,7 @@ typedef struct PnvSystem {
extern void pnv_lpc_create(PnvChip *chip, bool has_serirq);
extern void pnv_psi_create(PnvChip *chip, XICSState *xics);
+extern void pnv_occ_create(PnvChip *chip);
typedef enum PnvPsiIrq {
PSIHB_IRQ_PSI, /* internal use only */
--
2.5.0
- [Qemu-devel] [PATCH 38/77] ppc/xics: Add "native" XICS subclass, (continued)
[Qemu-devel] [PATCH 43/77] ppc/pnv: Add OCC model stub with interrupt support,
Benjamin Herrenschmidt <=
[Qemu-devel] [PATCH 47/77] pci: Don't call pci_irq_handler() for a negative intx, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 46/77] pci: Use the new pci_can_add_device() to enforce devfn_min/max, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 42/77] ppc/pnv: Add cut down PSI bridge model and hookup external interrupt, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 51/77] ppc: Use a helper to filter writes to LPCR, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 50/77] ppc: Update LPCR definitions, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 49/77] ppc/pnv: Create a default PCI layout, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 53/77] ppc: Add proper real mode translation support, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 52/77] ppc: Cosmetic, align some comments, Benjamin Herrenschmidt, 2015/11/10
[Qemu-devel] [PATCH 63/77] ppc: Initialize AMOR in PAPR mode, Benjamin Herrenschmidt, 2015/11/10