mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
hw/arm/xlnx-versal: add support for GICv2
Add support for GICv2 instantiation in the Versal SoC. This is in preparation for the RPU refactoring. Signed-off-by: Luc Michel <luc.michel@amd.com> Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20250926070806.292065-26-luc.michel@amd.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
committed by
Peter Maydell
parent
d95bf38556
commit
0dfff625b5
+62
-20
@@ -45,6 +45,7 @@
|
||||
#include "hw/misc/xlnx-versal-crl.h"
|
||||
#include "hw/intc/arm_gicv3_common.h"
|
||||
#include "hw/intc/arm_gicv3_its_common.h"
|
||||
#include "hw/intc/arm_gic.h"
|
||||
#include "hw/core/split-irq.h"
|
||||
|
||||
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
|
||||
@@ -74,6 +75,7 @@ typedef struct VersalGicMap {
|
||||
int version;
|
||||
uint64_t dist;
|
||||
uint64_t redist;
|
||||
uint64_t cpu_iface;
|
||||
uint64_t its;
|
||||
size_t num_irq;
|
||||
bool has_its;
|
||||
@@ -503,6 +505,10 @@ static void versal_create_gic_its(Versal *s,
|
||||
g_autofree char *node_pat = NULL, *node = NULL;
|
||||
const char compatible[] = "arm,gic-v3-its";
|
||||
|
||||
if (map->gic.version != 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!map->gic.has_its) {
|
||||
return;
|
||||
}
|
||||
@@ -542,45 +548,81 @@ static DeviceState *versal_create_gic(Versal *s,
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sbd;
|
||||
QList *redist_region_count;
|
||||
g_autofree char *node = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
const char compatible[] = "arm,gic-v3";
|
||||
const char gicv3_compat[] = "arm,gic-v3";
|
||||
const char gicv2_compat[] = "arm,cortex-a15-gic";
|
||||
|
||||
switch (map->gic.version) {
|
||||
case 2:
|
||||
dev = qdev_new(gic_class_name());
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dev = qdev_new(gicv3_class_name());
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
dev = qdev_new(gicv3_class_name());
|
||||
name = g_strdup_printf("%s-gic[*]", map->name);
|
||||
object_property_add_child(OBJECT(s), name, OBJECT(dev));
|
||||
sbd = SYS_BUS_DEVICE(dev);
|
||||
qdev_prop_set_uint32(dev, "revision", 3);
|
||||
qdev_prop_set_uint32(dev, "revision", map->gic.version);
|
||||
qdev_prop_set_uint32(dev, "num-cpu", num_cpu);
|
||||
qdev_prop_set_uint32(dev, "num-irq", map->gic.num_irq + 32);
|
||||
|
||||
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);
|
||||
qdev_prop_set_uint32(dev, "first-cpu-index", first_cpu_idx);
|
||||
|
||||
if (map->gic.version == 3) {
|
||||
QList *redist_region_count;
|
||||
|
||||
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-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,
|
||||
sysbus_mmio_get_region(sbd, 0));
|
||||
memory_region_add_subregion(mr, map->gic.redist,
|
||||
sysbus_mmio_get_region(sbd, 1));
|
||||
|
||||
if (map->gic.version == 3) {
|
||||
memory_region_add_subregion(mr, map->gic.redist,
|
||||
sysbus_mmio_get_region(sbd, 1));
|
||||
} else {
|
||||
memory_region_add_subregion(mr, map->gic.cpu_iface,
|
||||
sysbus_mmio_get_region(sbd, 1));
|
||||
}
|
||||
|
||||
if (map->dtb_expose) {
|
||||
node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, compatible,
|
||||
sizeof(compatible));
|
||||
if (map->gic.version == 3) {
|
||||
node = versal_fdt_add_subnode(s, "/gic", map->gic.dist,
|
||||
gicv3_compat,
|
||||
sizeof(gicv3_compat));
|
||||
qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
|
||||
2, map->gic.dist,
|
||||
2, 0x10000,
|
||||
2, map->gic.redist,
|
||||
2, GICV3_REDIST_SIZE * num_cpu);
|
||||
} else {
|
||||
node = versal_fdt_add_subnode(s, "/gic", map->gic.dist,
|
||||
gicv2_compat,
|
||||
sizeof(gicv2_compat));
|
||||
qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
|
||||
2, map->gic.dist,
|
||||
2, 0x1000,
|
||||
2, map->gic.cpu_iface,
|
||||
2, 0x1000);
|
||||
}
|
||||
|
||||
qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic);
|
||||
qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3);
|
||||
qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg",
|
||||
2, map->gic.dist,
|
||||
2, 0x10000,
|
||||
2, map->gic.redist,
|
||||
2, GICV3_REDIST_SIZE * num_cpu);
|
||||
qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts",
|
||||
GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
|
||||
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||
|
||||
Reference in New Issue
Block a user