master
c 556 lines 16.5 KB
Raw
1 /*
2 * QEMU L2VIC Interrupt Controller
3 *
4 * Arm PrimeCell PL190 Vector Interrupt Controller was used as a reference.
5 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "hw/core/irq.h"
11 #include "hw/core/sysbus.h"
12 #include "migration/vmstate.h"
13 #include "qemu/log.h"
14 #include "qemu/module.h"
15 #include "qemu/bitmap.h"
16 #include "qemu/bitops.h"
17 #include "hw/intc/hex-l2vic.h"
18 #include "trace.h"
19
20 #define L2VIC_VID_GRP_0 0x0 /* Read */
21 #define L2VIC_VID_GRP_1 0x4 /* Read */
22 #define L2VIC_VID_GRP_2 0x8 /* Read */
23 #define L2VIC_VID_GRP_3 0xC /* Read */
24 #define L2VIC_INT_ENABLEn 0x100 /* Read/Write */
25 #define L2VIC_INT_ENABLE_CLEARn 0x180 /* Write */
26 #define L2VIC_INT_ENABLE_SETn 0x200 /* Write */
27 #define L2VIC_INT_TYPEn 0x280 /* Read/Write */
28 #define L2VIC_INT_STATUSn 0x380 /* Read */
29 #define L2VIC_INT_CLEARn 0x400 /* Write */
30 #define L2VIC_SOFT_INTn 0x480 /* Write */
31 #define L2VIC_INT_PENDINGn 0x500 /* Read */
32 #define L2VIC_INT_GRPn_0 0x600 /* Read/Write */
33 #define L2VIC_INT_GRPn_1 0x680 /* Read/Write */
34 #define L2VIC_INT_GRPn_2 0x700 /* Read/Write */
35 #define L2VIC_INT_GRPn_3 0x780 /* Read/Write */
36
37 #define L2VIC_INTERRUPT_MAX 1024
38 /*
39 * Note about l2vic groups:
40 * Each interrupt to L2VIC can be configured to associate with one of
41 * four groups.
42 * Group 0 interrupts go to IRQ2 via VID 0 (SSR: 0xC2, the default)
43 * Group 1 interrupts go to IRQ3 via VID 1 (SSR: 0xC3)
44 * Group 2 interrupts go to IRQ4 via VID 2 (SSR: 0xC4)
45 * Group 3 interrupts go to IRQ5 via VID 3 (SSR: 0xC5)
46 */
47
48 static void bitmap32_write_word(uint32_t *bitmap, int word_offset, uint32_t val)
49 {
50 bitmap[word_offset] = val;
51 }
52
53 static void bitmap32_clear_word(uint32_t *bitmap, int word_offset,
54 uint32_t mask)
55 {
56 bitmap[word_offset] &= ~mask;
57 }
58
59 static void bitmap32_set_word(uint32_t *bitmap, int word_offset, uint32_t mask)
60 {
61 bitmap[word_offset] |= mask;
62 }
63
64 static uint32_t bitmap32_read_word(uint32_t *bitmap, int word_offset)
65 {
66 return bitmap[word_offset];
67 }
68
69 OBJECT_DECLARE_SIMPLE_TYPE(HexL2VICState, HEX_L2VIC)
70
71 #define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
72 #define L2VIC_REG_RANGE_SIZE 0x80
73
74 typedef struct HexL2VICState {
75 SysBusDevice parent_obj;
76
77 MemoryRegion iomem;
78 MemoryRegion fast_iomem;
79 /*
80 * vid_group[i] is readable at L2VIC_VID_GRP_i (offset i*4): the irq
81 * last delivered through VID group i, 0-1023 so only 10 bits are used.
82 */
83 uint32_t vid_group[4];
84 /*
85 * Last irq delivered on any VID group; not specific to group 0.
86 * Used by the ciad path to clear the most-recently-delivered
87 * interrupt from int_status.
88 */
89 uint32_t vid;
90 DECLARE_BITMAP32(int_enable, L2VIC_INTERRUPT_MAX);
91 /* Asserted interrupts awaiting delivery once no VID is active */
92 DECLARE_BITMAP32(int_pending, L2VIC_INTERRUPT_MAX);
93 /* Which enabled interrupt is active */
94 DECLARE_BITMAP32(int_status, L2VIC_INTERRUPT_MAX);
95 /* Edge or Level interrupt */
96 DECLARE_BITMAP32(int_type, L2VIC_INTERRUPT_MAX);
97 DECLARE_BITMAP32(int_group_n[4], L2VIC_INTERRUPT_MAX);
98 qemu_irq irq[8];
99 } HexL2VICState;
100
101 typedef enum {
102 L2VIC_OP_WRITE,
103 L2VIC_OP_CLEAR,
104 L2VIC_OP_SET,
105 L2VIC_OP_NONE,
106 } L2VicWriteOp;
107
108 typedef struct {
109 hwaddr base;
110 size_t state_offset;
111 L2VicWriteOp write_op;
112 bool write_only;
113 } L2VicRegRange;
114
115 static const L2VicRegRange l2vic_reg_ranges[] = {
116 { L2VIC_INT_ENABLEn, offsetof(HexL2VICState, int_enable),
117 L2VIC_OP_WRITE, false },
118 { L2VIC_INT_ENABLE_CLEARn, offsetof(HexL2VICState, int_enable),
119 L2VIC_OP_CLEAR, true },
120 { L2VIC_INT_ENABLE_SETn, offsetof(HexL2VICState, int_enable),
121 L2VIC_OP_SET, true },
122 { L2VIC_INT_TYPEn, offsetof(HexL2VICState, int_type),
123 L2VIC_OP_WRITE, false },
124 { L2VIC_INT_STATUSn, offsetof(HexL2VICState, int_status),
125 L2VIC_OP_NONE, false },
126 { L2VIC_INT_CLEARn, offsetof(HexL2VICState, int_status),
127 L2VIC_OP_CLEAR, true },
128 { L2VIC_SOFT_INTn, offsetof(HexL2VICState, int_pending),
129 L2VIC_OP_NONE, true },
130 { L2VIC_INT_PENDINGn, offsetof(HexL2VICState, int_pending),
131 L2VIC_OP_WRITE, false },
132 { L2VIC_INT_GRPn_0, offsetof(HexL2VICState, int_group_n[0]),
133 L2VIC_OP_WRITE, false },
134 { L2VIC_INT_GRPn_1, offsetof(HexL2VICState, int_group_n[1]),
135 L2VIC_OP_WRITE, false },
136 { L2VIC_INT_GRPn_2, offsetof(HexL2VICState, int_group_n[2]),
137 L2VIC_OP_WRITE, false },
138 { L2VIC_INT_GRPn_3, offsetof(HexL2VICState, int_group_n[3]),
139 L2VIC_OP_WRITE, false },
140 };
141
142 static uint32_t *l2vic_state_bitmap(HexL2VICState *s, size_t state_offset)
143 {
144 return (uint32_t *)((char *)s + state_offset);
145 }
146
147 static bool l2vic_reg_read_range(HexL2VICState *s, hwaddr offset,
148 uint64_t *value)
149 {
150 int i;
151
152 for (i = 0; i < ARRAY_SIZE(l2vic_reg_ranges); i++) {
153 const L2VicRegRange *r = &l2vic_reg_ranges[i];
154
155 if (offset >= r->base &&
156 offset < r->base + L2VIC_REG_RANGE_SIZE) {
157 if (r->write_only) {
158 *value = 0;
159 } else {
160 uint32_t *bitmap = l2vic_state_bitmap(s, r->state_offset);
161 *value = bitmap32_read_word(bitmap,
162 (offset - r->base) >> 2);
163 }
164 return true;
165 }
166 }
167 return false;
168 }
169
170 static bool l2vic_reg_write_range(HexL2VICState *s, hwaddr offset,
171 uint32_t val)
172 {
173 int i;
174
175 for (i = 0; i < ARRAY_SIZE(l2vic_reg_ranges); i++) {
176 const L2VicRegRange *r = &l2vic_reg_ranges[i];
177
178 if (offset >= r->base &&
179 offset < r->base + L2VIC_REG_RANGE_SIZE) {
180 uint32_t *bitmap = l2vic_state_bitmap(s, r->state_offset);
181 int word = (offset - r->base) >> 2;
182
183 switch (r->write_op) {
184 case L2VIC_OP_WRITE:
185 bitmap32_write_word(bitmap, word, val);
186 break;
187 case L2VIC_OP_CLEAR:
188 bitmap32_clear_word(bitmap, word, val);
189 break;
190 case L2VIC_OP_SET:
191 bitmap32_set_word(bitmap, word, val);
192 break;
193 case L2VIC_OP_NONE:
194 /* Read-only or handled elsewhere; ignore the write. */
195 break;
196 default:
197 g_assert_not_reached();
198 }
199 return true;
200 }
201 }
202 return false;
203 }
204
205 /*
206 * The four INT_GRPn_* register arrays are interleaved across irqs in
207 * blocks of 8: irq 0-7 live in group_n[0], irq 8-15 in group_n[1], irq
208 * 16-23 in group_n[2], irq 24-31 in group_n[3], irq 32-39 back in
209 * group_n[0], and so on.
210 */
211 static uint32_t *get_int_group(HexL2VICState *s, int irq)
212 {
213 return s->int_group_n[extract32(irq, 3, 2)];
214 }
215
216 static int find_slice(int irq)
217 {
218 return irq / 32;
219 }
220
221 static int get_vid(HexL2VICState *s, int irq)
222 {
223 uint32_t *group = get_int_group(s, irq);
224 uint32_t slice = group[find_slice(irq)];
225 uint32_t vid;
226 /*
227 * Each irq occupies a 4-bit field: bit 3 is the group-enable bit,
228 * bits 0-2 select the VID group. Shift down to this irq's field.
229 */
230 uint32_t val = slice >> ((irq & 0x7) * 4);
231
232 if (!(val & 0x8)) {
233 return 0;
234 }
235 vid = val & 0x7;
236 if (vid >= ARRAY_SIZE(s->vid_group)) {
237 qemu_log_mask(LOG_GUEST_ERROR,
238 "L2VIC: irq %d requests invalid vid group %u\n",
239 irq, vid);
240 return 0;
241 }
242 return vid;
243 }
244
245 static inline bool vid_active(HexL2VICState *s)
246 {
247 const uint32_t size = L2VIC_INTERRUPT_MAX;
248 const uint32_t active_irq = find_first_bit32(s->int_status, size);
249 return active_irq != size;
250 }
251
252 static bool l2vic_update(HexL2VICState *s, int irq)
253 {
254 bool pending;
255 bool enable;
256
257 if (vid_active(s)) {
258 return true;
259 }
260
261 pending = test_bit32(irq, s->int_pending);
262 enable = test_bit32(irq, s->int_enable);
263 if (pending && enable) {
264 int vid = get_vid(s, irq);
265 set_bit32(irq, s->int_status);
266 clear_bit32(irq, s->int_pending);
267 /*
268 * Only auto-disable for edge-triggered interrupts (type=1).
269 * Level-triggered interrupts (type=0, the default) keep their
270 * enable bit set across deliveries -- the firmware enables once
271 * and expects the interrupt to remain enabled.
272 */
273 if (test_bit32(irq, s->int_type)) {
274 clear_bit32(irq, s->int_enable);
275 }
276 s->vid = irq;
277 s->vid_group[vid] = irq;
278
279 qemu_irq_pulse(s->irq[vid + 2]);
280 trace_hex_l2vic_delivered(irq, vid);
281 return true;
282 }
283 return false;
284 }
285
286 static void l2vic_update_all(HexL2VICState *s)
287 {
288 for (int i = 0; i < L2VIC_INTERRUPT_MAX; i++) {
289 if (l2vic_update(s, i)) {
290 /* once vid is active, no-one else can set it until ciad */
291 return;
292 }
293 }
294 }
295
296 static void l2vic_set_irq(void *opaque, int irq, int level)
297 {
298 HexL2VICState *s = (HexL2VICState *)opaque;
299
300 if (level) {
301 set_bit32(irq, s->int_pending);
302 }
303 l2vic_update(s, irq);
304 }
305
306 static void l2vic_write(void *opaque, hwaddr offset, uint64_t val,
307 unsigned size)
308 {
309 HexL2VICState *s = (HexL2VICState *)opaque;
310
311 trace_hex_l2vic_reg_write((unsigned)offset, (uint32_t)val);
312
313 if (!l2vic_reg_write_range(s, offset, val)) {
314 qemu_log_mask(LOG_UNIMP,
315 "%s: offset 0x%" HWADDR_PRIx " unimplemented\n",
316 __func__, offset);
317 }
318
319 /* SOFT_INT also sets pending for edge-triggered interrupts */
320 if (offset >= L2VIC_SOFT_INTn &&
321 offset < L2VIC_SOFT_INTn + L2VIC_REG_RANGE_SIZE && val) {
322 int base_irq = ((offset - L2VIC_SOFT_INTn) >> 2) * 32;
323 uint32_t bits = val;
324 int bit;
325
326 while ((bit = ctz32(bits)) < 32) {
327 int irq = base_irq + bit;
328
329 if (test_bit32(irq, s->int_type)) {
330 set_bit32(irq, s->int_pending);
331 }
332 bits &= ~(1u << bit);
333 }
334 }
335
336 l2vic_update_all(s);
337 }
338
339 static uint64_t l2vic_read(void *opaque, hwaddr offset, unsigned size)
340 {
341 uint64_t value;
342 HexL2VICState *s = (HexL2VICState *)opaque;
343
344 if (offset <= L2VIC_VID_GRP_3) {
345 value = s->vid_group[offset >> 2];
346 } else if (!l2vic_reg_read_range(s, offset, &value)) {
347 value = 0;
348 qemu_log_mask(LOG_GUEST_ERROR,
349 "L2VIC: %s: offset 0x%" HWADDR_PRIx "\n", __func__,
350 offset);
351 }
352
353 trace_hex_l2vic_reg_read((unsigned)offset, (uint32_t)value);
354 return value;
355 }
356
357 static const MemoryRegionOps l2vic_ops = {
358 .read = l2vic_read,
359 .write = l2vic_write,
360 .endianness = DEVICE_LITTLE_ENDIAN,
361 .valid.min_access_size = 4,
362 .valid.max_access_size = 4,
363 .valid.unaligned = false,
364 };
365
366 #define FASTL2VIC_ENABLE 0x0
367 #define FASTL2VIC_DISABLE 0x1
368 #define FASTL2VIC_INT 0x2
369
370 static void fastl2vic_write(void *opaque, hwaddr offset, uint64_t val,
371 unsigned size)
372 {
373 if (offset == 0) {
374 uint32_t cmd = (val >> 16) & 0x3;
375 uint32_t irq = val & 0x3ff;
376 uint32_t slice = (irq / 32) * 4;
377 val = 1 << (irq % 32);
378
379 if (cmd == FASTL2VIC_ENABLE) {
380 l2vic_write(opaque, L2VIC_INT_ENABLE_SETn + slice, val, size);
381 } else if (cmd == FASTL2VIC_DISABLE) {
382 l2vic_write(opaque, L2VIC_INT_ENABLE_CLEARn + slice, val, size);
383 } else if (cmd == FASTL2VIC_INT) {
384 l2vic_write(opaque, L2VIC_SOFT_INTn + slice, val, size);
385 } else {
386 qemu_log_mask(LOG_GUEST_ERROR,
387 "%s: invalid write cmd %" PRId32 "\n",
388 __func__, cmd);
389 }
390 return;
391 }
392 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid write offset 0x%08" HWADDR_PRIx
393 "\n", __func__, offset);
394 }
395
396 static uint64_t fastl2vic_read(void *opaque, hwaddr offset, unsigned size)
397 {
398 return 0;
399 }
400
401 static const MemoryRegionOps fastl2vic_ops = {
402 .read = fastl2vic_read,
403 .write = fastl2vic_write,
404 .endianness = DEVICE_LITTLE_ENDIAN,
405 .valid.min_access_size = 4,
406 .valid.max_access_size = 4,
407 .valid.unaligned = false,
408 };
409
410 static uint32_t l2vic_interface_read_vid_impl(HexL2VicInterface *iface,
411 uint32_t group)
412 {
413 HexL2VICState *s = HEX_L2VIC(iface);
414 uint32_t result = 0;
415
416 if (group == 0) {
417 /* VID register combines vid_group[0] (VID0) and vid_group[1] (VID1) */
418 result = deposit32(result, 0, 16, s->vid_group[0]);
419 result = deposit32(result, 16, 16, s->vid_group[1]);
420 } else if (group == 1) {
421 /* VID1 register combines vid_group[2] (VID2) and vid_group[3] (VID3) */
422 result = deposit32(result, 0, 16, s->vid_group[2]);
423 result = deposit32(result, 16, 16, s->vid_group[3]);
424 }
425 return result;
426 }
427
428 static void l2vic_interface_update_vid_impl(HexL2VicInterface *iface,
429 uint32_t group, uint32_t value)
430 {
431 HexL2VICState *s = HEX_L2VIC(iface);
432
433 if (group == 0) {
434 s->vid_group[0] = extract32(value, 0, 16);
435 s->vid_group[1] = extract32(value, 16, 16);
436 } else if (group == 1) {
437 s->vid_group[2] = extract32(value, 0, 16);
438 s->vid_group[3] = extract32(value, 16, 16);
439 }
440
441 l2vic_update_all(s);
442 }
443
444 static void l2vic_interface_clear_interrupt_impl(HexL2VicInterface *iface)
445 {
446 HexL2VICState *s = HEX_L2VIC(iface);
447
448 if (s->vid < L2VIC_INTERRUPT_MAX) {
449 clear_bit32(s->vid, s->int_status);
450 }
451 l2vic_update_all(s);
452 }
453
454 static void l2vic_reset_hold(Object *obj, ResetType type G_GNUC_UNUSED)
455 {
456 HexL2VICState *s = HEX_L2VIC(obj);
457
458 memset(s->int_enable, 0, sizeof(s->int_enable));
459 memset(s->int_pending, 0, sizeof(s->int_pending));
460 memset(s->int_status, 0, sizeof(s->int_status));
461 memset(s->int_type, 0, sizeof(s->int_type));
462 memset(s->int_group_n, 0, sizeof(s->int_group_n));
463 memset(s->vid_group, 0, sizeof(s->vid_group));
464 s->vid = 0;
465
466 l2vic_update_all(s);
467 }
468
469 static void reset_irq_handler(void *opaque, int irq, int level)
470 {
471 Object *obj = OBJECT(opaque);
472
473 if (level) {
474 l2vic_reset_hold(obj, RESET_TYPE_COLD);
475 }
476 }
477
478 static void l2vic_init(Object *obj)
479 {
480 DeviceState *dev = DEVICE(obj);
481 HexL2VICState *s = HEX_L2VIC(obj);
482 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
483 int i;
484
485 memory_region_init_io(&s->iomem, obj, &l2vic_ops, s, "l2vic", 0x1000);
486 sysbus_init_mmio(sbd, &s->iomem);
487 memory_region_init_io(&s->fast_iomem, obj, &fastl2vic_ops, s, "fast",
488 0x10000);
489 sysbus_init_mmio(sbd, &s->fast_iomem);
490
491 qdev_init_gpio_in(dev, l2vic_set_irq, L2VIC_INTERRUPT_MAX);
492 qdev_init_gpio_in_named(dev, reset_irq_handler, "reset", 1);
493 for (i = 0; i < 8; i++) {
494 sysbus_init_irq(sbd, &s->irq[i]);
495 }
496 }
497
498 static const VMStateDescription vmstate_l2vic = {
499 .name = "l2vic",
500 .version_id = 1,
501 .minimum_version_id = 1,
502 .fields =
503 (VMStateField[]){
504 VMSTATE_UINT32_ARRAY(vid_group, HexL2VICState, 4),
505 VMSTATE_UINT32(vid, HexL2VICState),
506 VMSTATE_UINT32_ARRAY(int_enable, HexL2VICState, SLICE_MAX),
507 VMSTATE_UINT32_ARRAY(int_type, HexL2VICState, SLICE_MAX),
508 VMSTATE_UINT32_ARRAY(int_status, HexL2VICState, SLICE_MAX),
509 VMSTATE_UINT32_ARRAY(int_pending, HexL2VICState, SLICE_MAX),
510 VMSTATE_UINT32_2DARRAY(int_group_n, HexL2VICState, 4, SLICE_MAX),
511 VMSTATE_END_OF_LIST() }
512 };
513
514 static void l2vic_interface_class_init(ObjectClass *klass, const void *data)
515 {
516 HexL2VicInterfaceClass *k = HEX_L2VIC_INTERFACE_CLASS(klass);
517
518 k->read_vid = l2vic_interface_read_vid_impl;
519 k->update_vid = l2vic_interface_update_vid_impl;
520 k->clear_interrupt = l2vic_interface_clear_interrupt_impl;
521 }
522
523 static void l2vic_class_init(ObjectClass *klass, const void *data)
524 {
525 DeviceClass *dc = DEVICE_CLASS(klass);
526 ResettableClass *rc = RESETTABLE_CLASS(klass);
527
528 dc->vmsd = &vmstate_l2vic;
529 rc->phases.hold = l2vic_reset_hold;
530 }
531
532 static const TypeInfo l2vic_interface_info = {
533 .name = TYPE_HEX_L2VIC_INTERFACE,
534 .parent = TYPE_INTERFACE,
535 .class_size = sizeof(HexL2VicInterfaceClass),
536 .class_init = l2vic_interface_class_init,
537 };
538
539 static const TypeInfo l2vic_info = {
540 .name = TYPE_HEX_L2VIC,
541 .parent = TYPE_SYS_BUS_DEVICE,
542 .instance_size = sizeof(HexL2VICState),
543 .instance_init = l2vic_init,
544 .class_init = l2vic_class_init,
545 .interfaces = (InterfaceInfo[]) {
546 { TYPE_HEX_L2VIC_INTERFACE },
547 { }
548 },
549 };
550
551 static const TypeInfo l2vic_types[] = {
552 l2vic_interface_info,
553 l2vic_info,
554 };
555
556 DEFINE_TYPES(l2vic_types)