Patchwork [14/19] openpic: convert to qdev

login
register
mail settings
Submitter Alexander Graf
Date Dec. 8, 2012, 1:44 p.m.
Message ID <1354974282-1915-15-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/204649/
State New
Headers show

Comments

Alexander Graf - Dec. 8, 2012, 1:44 p.m.
This patch converts the OpenPIC device to qdev. Along the way it
renames the "openpic" target to "raven" and the "mpic" target to
"mpc8544", to better reflect the actual models they implement.

This way we have a generic OpenPIC device now that can handle
different flavors of the OpenPIC specification.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/openpic.c      |  278 ++++++++++++++++++++++++++---------------------------
 hw/openpic.h      |    8 +-
 hw/ppc/e500.c     |   24 ++++-
 hw/ppc_newworld.c |   25 +++++-
 4 files changed, 180 insertions(+), 155 deletions(-)
Scott Wood - Dec. 10, 2012, 11:47 p.m.
On 12/08/2012 07:44:37 AM, Alexander Graf wrote:
> This patch converts the OpenPIC device to qdev. Along the way it
> renames the "openpic" target to "raven" and the "mpic" target to
> "mpc8544", to better reflect the actual models they implement.
> 
> This way we have a generic OpenPIC device now that can handle
> different flavors of the OpenPIC specification.

I'd rather not see the expansion of "mpc8544" hardcoding, especially  
since it's not really modelling an MPIC as found in an mpc8544, but  
rather half-implementing a generic Freescale MPIC.  Can we just call it  
a Freescale MPIC, and then work on parameterizing it properly (starting  
with MPIC version)?

-Scott
Alexander Graf - Dec. 11, 2012, 8:25 a.m.
On 11.12.2012, at 00:47, Scott Wood <scottwood@freescale.com> wrote:

> On 12/08/2012 07:44:37 AM, Alexander Graf wrote:
>> This patch converts the OpenPIC device to qdev. Along the way it
>> renames the "openpic" target to "raven" and the "mpic" target to
>> "mpc8544", to better reflect the actual models they implement.
>> This way we have a generic OpenPIC device now that can handle
>> different flavors of the OpenPIC specification.
> 
> I'd rather not see the expansion of "mpc8544" hardcoding, especially since it's not really modelling an MPIC as found in an mpc8544, but rather half-implementing a generic Freescale MPIC.  

That's what we've been doing wrong all the time now. We shouldn't implement a half-generic fsl mpic, because we will never get to a point where we're accurate enough or flexible enough for both definitions.

If we want a pv style generic mpic (for -M e500), let's add such an mpic to the model list and make that one be really generic. But the MPIC in -M mpc8544ds should behave exactly like an mpc8544 mpic. Whenever we fail to do so, we better fix the emulation to be accurate ;)

> Can we just call it a Freescale MPIC, and then work on parameterizing it properly (starting with MPIC version)?

We can add a generic fsl mpic if you like. We can also extract commonalities between the generic fsl mpic and the mpc8544 mpic into a function inside openpic.c.

The MPIC version is a parameter after this patch set, but it's an internal parameter. My first version of the qdevification was setting all the openpic parameters from the machine file, so that you could assemble whatever openpic you like by setting the currect parameters.

That approach is overkill though. We are working in an open source world, where you can always just modify openpic.c, addd your model and be happy :)

Thanks a lot for the review btw!


Alex

Patch

diff --git a/hw/openpic.c b/hw/openpic.c
index 321c6d4..6aac4b8 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -37,6 +37,7 @@ 
 #include "ppc_mac.h"
 #include "pci.h"
 #include "openpic.h"
+#include "sysbus.h"
 
 //#define DEBUG_OPENPIC
 
@@ -53,30 +54,10 @@ 
 #define MAX_IPI     4
 #define VID         0x03 /* MPIC version ID */
 
-enum {
-    IRQ_IPVP = 0,
-    IRQ_IDE,
-};
-
-/* OpenPIC */
-#define OPENPIC_MAX_CPU      2
-#define OPENPIC_MAX_IRQ     64
-#define OPENPIC_EXT_IRQ     48
-#define OPENPIC_MAX_TMR      MAX_TMR
-#define OPENPIC_MAX_IPI      MAX_IPI
-
-/* Interrupt definitions */
-#define OPENPIC_IRQ_FE     (OPENPIC_EXT_IRQ)     /* Internal functional IRQ */
-#define OPENPIC_IRQ_ERR    (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
-#define OPENPIC_IRQ_TIM0   (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
-#if OPENPIC_MAX_IPI > 0
-#define OPENPIC_IRQ_IPI0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
-#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
-#else
-#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
-#define OPENPIC_IRQ_MBX0   (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
-#endif
+/* OpenPIC capability flags */
+#define OPENPIC_FLAG_IDE_CRIT     (1 << 0)
 
