2 * SPDX-License-Identifier: GPL-2.0-or-later
6 * (c) 2020 Laurent Vivier <laurent@vivier.eu>
10 #include "qemu/osdep.h"
12 #include "hw/qdev-properties.h"
13 #include "hw/sysbus.h"
14 #include "migration/vmstate.h"
15 #include "monitor/monitor.h"
18 #include "hw/intc/intc.h"
19 #include "hw/intc/goldfish_pic.h"
25 REG_IRQ_PENDING
= 0x04,
26 REG_IRQ_DISABLE_ALL
= 0x08,
31 static bool goldfish_pic_get_statistics(InterruptStatsProvider
*obj
,
32 uint64_t **irq_counts
,
33 unsigned int *nb_irqs
)
35 GoldfishPICState
*s
= GOLDFISH_PIC(obj
);
37 *irq_counts
= s
->stats_irq_count
;
38 *nb_irqs
= ARRAY_SIZE(s
->stats_irq_count
);
42 static void goldfish_pic_print_info(InterruptStatsProvider
*obj
, Monitor
*mon
)
44 GoldfishPICState
*s
= GOLDFISH_PIC(obj
);
45 monitor_printf(mon
, "goldfish-pic.%d: pending=0x%08x enabled=0x%08x\n",
46 s
->idx
, s
->pending
, s
->enabled
);
49 static void goldfish_pic_update(GoldfishPICState
*s
)
51 if (s
->pending
& s
->enabled
) {
52 qemu_irq_raise(s
->irq
);
54 qemu_irq_lower(s
->irq
);
58 static void goldfish_irq_request(void *opaque
, int irq
, int level
)
60 GoldfishPICState
*s
= opaque
;
62 trace_goldfish_irq_request(s
, s
->idx
, irq
, level
);
65 s
->pending
|= 1 << irq
;
66 s
->stats_irq_count
[irq
]++;
68 s
->pending
&= ~(1 << irq
);
70 goldfish_pic_update(s
);
73 static uint64_t goldfish_pic_read(void *opaque
, hwaddr addr
,
76 GoldfishPICState
*s
= opaque
;
81 /* The number of pending interrupts (0 to 32) */
82 value
= ctpop32(s
->pending
& s
->enabled
);
85 /* The pending interrupt mask */
86 value
= s
->pending
& s
->enabled
;
89 qemu_log_mask(LOG_UNIMP
,
90 "%s: unimplemented register read 0x%02"HWADDR_PRIx
"\n",
95 trace_goldfish_pic_read(s
, s
->idx
, addr
, size
, value
);
100 static void goldfish_pic_write(void *opaque
, hwaddr addr
,
101 uint64_t value
, unsigned size
)
103 GoldfishPICState
*s
= opaque
;
105 trace_goldfish_pic_write(s
, s
->idx
, addr
, size
, value
);
108 case REG_IRQ_DISABLE_ALL
:
113 s
->enabled
&= ~value
;
119 qemu_log_mask(LOG_UNIMP
,
120 "%s: unimplemented register write 0x%02"HWADDR_PRIx
"\n",
124 goldfish_pic_update(s
);
127 static const MemoryRegionOps goldfish_pic_ops
= {
128 .read
= goldfish_pic_read
,
129 .write
= goldfish_pic_write
,
130 .endianness
= DEVICE_NATIVE_ENDIAN
,
131 .valid
.max_access_size
= 4,
132 .impl
.min_access_size
= 4,
133 .impl
.max_access_size
= 4,
136 static void goldfish_pic_reset(DeviceState
*dev
)
138 GoldfishPICState
*s
= GOLDFISH_PIC(dev
);
141 trace_goldfish_pic_reset(s
, s
->idx
);
145 for (i
= 0; i
< ARRAY_SIZE(s
->stats_irq_count
); i
++) {
146 s
->stats_irq_count
[i
] = 0;
150 static void goldfish_pic_realize(DeviceState
*dev
, Error
**errp
)
152 GoldfishPICState
*s
= GOLDFISH_PIC(dev
);
154 trace_goldfish_pic_realize(s
, s
->idx
);
156 memory_region_init_io(&s
->iomem
, OBJECT(s
), &goldfish_pic_ops
, s
,
157 "goldfish_pic", 0x24);
160 static const VMStateDescription vmstate_goldfish_pic
= {
161 .name
= "goldfish_pic",
163 .minimum_version_id
= 1,
164 .fields
= (VMStateField
[]) {
165 VMSTATE_UINT32(pending
, GoldfishPICState
),
166 VMSTATE_UINT32(enabled
, GoldfishPICState
),
167 VMSTATE_END_OF_LIST()
171 static void goldfish_pic_instance_init(Object
*obj
)
173 SysBusDevice
*dev
= SYS_BUS_DEVICE(obj
);
174 GoldfishPICState
*s
= GOLDFISH_PIC(obj
);
176 trace_goldfish_pic_instance_init(s
);
178 sysbus_init_mmio(dev
, &s
->iomem
);
179 sysbus_init_irq(dev
, &s
->irq
);
181 qdev_init_gpio_in(DEVICE(obj
), goldfish_irq_request
, GOLDFISH_PIC_IRQ_NB
);
184 static Property goldfish_pic_properties
[] = {
185 DEFINE_PROP_UINT8("index", GoldfishPICState
, idx
, 0),
186 DEFINE_PROP_END_OF_LIST(),
189 static void goldfish_pic_class_init(ObjectClass
*oc
, void *data
)
191 DeviceClass
*dc
= DEVICE_CLASS(oc
);
192 InterruptStatsProviderClass
*ic
= INTERRUPT_STATS_PROVIDER_CLASS(oc
);
194 dc
->reset
= goldfish_pic_reset
;
195 dc
->realize
= goldfish_pic_realize
;
196 dc
->vmsd
= &vmstate_goldfish_pic
;
197 ic
->get_statistics
= goldfish_pic_get_statistics
;
198 ic
->print_info
= goldfish_pic_print_info
;
199 device_class_set_props(dc
, goldfish_pic_properties
);
202 static const TypeInfo goldfish_pic_info
= {
203 .name
= TYPE_GOLDFISH_PIC
,
204 .parent
= TYPE_SYS_BUS_DEVICE
,
205 .class_init
= goldfish_pic_class_init
,
206 .instance_init
= goldfish_pic_instance_init
,
207 .instance_size
= sizeof(GoldfishPICState
),
208 .interfaces
= (InterfaceInfo
[]) {
209 { TYPE_INTERRUPT_STATS_PROVIDER
},
214 static void goldfish_pic_register_types(void)
216 type_register_static(&goldfish_pic_info
);
219 type_init(goldfish_pic_register_types
)