Add the instance of the GIC ITS in the APU. Signed-off-by: Luc Michel <luc.mic...@amd.com> Reviewed-by: Francisco Iglesias <francisco.igles...@amd.com> --- hw/arm/xlnx-versal.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 6374a8de4c7..d11ff5aaf24 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -42,10 +42,11 @@ #include "hw/misc/xlnx-versal-cfu.h" #include "hw/misc/xlnx-versal-cframe-reg.h" #include "hw/or-irq.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/intc/arm_gicv3_common.h" +#include "hw/intc/arm_gicv3_its_common.h" #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f") #define GEM_REVISION 0x40070106 @@ -70,11 +71,13 @@ typedef struct VersalSimplePeriphMap { typedef struct VersalGicMap { int version; uint64_t dist; uint64_t redist; + uint64_t its; size_t num_irq; + bool has_its; } VersalGicMap; enum StartPoweredOffMode { SPO_SECONDARIES, SPO_ALL, @@ -213,10 +216,12 @@ static const VersalMap VERSAL_MAP = { .gic = { .version = 3, .dist = 0xf9000000, .redist = 0xf9080000, .num_irq = 192, + .has_its = true, + .its = 0xf9020000, }, }, .uart[0] = { 0xff000000, 18 }, .uart[1] = { 0xff010000, 19 }, @@ -449,10 +454,52 @@ static MemoryRegion *create_cpu_mr(Versal *s, DeviceState *cluster, memory_region_add_subregion(mr, 0, root_alias); return mr; } +static void versal_create_gic_its(Versal *s, + const VersalCpuClusterMap *map, + DeviceState *gic, + MemoryRegion *mr, + char *gic_node) +{ + DeviceState *dev; + SysBusDevice *sbd; + g_autofree char *node_pat = NULL, *node = NULL; + const char compatible[] = "arm,gic-v3-its"; + + if (!map->gic.has_its) { + return; + } + + dev = qdev_new(TYPE_ARM_GICV3_ITS); + sbd = SYS_BUS_DEVICE(dev); + + object_property_add_child(OBJECT(gic), "its", OBJECT(dev)); + object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(gic), + &error_abort); + + sysbus_realize_and_unref(sbd, &error_abort); + + memory_region_add_subregion(mr, map->gic.its, + sysbus_mmio_get_region(sbd, 0)); + + if (!map->dtb_expose) { + return; + } + + qemu_fdt_setprop(s->cfg.fdt, gic_node, "ranges", NULL, 0); + qemu_fdt_setprop_cell(s->cfg.fdt, gic_node, "#address-cells", 2); + qemu_fdt_setprop_cell(s->cfg.fdt, gic_node, "#size-cells", 2); + + node_pat = g_strdup_printf("%s/its", gic_node); + node = versal_fdt_add_simple_subnode(s, node_pat, map->gic.its, 0x20000, + compatible, sizeof(compatible)); + qemu_fdt_setprop(s->cfg.fdt, node, "msi-controller", NULL, 0); + qemu_fdt_setprop_cell(s->cfg.fdt, node, "#msi-cells", 1); +} + static DeviceState *versal_create_gic(Versal *s, const VersalCpuClusterMap *map, MemoryRegion *mr, size_t num_cpu) { @@ -474,10 +521,11 @@ static DeviceState *versal_create_gic(Versal *s, redist_region_count = qlist_new(); qlist_append_int(redist_region_count, num_cpu); qdev_prop_set_array(dev, "redist-region-count", redist_region_count); qdev_prop_set_bit(dev, "has-security-extensions", true); + qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its); object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), &error_abort); sysbus_realize_and_unref(sbd, &error_fatal); memory_region_add_subregion(mr, map->gic.dist, @@ -499,10 +547,12 @@ static DeviceState *versal_create_gic(Versal *s, GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ, GIC_FDT_IRQ_FLAGS_LEVEL_HI); qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0); } + versal_create_gic_its(s, map, dev, mr, node); + return dev; } static void connect_gic_to_cpu(const VersalCpuClusterMap *map, DeviceState *gic, DeviceState *cpu, size_t idx, -- 2.50.1