+/* OpenPIC address map */
 #define OPENPIC_GLB_REG_START        0x0
 #define OPENPIC_GLB_REG_SIZE         0x10F0
 #define OPENPIC_TMR_REG_START        0x10F0
@@ -86,31 +67,37 @@  enum {
 #define OPENPIC_CPU_REG_START        0x20000
 #define OPENPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
 
-/* MPIC */
-#define MPIC_MAX_CPU      1
-#define MPIC_MAX_EXT     12
-#define MPIC_MAX_INT     64
-#define MPIC_MAX_IRQ     MAX_IRQ
+/* Raven */
+#define RAVEN_MAX_CPU      2
+#define RAVEN_MAX_EXT     48
+#define RAVEN_MAX_IRQ     64
+#define RAVEN_MAX_TMR      MAX_TMR
+#define RAVEN_MAX_IPI      MAX_IPI
+
+/* Interrupt definitions */
+#define RAVEN_FE_IRQ     (RAVEN_MAX_EXT)     /* Internal functional IRQ */
+#define RAVEN_ERR_IRQ    (RAVEN_MAX_EXT + 1) /* Error IRQ */
+#define RAVEN_TMR_IRQ    (RAVEN_MAX_EXT + 2) /* First timer IRQ */
+#define RAVEN_IPI_IRQ    (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */
+/* First doorbell IRQ */
+#define RAVEN_DBL_IRQ    (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
+
+/* MPC8544 */
+#define MPC8544_MAX_CPU      1
+#define MPC8544_MAX_EXT     12
+#define MPC8544_MAX_INT     64
+#define MPC8544_MAX_IRQ     MAX_IRQ
 
 /* Interrupt definitions */
 /* IRQs, accessible through the IRQ region */
-#define MPIC_EXT_IRQ      0x00
-#define MPIC_INT_IRQ      0x10
-#define MPIC_MSG_IRQ      0xb0
-#define MPIC_MSI_IRQ      0xe0
+#define MPC8544_EXT_IRQ      0x00
+#define MPC8544_INT_IRQ      0x10
+#define MPC8544_MSG_IRQ      0xb0
+#define MPC8544_MSI_IRQ      0xe0
 /* These are available through separate regions, but
    for simplicity's sake mapped into the same number space */
-#define MPIC_TMR_IRQ      0xf3
-#define MPIC_IPI_IRQ      0xfb
-
-#define MPIC_GLB_REG_START        0x0
-#define MPIC_GLB_REG_SIZE         0x10F0
-#define MPIC_TMR_REG_START        0x10F0
-#define MPIC_TMR_REG_SIZE         0x220
-#define MPIC_SRC_REG_START        0x10000
-#define MPIC_SRC_REG_SIZE         (MAX_IRQ * 0x20)
-#define MPIC_CPU_REG_START        0x20000
-#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
+#define MPC8544_TMR_IRQ      0xf3
+#define MPC8544_IPI_IRQ      0xfb
 
 /*
  * Block Revision Register1 (BRR1): QEMU does not fully emulate
@@ -128,6 +115,7 @@  enum {
 #define FREP_VID_SHIFT     0
 
 #define VID_REVISION_1_2   2
+#define VID_REVISION_1_3   3
 
 #define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
 
@@ -204,10 +192,11 @@  typedef struct IRQ_dst_t {
 } IRQ_dst_t;
 
 typedef struct OpenPICState {
-    PCIDevice pci_dev;
+    SysBusDevice busdev;
     MemoryRegion mem;
 
     /* Behavior control */
+    uint32_t model;
     uint32_t flags;
     uint32_t nb_irqs;
     uint32_t vid;
@@ -230,15 +219,15 @@  typedef struct OpenPICState {
     IRQ_src_t src[MAX_IRQ];
     /* Local registers per output pin */
     IRQ_dst_t dst[MAX_CPU];
-    int nb_cpus;
+    uint32_t nb_cpus;
     /* Timer registers */
     struct {
         uint32_t ticc;  /* Global timer current count register */
         uint32_t tibc;  /* Global timer base count register */
     } timers[MAX_TMR];
-    int max_irq;
-    int irq_ipi0;
-    int irq_tim0;
+    uint32_t max_irq;
+    uint32_t irq_ipi0;
+    uint32_t irq_tim0;
 } OpenPICState;
 
 static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
@@ -410,9 +399,9 @@  static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     openpic_update_irq(opp, n_IRQ);
 }
 
