1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "hw/intc/xlnx_scu_gic.h"
27#include "hw/fdt_generic_util.h"
28
29
30
31#define MAX_SPI (32 * 5)
32
33static int xlnx_scu_gic_inject_error(XlnxSCUGICState *s, int irq, int level)
34{
35 bool inject;
36 uint8_t i;
37
38 assert(irq < MAX_SPI);
39 inject = 0;
40 for (i = 0; i < XLNX_SCU_GIC_MAX_INJECTOR; i++) {
41 inject |= s->intr_inj[i][irq / 32] & (1 << irq % 32);
42 }
43
44 return ((level != 0) || inject);
45}
46
47static void xlnx_scu_gic_set_irq(void *opaque, int irq, int level)
48{
49 XlnxSCUGICState *s = XLNX_SCU_GIC(opaque);
50 XlnxSCUGICClass *agc = XLNX_SCU_GIC_GET_CLASS(opaque);
51
52 if (irq < MAX_SPI) {
53
54
55
56 s->ext_level[irq / 32] = deposit32(s->ext_level[irq / 32], irq % 32, 1,
57 level);
58
59 level = xlnx_scu_gic_inject_error(s, irq, level);
60 }
61
62 agc->parent_irq_handler(opaque, irq, level);
63}
64
65static void xlnx_scu_gic_update_irq(XlnxSCUGICState *s, unsigned int reg)
66{
67 XlnxSCUGICClass *agc = XLNX_SCU_GIC_GET_CLASS(s);
68 int irq, level;
69
70 for (irq = reg * 32; irq < (reg + 1) * 32; irq++) {
71 level = xlnx_scu_gic_inject_error(s, irq,
72 s->ext_level[irq / 32] &
73 (1 << irq % 32));
74 agc->parent_irq_handler(s, irq, level);
75 }
76}
77
78void xlnx_scu_gic_set_intr(XlnxSCUGICState *s, unsigned int reg, uint32_t val,
79 uint8_t injector)
80{
81 assert(reg < XLNX_SCU_GIC_IRQ_REG);
82
83 s->intr_inj[injector][reg] = val;
84 xlnx_scu_gic_update_irq(s, reg);
85}
86
87static void xlnx_scu_gic_class_init(ObjectClass *klass, void *data)
88{
89 ARMGICClass *agc = ARM_GIC_CLASS(klass);
90 XlnxSCUGICClass *xsgc = XLNX_SCU_GIC_CLASS(klass);
91
92 xsgc->parent_irq_handler = agc->irq_handler;
93 agc->irq_handler = xlnx_scu_gic_set_irq;
94}
95
96static const TypeInfo xlnx_scu_gic_info = {
97 .name = TYPE_XLNX_SCU_GIC,
98 .parent = TYPE_ARM_GIC,
99 .instance_size = sizeof(XlnxSCUGICState),
100 .class_init = xlnx_scu_gic_class_init,
101 .class_size = sizeof(XlnxSCUGICClass),
102};
103
104static void xlnx_scu_gic_register_types(void)
105{
106 type_register_static(&xlnx_scu_gic_info);
107}
108
109type_init(xlnx_scu_gic_register_types)
110