diff mbox

[25/40] openpic: convert to qdev

Message ID 1355487236-27451-26-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf Dec. 14, 2012, 12:13 p.m. UTC
This patch converts the OpenPIC device to qdev. Along the way it
renames the "openpic" target to "raven" and the "mpic" target to
"fsl_mpic_20", 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(-)

Comments

Blue Swirl Dec. 14, 2012, 8:32 p.m. UTC | #1
On Fri, Dec 14, 2012 at 12:13 PM, Alexander Graf <agraf@suse.de> wrote:
> This patch converts the OpenPIC device to qdev. Along the way it
> renames the "openpic" target to "raven" and the "mpic" target to
> "fsl_mpic_20", 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(-)
>
> diff --git a/hw/openpic.c b/hw/openpic.c
> index 5116b3e..591b291 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
>
> @@ -54,30 +55,10 @@
>  #define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
>  #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
> @@ -87,31 +68,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))
> +
> +/* FSL_MPIC_20 */
> +#define FSL_MPIC_20_MAX_CPU      1
> +#define FSL_MPIC_20_MAX_EXT     12
> +#define FSL_MPIC_20_MAX_INT     64
> +#define FSL_MPIC_20_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 FSL_MPIC_20_EXT_IRQ      0x00
> +#define FSL_MPIC_20_INT_IRQ      0x10
> +#define FSL_MPIC_20_MSG_IRQ      0xb0
> +#define FSL_MPIC_20_MSI_IRQ      0xe0
>  /* These are available through separate regions, but
>     for simplicity's sake mapped into the same number space */
> -#define MPIC_TMR_IRQ      0x100
> -#define MPIC_IPI_IRQ      0x104
> -
> -#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_SRC * 0x20)
> -#define MPIC_CPU_REG_START        0x20000
> -#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
> +#define FSL_MPIC_20_TMR_IRQ      0x100
> +#define FSL_MPIC_20_IPI_IRQ      0x104
>
>  /*
>   * Block Revision Register1 (BRR1): QEMU does not fully emulate
> @@ -129,6 +116,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 */
>
> @@ -205,10 +193,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;
> @@ -231,15 +220,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);
> @@ -411,9 +400,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;
> @@ -506,7 +495,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 */
> @@ -971,7 +960,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);
> @@ -984,8 +973,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)
> @@ -1020,7 +1007,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);
> @@ -1034,7 +1021,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)
> @@ -1048,17 +1035,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 {

Sorry for not noticing this earlier, but this should be MemReg with
also a typedef.

> +    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,
> @@ -1068,16 +1056,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_FSL_MPIC_20:
> +    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 = FSL_MPIC_20_MAX_IRQ;
> +        opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
> +        opp->irq_tim0 = FSL_MPIC_20_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);
>
> @@ -1085,83 +1114,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_FSL_MPIC_20),
> +    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..e226d7b 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_FSL_MPIC_20 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..fa9b8ed 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_FSL_MPIC_20);
> +    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());
> --
> 1.6.0.2
>
>
Alexander Graf Dec. 14, 2012, 8:42 p.m. UTC | #2
On 14.12.2012, at 21:32, Blue Swirl wrote:

