Add the instance of the GIC ITS in the APU.
Signed-off-by: Luc Michel <luc.michel@amd.com>
Reviewed-by: Francisco Iglesias <francisco.iglesias@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 f4b9f419728..6252e0742c4 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