mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
hw/arm/xlnx-versal: add support for multiple GICs
The Versal SoC contains two GICs: one GICv3 in the APU and one GICv2 in the RPU (currently not instantiated). To prepare for the GICv2 instantiation, add support for multiple GICs when connecting interrupts. When a GIC is created, the first-cpu-index property is set on it, and a pointer to the GIC is stored in the intc array. When connecting an IRQ, a TYPE_SPLIT_IRQ device is created with its num-lines property set to the number of GICs in the SoC. The split device is used to fan out the IRQ to all the GICs. 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-25-luc.michel@amd.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
committed by
Peter Maydell
parent
27493e5e68
commit
d95bf38556
+52
-4
@@ -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/core/split-irq.h"
|
||||
|
||||
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
|
||||
#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
|
||||
@@ -317,6 +318,43 @@ static inline Object *versal_get_child_idx(Versal *s, const char *child,
|
||||
return versal_get_child(s, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* The SoC embeds multiple GICs. They all receives the same IRQ lines at the
|
||||
* same index. This function creates a TYPE_SPLIT_IRQ device to fan out the
|
||||
* given IRQ input to all the GICs.
|
||||
*
|
||||
* The TYPE_SPLIT_IRQ devices lie in the /soc/irq-splits QOM container
|
||||
*/
|
||||
static qemu_irq versal_get_gic_irq(Versal *s, int irq_idx)
|
||||
{
|
||||
DeviceState *split;
|
||||
Object *container = versal_get_child(s, "irq-splits");
|
||||
int idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
|
||||
g_autofree char *name = g_strdup_printf("irq[%d]", idx);
|
||||
|
||||
split = DEVICE(object_resolve_path_at(container, name));
|
||||
|
||||
if (split == NULL) {
|
||||
size_t i;
|
||||
|
||||
split = qdev_new(TYPE_SPLIT_IRQ);
|
||||
qdev_prop_set_uint16(split, "num-lines", s->intc->len);
|
||||
object_property_add_child(container, name, OBJECT(split));
|
||||
qdev_realize_and_unref(split, NULL, &error_abort);
|
||||
|
||||
for (i = 0; i < s->intc->len; i++) {
|
||||
DeviceState *gic;
|
||||
|
||||
gic = g_array_index(s->intc, DeviceState *, i);
|
||||
qdev_connect_gpio_out(split, i, qdev_get_gpio_in(gic, idx));
|
||||
}
|
||||
} else {
|
||||
g_assert(FIELD_EX32(irq_idx, VERSAL_IRQ, ORED));
|
||||
}
|
||||
|
||||
return qdev_get_gpio_in(split, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the R_VERSAL_IRQ_ORED flag is set on an IRQ descriptor, this function is
|
||||
* used to return the corresponding or gate input IRQ. The or gate is created if
|
||||
@@ -353,12 +391,10 @@ static qemu_irq versal_get_irq(Versal *s, int irq_idx)
|
||||
{
|
||||
qemu_irq irq;
|
||||
bool ored;
|
||||
DeviceState *gic;
|
||||
|
||||
ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
|
||||
|
||||
gic = DEVICE(versal_get_child_idx(s, "apu-gic", 0));
|
||||
irq = qdev_get_gpio_in(gic, FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ));
|
||||
irq = versal_get_gic_irq(s, irq_idx);
|
||||
|
||||
if (ored) {
|
||||
irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
|
||||
@@ -501,6 +537,7 @@ static void versal_create_gic_its(Versal *s,
|
||||
static DeviceState *versal_create_gic(Versal *s,
|
||||
const VersalCpuClusterMap *map,
|
||||
MemoryRegion *mr,
|
||||
int first_cpu_idx,
|
||||
size_t num_cpu)
|
||||
{
|
||||
DeviceState *dev;
|
||||
@@ -525,6 +562,7 @@ static DeviceState *versal_create_gic(Versal *s,
|
||||
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);
|
||||
|
||||
sysbus_realize_and_unref(sbd, &error_fatal);
|
||||
|
||||
@@ -551,6 +589,8 @@ static DeviceState *versal_create_gic(Versal *s,
|
||||
|
||||
versal_create_gic_its(s, map, dev, mr, node);
|
||||
|
||||
g_array_append_val(s->intc, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -608,9 +648,11 @@ static inline void versal_create_and_connect_gic(Versal *s,
|
||||
size_t num_cpu)
|
||||
{
|
||||
DeviceState *gic;
|
||||
int first_cpu_idx;
|
||||
size_t i;
|
||||
|
||||
gic = versal_create_gic(s, map, mr, num_cpu);
|
||||
first_cpu_idx = CPU(cpus[0])->cpu_index;
|
||||
gic = versal_create_gic(s, map, mr, first_cpu_idx, num_cpu);
|
||||
|
||||
for (i = 0; i < num_cpu; i++) {
|
||||
connect_gic_to_cpu(map, gic, cpus[i], i, num_cpu);
|
||||
@@ -1539,6 +1581,10 @@ static void versal_realize(DeviceState *dev, Error **errp)
|
||||
s->phandle.clk_125mhz = fdt_add_clk_node(s, "/clk125", 125 * 1000 * 1000);
|
||||
s->phandle.gic = qemu_fdt_alloc_phandle(s->cfg.fdt);
|
||||
|
||||
container = object_new(TYPE_CONTAINER);
|
||||
object_property_add_child(OBJECT(s), "irq-splits", container);
|
||||
object_unref(container);
|
||||
|
||||
container = object_new(TYPE_CONTAINER);
|
||||
object_property_add_child(OBJECT(s), "irq-or-gates", container);
|
||||
object_unref(container);
|
||||
@@ -1720,6 +1766,7 @@ static void versal_base_init(Object *obj)
|
||||
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
|
||||
memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
|
||||
"mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
|
||||
s->intc = g_array_new(false, false, sizeof(DeviceState *));
|
||||
|
||||
num_can = versal_get_map(s)->num_canfd;
|
||||
s->cfg.canbus = g_new0(CanBusState *, num_can);
|
||||
@@ -1737,6 +1784,7 @@ static void versal_base_finalize(Object *obj)
|
||||
{
|
||||
Versal *s = XLNX_VERSAL_BASE(obj);
|
||||
|
||||
g_array_free(s->intc, true);
|
||||
g_free(s->cfg.canbus);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ struct Versal {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
GArray *intc;
|
||||
MemoryRegion mr_ps;
|
||||
|
||||
struct {
|
||||
|
||||
Reference in New Issue
Block a user