/*
* IRQ descriptor to catch the following cases:
+ * - An IRQ can either connect to the GICs, to the PPU1 intc, or the the EAM
* - Multiple devices can connect to the same IRQ. They are OR'ed together.
*/
FIELD(VERSAL_IRQ, IRQ, 0, 16)
+FIELD(VERSAL_IRQ, TARGET, 16, 2)
FIELD(VERSAL_IRQ, ORED, 18, 1)
FIELD(VERSAL_IRQ, OR_IDX, 19, 4) /* input index on the IRQ OR gate */
+typedef enum VersalIrqTarget {
+ IRQ_TARGET_GIC,
+ IRQ_TARGET_PPU1,
+ IRQ_TARGET_EAM,
+} VersalIrqTarget;
+
+#define PPU1_IRQ(irq) ((IRQ_TARGET_PPU1 << R_VERSAL_IRQ_TARGET_SHIFT) | (irq))
+#define EAM_IRQ(irq) ((IRQ_TARGET_EAM << R_VERSAL_IRQ_TARGET_SHIFT) | (irq))
#define OR_IRQ(irq, or_idx) \
(R_VERSAL_IRQ_ORED_MASK | ((or_idx) << R_VERSAL_IRQ_OR_IDX_SHIFT) | (irq))
+#define PPU1_OR_IRQ(irq, or_idx) \
+ ((IRQ_TARGET_PPU1 << R_VERSAL_IRQ_TARGET_SHIFT) | OR_IRQ(irq, or_idx))
typedef struct VersalSimplePeriphMap {
uint64_t addr;
static qemu_irq versal_get_irq_or_gate_in(Versal *s, int irq_idx,
qemu_irq target_irq)
{
+ static const char *TARGET_STR[] = {
+ [IRQ_TARGET_GIC] = "gic",
+ [IRQ_TARGET_PPU1] = "ppu1",
+ [IRQ_TARGET_EAM] = "eam",
+ };
+
+ VersalIrqTarget target;
Object *container = versal_get_child(s, "irq-or-gates");
DeviceState *dev;
g_autofree char *name;
idx = FIELD_EX32(irq_idx, VERSAL_IRQ, IRQ);
or_idx = FIELD_EX32(irq_idx, VERSAL_IRQ, OR_IDX);
+ target = FIELD_EX32(irq_idx, VERSAL_IRQ, TARGET);
- name = g_strdup_printf("irq[%d]", idx);
+ name = g_strdup_printf("%s-irq[%d]", TARGET_STR[target], idx);
dev = DEVICE(object_resolve_path_at(container, name));
if (dev == NULL) {
static qemu_irq versal_get_irq(Versal *s, int irq_idx)
{
+ VersalIrqTarget target;
qemu_irq irq;
bool ored;
+ target = FIELD_EX32(irq_idx, VERSAL_IRQ, TARGET);
ored = FIELD_EX32(irq_idx, VERSAL_IRQ, ORED);
- irq = versal_get_gic_irq(s, irq_idx);
+ switch (target) {
+ case IRQ_TARGET_EAM:
+ /* EAM not implemented */
+ return NULL;
+
+ case IRQ_TARGET_PPU1:
+ /* PPU1 CPU not implemented */
+ return NULL;
+
+ case IRQ_TARGET_GIC:
+ irq = versal_get_gic_irq(s, irq_idx);
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
if (ored) {
irq = versal_get_irq_or_gate_in(s, irq_idx, irq);