On Fri, Dec 14, 2012 at 12:13 PM, Alexander Graf <ag...@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 <ag...@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 > >