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
26
27
28#include "qemu/osdep.h"
29#include "hw/sysbus.h"
30#include "hw/register-dep.h"
31#include "qemu/log.h"
32
33#ifndef IRQ_TEST_COMPONENT_ERR_DEBUG
34#define IRQ_TEST_COMPONENT_ERR_DEBUG 0
35#endif
36
37#define TYPE_IRQ_TEST_COMPONENT "qemu.irq-test-component"
38
39#define IRQ_TEST_COMPONENT(obj) \
40 OBJECT_CHECK(IRQTestComponent, (obj), TYPE_IRQ_TEST_COMPONENT)
41
42DEP_REG32(CONFIG, 0x0)
43DEP_REG32(STATUS, 0x4)
44 DEP_FIELD(STATUS, POWER, 1, 0)
45 DEP_FIELD(STATUS, HALT, 1, 1)
46DEP_REG32(DATA, 0x8)
47DEP_REG32(IRQ_STATUS, 0x10)
48 DEP_FIELD(IRQ_STATUS, IRQ0, 1, 0)
49DEP_REG32(IRQ_MASK, 0x14)
50 DEP_FIELD(IRQ_MASK, IRQ0, 1, 0)
51DEP_REG32(IRQ_ENABLE, 0x18)
52 DEP_FIELD(IRQ_ENABLE, IRQ0, 1, 0)
53DEP_REG32(IRQ_DISABLE, 0x1c)
54 DEP_FIELD(IRQ_DISABLE, IRQ0, 1, 0)
55DEP_REG32(IRQ_TRIGGER, 0x20)
56 DEP_FIELD(IRQ_TRIGGER, IRQ0, 1, 0)
57
58#define R_MAX ((R_IRQ_TRIGGER) + 1)
59
60typedef struct IRQTestComponent {
61 SysBusDevice parent_obj;
62 MemoryRegion iomem;
63
64 qemu_irq irq;
65 qemu_irq pmu_wake;
66
67 uint32_t regs[R_MAX];
68 DepRegisterInfo regs_info[R_MAX];
69} IRQTestComponent;
70
71static void itc_update_irq(void *opaque)
72{
73 IRQTestComponent *s = IRQ_TEST_COMPONENT(opaque);
74 bool pending = s->regs[R_IRQ_STATUS] & (~s->regs[R_IRQ_MASK]) &
75 R_IRQ_STATUS_IRQ0_MASK;
76
77 qemu_set_irq(s->irq, pending);
78 qemu_set_irq(s->pmu_wake, pending);
79}
80
81
82static void itc_generate_irq(void *opaque, int n, int level)
83{
84 IRQTestComponent *s = IRQ_TEST_COMPONENT(opaque);
85
86 s->regs[R_IRQ_STATUS] &= ~R_IRQ_STATUS_IRQ0_MASK;
87 s->regs[R_IRQ_STATUS] |= level;
88
89 itc_update_irq(s);
90}
91
92
93
94static uint64_t itc_status_postr(DepRegisterInfo *reg, uint64_t val64)
95{
96 IRQTestComponent *s = IRQ_TEST_COMPONENT(reg->opaque);
97 DeviceState *dev = DEVICE(s);
98 uint32_t tmp = val64;
99
100
101 tmp = deposit32(tmp, R_STATUS_POWER_SHIFT, 1, dev->ps.power);
102 tmp = deposit32(tmp, R_STATUS_HALT_SHIFT, 1, dev->ps.halt);
103
104 return tmp;
105}
106
107static void itc_irq_status_postw(DepRegisterInfo *reg, uint64_t val64)
108{
109 IRQTestComponent *s = IRQ_TEST_COMPONENT(reg->opaque);
110
111 itc_update_irq(s);
112}
113
114static void itc_irq_enable_postw(DepRegisterInfo *reg, uint64_t val64)
115{
116 IRQTestComponent *s = IRQ_TEST_COMPONENT(reg->opaque);
117 uint32_t val = val64;
118
119 s->regs[R_IRQ_MASK] &= ~val;
120 itc_update_irq(s);
121}
122
123static void itc_irq_disable_postw(DepRegisterInfo *reg, uint64_t val64)
124{
125 IRQTestComponent *s = IRQ_TEST_COMPONENT(reg->opaque);
126 uint32_t val = val64;
127
128 s->regs[R_IRQ_MASK] |= val;
129 itc_update_irq(s);
130}
131
132static void itc_irq_trigger_postw(DepRegisterInfo *reg, uint64_t val64)
133{
134 IRQTestComponent *s = IRQ_TEST_COMPONENT(reg->opaque);
135 uint32_t val = val64;
136
137 s->regs[R_IRQ_STATUS] |= val;
138 itc_update_irq(s);
139}
140
141static DepRegisterAccessInfo irq_test_comp_regs_info[] = {
142 { .name = "CONFIG", .decode.addr = A_CONFIG,
143 .rsvd = 0xffffffff,
144 },{ .name = "STATUS", .decode.addr = A_STATUS,
145 .rsvd = 0xfffffffe,
146 .ro = 0xfffffffe,
147 .post_read = itc_status_postr,
148 },{ .name = "DATA", .decode.addr = A_DATA,
149 },{ .name = "IRQ_STATUS", .decode.addr = A_IRQ_STATUS,
150 .w1c = 0xffffffff,
151 .rsvd = 0xfffffffe,
152 .post_write = itc_irq_status_postw,
153 },{ .name = "IRQ_MASK", .decode.addr = A_IRQ_MASK,
154 .ro = 0xffffffff,
155 .rsvd = 0xfffffffe,
156 .reset = 0xffffffff,
157 },{ .name = "IRQ_ENABLE", .decode.addr = A_IRQ_ENABLE,
158 .rsvd = 0xfffffffe,
159 .post_write = itc_irq_enable_postw,
160 },{ .name = "IRQ_DISABLE", .decode.addr = A_IRQ_DISABLE,
161 .rsvd = 0xfffffffe,
162 .post_write = itc_irq_disable_postw,
163 },{ .name = "IRQ_TRIGGER", .decode.addr = A_IRQ_TRIGGER,
164 .rsvd = 0xfffffffe,
165 .post_write = itc_irq_trigger_postw,
166 }
167};
168
169static void irq_test_comp_reset(DeviceState *dev)
170{
171 IRQTestComponent *s = IRQ_TEST_COMPONENT(dev);
172 unsigned int i;
173
174 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
175 dep_register_reset(&s->regs_info[i]);
176 }
177 itc_update_irq(s);
178}
179
180static uint64_t irq_test_comp_read(void *opaque, hwaddr addr, unsigned size)
181{
182 IRQTestComponent *s = IRQ_TEST_COMPONENT(opaque);
183 DepRegisterInfo *r = &s->regs_info[addr / 4];
184
185 if (!r->data) {
186 qemu_log_mask(LOG_GUEST_ERROR,
187 "%s: Decode error: read from %" HWADDR_PRIx "\n",
188 object_get_canonical_path(OBJECT(s)),
189 addr);
190 return 0;
191 }
192 return dep_register_read(r);
193}
194
195static void irq_test_comp_write(void *opaque, hwaddr addr, uint64_t value,
196 unsigned size)
197{
198 IRQTestComponent *s = IRQ_TEST_COMPONENT(opaque);
199 DepRegisterInfo *r = &s->regs_info[addr / 4];
200
201 if (!r->data) {
202 qemu_log_mask(LOG_GUEST_ERROR,
203 "%s: Decode error: write %" HWADDR_PRIx "=%" PRIx64 "\n",
204 object_get_canonical_path(OBJECT(s)),
205 addr, value);
206 return;
207 }
208 dep_register_write(r, value, ~0);
209}
210
211static const MemoryRegionOps irq_test_comp_ops = {
212 .read = irq_test_comp_read,
213 .write = irq_test_comp_write,
214 .endianness = DEVICE_LITTLE_ENDIAN,
215 .valid = {
216 .min_access_size = 4,
217 .max_access_size = 4,
218 },
219};
220
221static void irq_test_comp_realize(DeviceState *dev, Error **errp)
222{
223 IRQTestComponent *s = IRQ_TEST_COMPONENT(dev);
224 const char *prefix = object_get_canonical_path(OBJECT(dev));
225 unsigned int i;
226
227 for (i = 0; i < ARRAY_SIZE(irq_test_comp_regs_info); ++i) {
228 DepRegisterInfo *r = &s->regs_info[
229 irq_test_comp_regs_info[i].decode.addr/4];
230
231 *r = (DepRegisterInfo) {
232 .data = (uint8_t *)&s->regs[
233 irq_test_comp_regs_info[i].decode.addr/4],
234 .data_size = sizeof(uint32_t),
235 .access = &irq_test_comp_regs_info[i],
236 .debug = IRQ_TEST_COMPONENT_ERR_DEBUG,
237 .prefix = prefix,
238 .opaque = s,
239 };
240 dep_register_init(r);
241 }
242}
243
244static void irq_test_comp_init(Object *obj)
245{
246 IRQTestComponent *s = IRQ_TEST_COMPONENT(obj);
247 DeviceState *dev = DEVICE(obj);
248 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
249
250 memory_region_init_io(&s->iomem, obj, &irq_test_comp_ops, s,
251 TYPE_IRQ_TEST_COMPONENT, R_MAX * 4);
252 sysbus_init_mmio(sbd, &s->iomem);
253 sysbus_init_irq(sbd, &s->irq);
254
255
256 qdev_init_gpio_in(dev, itc_generate_irq, 1);
257
258 qdev_init_gpio_out_named(dev, &s->pmu_wake, "wake", 1);
259}
260
261static const VMStateDescription vmstate_irq_test_comp = {
262 .name = TYPE_IRQ_TEST_COMPONENT,
263 .version_id = 1,
264 .minimum_version_id = 1,
265 .minimum_version_id_old = 1,
266 .fields = (VMStateField[]) {
267 VMSTATE_UINT32_ARRAY(regs, IRQTestComponent, R_MAX),
268 VMSTATE_END_OF_LIST(),
269 }
270};
271
272static void irq_test_comp_class_init(ObjectClass *klass, void *data)
273{
274 DeviceClass *dc = DEVICE_CLASS(klass);
275
276 dc->reset = irq_test_comp_reset;
277 dc->realize = irq_test_comp_realize;
278 dc->vmsd = &vmstate_irq_test_comp;
279}
280
281static const TypeInfo irq_test_comp_info = {
282 .name = TYPE_IRQ_TEST_COMPONENT,
283 .parent = TYPE_SYS_BUS_DEVICE,
284 .instance_size = sizeof(IRQTestComponent),
285 .instance_init = irq_test_comp_init,
286 .class_init = irq_test_comp_class_init,
287};
288
289static void irq_test_comp_register_types(void)
290{
291 type_register_static(&irq_test_comp_info);
292}
293
294type_init(irq_test_comp_register_types)
295