#define VERSAL_NUM_PMC_APB_IRQS 18
#define NUM_OSPI_IRQ_LINES 3
+/*
+ * IRQ descriptor to catch the following cases:
+ * - Multiple devices can connect to the same IRQ. They are OR'ed together.
+ */
+FIELD(VERSAL_IRQ, IRQ, 0, 16)
+FIELD(VERSAL_IRQ, ORED, 18, 1)
+FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
+
+#define OR_IRQ(irq, or_idx) \
+ (R_VERSAL_IRQ_ORED_MASK | ((or_idx) << R_VERSAL_IRQ_OR_IDX_SHIFT) | (irq))
+
typedef struct VersalSimplePeriphMap {
uint64_t addr;
int irq;
return versal_get_child(s, n);
}
+/*
+ * 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
+ * not already existant.
+ *
+ * Or gates are placed under the /soc/irq-or-gates QOM container.
+ */
+static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
+ qemu_irq target_irq)
+{
+ Object *container = versal_get_child(s, "irq-or-gates");
+ DeviceState *dev;
+ g_autofree char *name;
+ int idx, or_idx;
+
+ idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
+ or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
+
+ name = g_strdup_printf("irq[%d]", idx);
+ dev = DEVICE(object_resolve_path_at(container, name));
+
+ if (dev == NULL) {
+ dev = qdev_new(TYPE_OR_IRQ);
+ object_property_add_child(container, name, OBJECT(dev));
+ qdev_prop_set_uint16(dev, "num-lines", 1 << R_VERSAL_IRQ_OR_IDX_LENGTH);
+ qdev_realize_and_unref(dev, NULL, &error_abort);
+ qdev_connect_gpio_out(dev, 0, target_irq);
+ }
+
+ return qdev_get_gpio_in(dev, or_idx);
+}
+
static qemu_irq versal_get_irq(Versal *s, int irq_idx)
{
- return qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic), irq_idx);
+ qemu_irq irq;
+ bool ored;
+
+ ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
+
+ irq = qdev_get_gpio_in(DEVICE(&s->fpd.apu.gic),
+ FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ));
+
+ if (ored) {
+ irq = versal_get_irq_or_gate_in(s, irq_idx, irq);
+ }
+
+ return irq;
}
static void versal_sysbus_connect_irq(Versal *s, SysBusDevice *sbd,
{
Versal *s = XLNX_VERSAL_BASE(dev);
qemu_irq pic[XLNX_VERSAL_NR_IRQS];
+ Object *container;
const VersalMap *map = versal_get_map(s);
size_t i;
versal_create_apu_cpus(s);
versal_create_apu_gic(s, pic);
+
+ container = object_new(TYPE_CONTAINER);
+ object_property_add_child(OBJECT(s), "irq-or-gates", container);
+ object_unref(container);
+
versal_create_rpu_cpus(s);
for (i = 0; i < map->num_uart; i++) {