-static void openpic_reset (void *opaque)
+static void openpic_reset(DeviceState *d)
 {
-    OpenPICState *opp = (OpenPICState *)opaque;
+    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
     int i;
 
     opp->glbc = 0x80000000;
@@ -505,7 +494,7 @@  static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
         break;
     case 0x1020: /* GLBC */
         if (val & 0x80000000) {
-            openpic_reset(opp);
+            openpic_reset(&opp->busdev.qdev);
         }
         break;
     case 0x1080: /* VENI */
@@ -970,7 +959,7 @@  static void openpic_save(QEMUFile* f, void *opaque)
         qemu_put_sbe32s(f, &opp->src[i].pending);
     }
 
-    qemu_put_sbe32s(f, &opp->nb_cpus);
+    qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
         qemu_put_be32s(f, &opp->dst[i].pctp);
@@ -983,8 +972,6 @@  static void openpic_save(QEMUFile* f, void *opaque)
         qemu_put_be32s(f, &opp->timers[i].ticc);
         qemu_put_be32s(f, &opp->timers[i].tibc);
     }
-
-    pci_device_save(&opp->pci_dev, f);
 }
 
 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
@@ -1019,7 +1006,7 @@  static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_sbe32s(f, &opp->src[i].pending);
     }
 
-    qemu_get_sbe32s(f, &opp->nb_cpus);
+    qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
         qemu_get_be32s(f, &opp->dst[i].pctp);
@@ -1033,7 +1020,7 @@  static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_be32s(f, &opp->timers[i].tibc);
     }
 
-    return pci_device_load(&opp->pci_dev, f);
+    return 0;
 }
 
 static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
@@ -1047,17 +1034,18 @@  static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
     }
 }
 
-qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
-                        qemu_irq **irqs)
+struct memreg {
+    const char             *name;
+    MemoryRegionOps const  *ops;
+    hwaddr      start_addr;
+    ram_addr_t              size;
+};
+
+static int openpic_init(SysBusDevice *dev)
 {
-    OpenPICState *opp;
-    int i;
-    struct {
-        const char             *name;
-        MemoryRegionOps const  *ops;
-        hwaddr      start_addr;
-        ram_addr_t              size;
-    } const list[] = {
+    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
+    int i, j;
+    const struct memreg list_le[] = {
         {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START,
                                      OPENPIC_GLB_REG_SIZE},
         {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START,
@@ -1067,16 +1055,57 @@  qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
         {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START,
                                      OPENPIC_CPU_REG_SIZE},
     };
+    const struct memreg list_be[] = {
+        {"glb", &openpic_glb_ops_be, OPENPIC_GLB_REG_START,
+                                     OPENPIC_GLB_REG_SIZE},
+        {"tmr", &openpic_tmr_ops_be, OPENPIC_TMR_REG_START,
+                                     OPENPIC_TMR_REG_SIZE},
+        {"src", &openpic_src_ops_be, OPENPIC_SRC_REG_START,
+                                     OPENPIC_SRC_REG_SIZE},
+        {"cpu", &openpic_cpu_ops_be, OPENPIC_CPU_REG_START,
+                                     OPENPIC_CPU_REG_SIZE},
+    };
+    struct memreg const *list;
 
-    /* XXX: for now, only one CPU is supported */
-    if (nb_cpus != 1)
-        return NULL;
-    opp = g_malloc0(sizeof(OpenPICState));
+    switch (opp->model) {
+    case OPENPIC_MODEL_MPC8544:
+    default:
+        opp->flags |= OPENPIC_FLAG_IDE_CRIT;
+        opp->nb_irqs = 80;
+        opp->vid = VID_REVISION_1_2;
+        opp->veni = VENI_GENERIC;
+        opp->spve_mask = 0xFFFF;
+        opp->tifr_reset = 0x00000000;
+        opp->ipvp_reset = 0x80000000;
+        opp->ide_reset = 0x00000001;
+        opp->max_irq = MPC8544_MAX_IRQ;
+        opp->irq_ipi0 = MPC8544_IPI_IRQ;
+        opp->irq_tim0 = MPC8544_TMR_IRQ;
+        list = list_be;
+        break;
+    case OPENPIC_MODEL_RAVEN:
+        opp->nb_irqs = RAVEN_MAX_EXT;
+        opp->vid = VID_REVISION_1_3;
+        opp->veni = VENI_GENERIC;
+        opp->spve_mask = 0xFF;
+        opp->tifr_reset = 0x003F7A00;
+        opp->ipvp_reset = 0xA0000000;
+        opp->ide_reset = 0x00000000;
+        opp->max_irq = RAVEN_MAX_IRQ;
+        opp->irq_ipi0 = RAVEN_IPI_IRQ;
+        opp->irq_tim0 = RAVEN_TMR_IRQ;
+        list = list_le;
+
+        /* Only UP supported today */
+        if (opp->nb_cpus != 1) {
+            return -EINVAL;
+        }
+        break;
+    }
 
     memory_region_init(&opp->mem, "openpic", 0x40000);
 
-    for (i = 0; i < ARRAY_SIZE(list); i++) {
-
+    for (i = 0; i < ARRAY_SIZE(list_le); i++) {
         memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
                               list[i].name, list[i].size);
 
@@ -1084,83 +1113,48 @@  qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
                                     &opp->sub_io_mem[i]);
     }
 
-    //    isu_base &= 0xFFFC0000;
-    opp->nb_cpus = nb_cpus;
-    opp->nb_irqs = OPENPIC_EXT_IRQ;
-    opp->vid = VID;
-    opp->veni = VENI_GENERIC;
-    opp->spve_mask = 0xFF;
-    opp->tifr_reset = 0x003F7A00;
-    opp->max_irq = OPENPIC_MAX_IRQ;
-    opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
-    opp->irq_tim0 = OPENPIC_IRQ_TIM0;
-
-    for (i = 0; i < nb_cpus; i++)
-        opp->dst[i].irqs = irqs[i];
-
-    register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
+    for (i = 0; i < opp->nb_cpus; i++) {
+        opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB);
+        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+            sysbus_init_irq(dev, &opp->dst[i].irqs[j]);
+        }
+    }
+
+    register_savevm(&opp->busdev.qdev, "openpic", 0, 2,
                     openpic_save, openpic_load, opp);
-    qemu_register_reset(openpic_reset, opp);
 
-    if (pmem)
-        *pmem = &opp->mem;
+    sysbus_init_mmio(dev, &opp->mem);
+    qdev_init_gpio_in(&dev->qdev, openpic_set_irq, opp->max_irq);
 
-    return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
+    return 0;
 }
 
-qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
-                     int nb_cpus, qemu_irq **irqs)
-{
-    OpenPICState    *mpp;
-    int           i;
-    struct {
-        const char             *name;
-        MemoryRegionOps const  *ops;
-        hwaddr      start_addr;
-        ram_addr_t              size;
-    } const list[] = {
-        {"glb", &openpic_glb_ops_be, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
-        {"tmr", &openpic_tmr_ops_be, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
-        {"src", &openpic_src_ops_be, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE},
-        {"cpu", &openpic_cpu_ops_be, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
-    };
-
-    mpp = g_malloc0(sizeof(OpenPICState));
-
-    memory_region_init(&mpp->mem, "mpic", 0x40000);
-    memory_region_add_subregion(address_space, base, &mpp->mem);
+static Property openpic_properties[] = {
+    DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_MPC8544),
+    DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
 
-    for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
+static void openpic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-        memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
-                              list[i].name, list[i].size);
+    k->init = openpic_init;
+    dc->props = openpic_properties;
+    dc->reset = openpic_reset;
+}
 
-        memory_region_add_subregion(&mpp->mem, list[i].start_addr,
-                                    &mpp->sub_io_mem[i]);
-    }
+static TypeInfo openpic_info = {
+    .name          = "openpic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(OpenPICState),
+    .class_init    = openpic_class_init,
+};
 
-    mpp->nb_cpus = nb_cpus;
-    /* 12 external sources, 48 internal sources , 4 timer sources,
-       4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */
-    mpp->nb_irqs = 80;
-    mpp->vid = VID_REVISION_1_2;
-    mpp->veni = VENI_GENERIC;
-    mpp->spve_mask = 0xFFFF;
-    mpp->tifr_reset = 0x00000000;
-    mpp->ipvp_reset = 0x80000000;
-    mpp->ide_reset = 0x00000001;
-    mpp->max_irq = MPIC_MAX_IRQ;
-    mpp->irq_ipi0 = MPIC_IPI_IRQ;
-    mpp->irq_tim0 = MPIC_TMR_IRQ;
-
-    for (i = 0; i < nb_cpus; i++)
-        mpp->dst[i].irqs = irqs[i];
-
-    /* Enable critical interrupt support */
-    mpp->flags |= OPENPIC_FLAG_IDE_CRIT;
-
-    register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
-    qemu_register_reset(openpic_reset, mpp);
-
-    return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
+static void openpic_register_types(void)
+{
+    type_register_static(&openpic_info);
 }
+
+type_init(openpic_register_types)
diff --git a/hw/openpic.h b/hw/openpic.h
index 8a68f20..824609c 100644
--- a/hw/openpic.h
+++ b/hw/openpic.h
@@ -11,11 +11,7 @@  enum {
     OPENPIC_OUTPUT_NB,
 };
 
-/* OpenPIC capability flags */
-#define OPENPIC_FLAG_IDE_CRIT    (1 << 0)
+#define OPENPIC_MODEL_RAVEN       0
+#define OPENPIC_MODEL_MPC8544     1
 
-qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
-                        qemu_irq **irqs);
-qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
-                     int nb_cpus, qemu_irq **irqs);
 #endif /* __OPENPIC_H__ */
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 3f6d58c..f9893ad 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -418,7 +418,7 @@  void ppce500_init(PPCE500Params *params)
     target_ulong dt_base = 0;
     target_ulong initrd_base = 0;
     target_long initrd_size=0;
