On Thu, May 07, 2015 at 05:57:12PM -0700, Peter Crosthwaite wrote: > Add the GIC and connect IRQ outputs to the CPUs. The GIC regions are > under-decoded through a 64k address region so implement aliases > accordingly. > > Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com> > --- > changed since v7: > Made GIC region size definition board specific > changed since v6: > Added aliases. > changed since v5: > Make commit msg body standalone > Add reset-cbar configuration > > hw/arm/xlnx-zynqmp.c | 59 > ++++++++++++++++++++++++++++++++++++++++++++ > include/hw/arm/xlnx-zynqmp.h | 14 +++++++++++ > 2 files changed, 73 insertions(+) > > diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c > index ec0ebaa..a8ab7e7 100644 > --- a/hw/arm/xlnx-zynqmp.c > +++ b/hw/arm/xlnx-zynqmp.c > @@ -16,6 +16,23 @@ > */ > > #include "hw/arm/xlnx-zynqmp.h" > +#include "exec/address-spaces.h" > + > +#define GIC_NUM_SPI_INTR 128
Is this correct? I think it should be 160. > + > +#define GIC_BASE_ADDR 0xf9000000 > +#define GIC_DIST_ADDR 0xf9010000 > +#define GIC_CPU_ADDR 0xf9020000 > + > +typedef struct XlnxZynqMPGICRegion { > + int region_index; > + uint32_t address; > +} XlnxZynqMPGICRegion; > + > +static const XlnxZynqMPGICRegion xlnx_zynqmp_gic_regions[] = { > + { .region_index = 0, .address = GIC_DIST_ADDR, }, > + { .region_index = 1, .address = GIC_CPU_ADDR, }, > +}; > > static void xlnx_zynqmp_init(Object *obj) > { > @@ -28,14 +45,46 @@ static void xlnx_zynqmp_init(Object *obj) > object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpu[i]), > &error_abort); > } > + > + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); > + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); > } > > static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) > { > XlnxZynqMPState *s = XLNX_ZYNQMP(dev); > + MemoryRegion *system_memory = get_system_memory(); > uint8_t i; > Error *err = NULL; > > + qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32); > + qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); > + qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_CPUS); > + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); > + if (err) { > + error_propagate((errp), (err)); > + return; > + } > + assert(ARRAY_SIZE(xlnx_zynqmp_gic_regions) == XLNX_ZYNQMP_GIC_REGIONS); > + for (i = 0; i < XLNX_ZYNQMP_GIC_REGIONS; i++) { > + SysBusDevice *gic = SYS_BUS_DEVICE(&s->gic); > + const XlnxZynqMPGICRegion *r = &xlnx_zynqmp_gic_regions[i]; > + MemoryRegion *mr = sysbus_mmio_get_region(gic, r->region_index); > + uint32_t addr = r->address; > + int j; > + > + sysbus_mmio_map(gic, r->region_index, addr); > + > + for (j = 0; j < XLNX_ZYNQMP_GIC_ALIASES; j++) { > + MemoryRegion *alias = &s->gic_mr[i][j]; > + > + addr += XLNX_ZYNQMP_GIC_REGION_SIZE; > + memory_region_init_alias(alias, OBJECT(s), "zynqmp-gic-alias", > mr, > + 0, XLNX_ZYNQMP_GIC_REGION_SIZE); > + memory_region_add_subregion(system_memory, addr, alias); > + } > + } > + > for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) { > object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC, > "psci-conduit", &error_abort); > @@ -45,11 +94,21 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error > **errp) > "start-powered-off", &error_abort); > } > > + object_property_set_int(OBJECT(&s->cpu[i]), GIC_BASE_ADDR, > + "reset-cbar", &err); > + if (err) { > + error_propagate((errp), (err)); > + return; > + } > + > object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); > if (err) { > error_propagate((errp), (err)); > return; > } > + > + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i, > + qdev_get_gpio_in(DEVICE(&s->cpu[i]), > ARM_CPU_IRQ)); > } > } > > diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h > index 62f6b6f..719bc8b 100644 > --- a/include/hw/arm/xlnx-zynqmp.h > +++ b/include/hw/arm/xlnx-zynqmp.h > @@ -19,6 +19,7 @@ > > #include "qemu-common.h" > #include "hw/arm/arm.h" > +#include "hw/intc/arm_gic.h" > > #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" > #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ > @@ -26,12 +27,25 @@ > > #define XLNX_ZYNQMP_NUM_CPUS 4 > > +#define XLNX_ZYNQMP_GIC_REGIONS 2 > + > +/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k > offsets > + * and under-decodes the 64k region. This mirrors the 4k regions to every 4k > + * aligned address in the 64k region. To implement each GIC region needs a > + * number of memory region aliases. > + */ > + > +#define XLNX_ZYNQMP_GIC_REGION_SIZE 0x4000 > +#define XLNX_ZYNQMP_GIC_ALIASES (0x10000 / XLNX_ZYNQMP_GIC_REGION_SIZE - > 1) > + > typedef struct XlnxZynqMPState { > /*< private >*/ > DeviceState parent_obj; > > /*< public >*/ > ARMCPU cpu[XLNX_ZYNQMP_NUM_CPUS]; > + GICState gic; > + MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES]; > } XlnxZynqMPState; > > #define XLNX_ZYNQMP_H > -- > 2.4.0.3.ge0ccc3b.dirty >