> On Fri, Dec 14, 2012 at 12:13 PM, Alexander Graf <agraf@suse.de> wrote:
>> This patch converts the OpenPIC device to qdev. Along the way it
>> renames the "openpic" target to "raven" and the "mpic" target to
>> "fsl_mpic_20", 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(-)
>> 
>> diff --git a/hw/openpic.c b/hw/openpic.c
>> index 5116b3e..591b291 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
>> 
>> @@ -54,30 +55,10 @@
>> #define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
>> #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
>> @@ -87,31 +68,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))
>> +
>> +/* FSL_MPIC_20 */
>> +#define FSL_MPIC_20_MAX_CPU      1
>> +#define FSL_MPIC_20_MAX_EXT     12
>> +#define FSL_MPIC_20_MAX_INT     64
>> +#define FSL_MPIC_20_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 FSL_MPIC_20_EXT_IRQ      0x00
>> +#define FSL_MPIC_20_INT_IRQ      0x10
>> +#define FSL_MPIC_20_MSG_IRQ      0xb0
>> +#define FSL_MPIC_20_MSI_IRQ      0xe0
>> /* These are available through separate regions, but
>>    for simplicity's sake mapped into the same number space */
>> -#define MPIC_TMR_IRQ      0x100
>> -#define MPIC_IPI_IRQ      0x104
>> -
>> -#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_SRC * 0x20)
>> -#define MPIC_CPU_REG_START        0x20000
>> -#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
>> +#define FSL_MPIC_20_TMR_IRQ      0x100
>> +#define FSL_MPIC_20_IPI_IRQ      0x104
>> 
>> /*
>>  * Block Revision Register1 (BRR1): QEMU does not fully emulate
>> @@ -129,6 +116,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 */
>> 
>> @@ -205,10 +193,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;
>> @@ -231,15 +220,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);
>> @@ -411,9 +400,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;
>> @@ -506,7 +495,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 */
>> @@ -971,7 +960,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);
>> @@ -984,8 +973,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)
>> @@ -1020,7 +1007,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);
>> @@ -1034,7 +1021,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)
>> @@ -1048,17 +1035,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 {
> 
> Sorry for not noticing this earlier, but this should be MemReg with
> also a typedef.

Ok, would you mind a follow-up patch?


Alex
Blue Swirl Dec. 14, 2012, 8:50 p.m. UTC | #3
On Fri, Dec 14, 2012 at 8:42 PM, Alexander Graf <agraf@suse.de> wrote:
>
> On 14.12.2012, at 21:32, Blue Swirl wrote:
>
>> On Fri, Dec 14, 2012 at 12:13 PM, Alexander Graf <agraf@suse.de> wrote:
>>> This patch converts the OpenPIC device to qdev. Along the way it
>>> renames the "openpic" target to "raven" and the "mpic" target to
>>> "fsl_mpic_20", 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(-)
>>>
>>> diff --git a/hw/openpic.c b/hw/openpic.c
>>> index 5116b3e..591b291 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
>>>
>>> @@ -54,30 +55,10 @@
>>> #define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
>>> #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
>>> @@ -87,31 +68,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))
>>> +
>>> +/* FSL_MPIC_20 */
>>> +#define FSL_MPIC_20_MAX_CPU      1
>>> +#define FSL_MPIC_20_MAX_EXT     12
>>> +#define FSL_MPIC_20_MAX_INT     64
>>> +#define FSL_MPIC_20_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 FSL_MPIC_20_EXT_IRQ      0x00
>>> +#define FSL_MPIC_20_INT_IRQ      0x10
>>> +#define FSL_MPIC_20_MSG_IRQ      0xb0
>>> +#define FSL_MPIC_20_MSI_IRQ      0xe0
>>> /* These are available through separate regions, but
>>>    for simplicity's sake mapped into the same number space */
>>> -#define MPIC_TMR_IRQ      0x100
>>> -#define MPIC_IPI_IRQ      0x104
>>> -
>>> -#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_SRC * 0x20)
>>> -#define MPIC_CPU_REG_START        0x20000
>>> -#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
>>> +#define FSL_MPIC_20_TMR_IRQ      0x100
>>> +#define FSL_MPIC_20_IPI_IRQ      0x104
>>>
>>> /*
>>>  * Block Revision Register1 (BRR1): QEMU does not fully emulate
>>> @@ -129,6 +116,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 */
>>>
>>> @@ -205,10 +193,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;
>>> @@ -231,15 +220,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);
>>> @@ -411,9 +400,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;
>>> @@ -506,7 +495,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 */
>>> @@ -971,7 +960,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);
>>> @@ -984,8 +973,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)
>>> @@ -1020,7 +1007,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);
>>> @@ -1034,7 +1021,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)
>>> @@ -1048,17 +1035,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 {
>>
>> Sorry for not noticing this earlier, but this should be MemReg with
>> also a typedef.
>
> Ok, would you mind a follow-up patch?

OK.

>
>
> Alex
>
diff mbox

Patch

diff --git a/hw/openpic.c b/hw/openpic.c
index 5116b3e..591b291 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
 
@@ -54,30 +55,10 @@ 
 #define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
 #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
@@ -87,31 +68,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))
+
+/* FSL_MPIC_20 */
+#define FSL_MPIC_20_MAX_CPU      1
+#define FSL_MPIC_20_MAX_EXT     12
+#define FSL_MPIC_20_MAX_INT     64
+#define FSL_MPIC_20_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 FSL_MPIC_20_EXT_IRQ      0x00
+#define FSL_MPIC_20_INT_IRQ      0x10
+#define FSL_MPIC_20_MSG_IRQ      0xb0
+#define FSL_MPIC_20_MSI_IRQ      0xe0
 /* These are available through separate regions, but
    for simplicity's sake mapped into the same number space */
-#define MPIC_TMR_IRQ      0x100
-#define MPIC_IPI_IRQ      0x104
-
-#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_SRC * 0x20)
-#define MPIC_CPU_REG_START        0x20000
-#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
+#define FSL_MPIC_20_TMR_IRQ      0x100
+#define FSL_MPIC_20_IPI_IRQ      0x104
 
 /*
  * Block Revision Register1 (BRR1): QEMU does not fully emulate
@@ -129,6 +116,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 */
 
@@ -205,10 +193,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;
@@ -231,15 +220,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);
@@ -411,9 +400,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;
@@ -506,7 +495,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 */
@@ -971,7 +960,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);
@@ -984,8 +973,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)
@@ -1020,7 +1007,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);
@@ -1034,7 +1021,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)
@@ -1048,17 +1035,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,
@@ -1068,16 +1056,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_FSL_MPIC_20:
+    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 = FSL_MPIC_20_MAX_IRQ;
+        opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
+        opp->irq_tim0 = FSL_MPIC_20_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);
 
@@ -1085,83 +1114,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_FSL_MPIC_20),
+    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..e226d7b 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_FSL_MPIC_20 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..fa9b8ed 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_FSL_MPIC_20);
+    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());