-    int i=0;
+    int i = 0, j, k;
     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
     qemu_irq **irqs, *mpic;
     DeviceState *dev;
@@ -492,13 +492,27 @@  void ppce500_init(PPCE500Params *params)
                                 ccsr_addr_space);
 
     /* MPIC */
-    mpic = mpic_init(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
-                     smp_cpus, irqs);
+    mpic = g_new(qemu_irq, 256);
+    dev = qdev_create(NULL, "openpic");
+    qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
+    qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_MPC8544);
+    qdev_init_nofail(dev);
+    s = sysbus_from_qdev(dev);
+
+    k = 0;
+    for (i = 0; i < smp_cpus; i++) {
+        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+            sysbus_connect_irq(s, k++, irqs[i][j]);
+        }
+    }
 
-    if (!mpic) {
-        cpu_abort(env, "MPIC failed to initialize\n");
+    for (i = 0; i < 256; i++) {
+        mpic[i] = qdev_get_gpio_in(dev, i);
     }
 
+    memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
+                                s->mmio[0].memory);
+
     /* Serial */
     if (serial_hds[0]) {
         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index b9c2cd8..8c2114e 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -67,6 +67,7 @@ 
 #include "hw/usb.h"
 #include "blockdev.h"
 #include "exec-memory.h"
+#include "sysbus.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -141,7 +142,7 @@  static void ppc_core99_init(QEMUMachineInitArgs *args)
     char *filename;
     qemu_irq *pic, **openpic_irqs;
     MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
-    int linux_boot, i;
+    int linux_boot, i, j, k;
     MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1);
     hwaddr kernel_base, initrd_base, cmdline_base = 0;
     long kernel_size, initrd_size;
@@ -156,6 +157,8 @@  static void ppc_core99_init(QEMUMachineInitArgs *args)
     void *fw_cfg;
     void *dbdma;
     int machine_arch;
+    SysBusDevice *s;
+    DeviceState *dev;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -320,7 +323,25 @@  static void ppc_core99_init(QEMUMachineInitArgs *args)
             exit(1);
         }
     }
-    pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs);
+
+    pic = g_new(qemu_irq, 64);
+
+    dev = qdev_create(NULL, "openpic");
+    qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN);
+    qdev_init_nofail(dev);
+    s = sysbus_from_qdev(dev);
+    pic_mem = s->mmio[0].memory;
+    k = 0;
+    for (i = 0; i < smp_cpus; i++) {
+        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+            sysbus_connect_irq(s, k++, openpic_irqs[i][j]);
+        }
+    }
+
+    for (i = 0; i < 64; i++) {
+        pic[i] = qdev_get_gpio_in(dev, i);
+    }
+
     if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
         /* 970 gets a U3 bus */
         pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io());