Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-migration-20210726a...
[qemu/armbru.git] / hw / intc / openpic.c
blob9b4c17854d2935d564ac25812495664703d1a67f
1 /*
2 * OpenPIC emulation
4 * Copyright (c) 2004 Jocelyn Mayer
5 * 2011 Alexander Graf
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
27 * Based on OpenPic implementations:
28 * - Intel GW80314 I/O companion chip developer's manual
29 * - Motorola MPC8245 & MPC8540 user manuals.
30 * - Motorola MCP750 (aka Raven) programmer manual.
31 * - Motorola Harrier programmer manuel
33 * Serial interrupts, as implemented in Raven chipset are not supported yet.
37 #include "qemu/osdep.h"
38 #include "hw/irq.h"
39 #include "hw/ppc/mac.h"
40 #include "hw/pci/pci.h"
41 #include "hw/ppc/openpic.h"
42 #include "hw/ppc/ppc_e500.h"
43 #include "hw/qdev-properties.h"
44 #include "hw/sysbus.h"
45 #include "migration/vmstate.h"
46 #include "hw/pci/msi.h"
47 #include "qapi/error.h"
48 #include "qemu/bitops.h"
49 #include "qapi/qmp/qerror.h"
50 #include "qemu/module.h"
51 #include "qemu/timer.h"
52 #include "qemu/error-report.h"
54 //#define DEBUG_OPENPIC
56 #ifdef DEBUG_OPENPIC
57 static const int debug_openpic = 1;
58 #else
59 static const int debug_openpic = 0;
60 #endif
62 static int get_current_cpu(void);
63 #define DPRINTF(fmt, ...) do { \
64 if (debug_openpic) { \
65 info_report("Core%d: " fmt, get_current_cpu(), ## __VA_ARGS__); \
66 } \
67 } while (0)
69 /* OpenPIC capability flags */
70 #define OPENPIC_FLAG_IDR_CRIT (1 << 0)
71 #define OPENPIC_FLAG_ILR (2 << 0)
73 /* OpenPIC address map */
74 #define OPENPIC_GLB_REG_START 0x0
75 #define OPENPIC_GLB_REG_SIZE 0x10F0
76 #define OPENPIC_TMR_REG_START 0x10F0
77 #define OPENPIC_TMR_REG_SIZE 0x220
78 #define OPENPIC_MSI_REG_START 0x1600
79 #define OPENPIC_MSI_REG_SIZE 0x200
80 #define OPENPIC_SUMMARY_REG_START 0x3800
81 #define OPENPIC_SUMMARY_REG_SIZE 0x800
82 #define OPENPIC_SRC_REG_START 0x10000
83 #define OPENPIC_SRC_REG_SIZE (OPENPIC_MAX_SRC * 0x20)
84 #define OPENPIC_CPU_REG_START 0x20000
85 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
87 static FslMpicInfo fsl_mpic_20 = {
88 .max_ext = 12,
91 static FslMpicInfo fsl_mpic_42 = {
92 .max_ext = 12,
95 #define FRR_NIRQ_SHIFT 16
96 #define FRR_NCPU_SHIFT 8
97 #define FRR_VID_SHIFT 0
99 #define VID_REVISION_1_2 2
100 #define VID_REVISION_1_3 3
102 #define VIR_GENERIC 0x00000000 /* Generic Vendor ID */
103 #define VIR_MPIC2A 0x00004614 /* IBM MPIC-2A */
105 #define GCR_RESET 0x80000000
106 #define GCR_MODE_PASS 0x00000000
107 #define GCR_MODE_MIXED 0x20000000
108 #define GCR_MODE_PROXY 0x60000000
110 #define TBCR_CI 0x80000000 /* count inhibit */
111 #define TCCR_TOG 0x80000000 /* toggles when decrement to zero */
113 #define IDR_EP_SHIFT 31
114 #define IDR_EP_MASK (1U << IDR_EP_SHIFT)
115 #define IDR_CI0_SHIFT 30
116 #define IDR_CI1_SHIFT 29
117 #define IDR_P1_SHIFT 1
118 #define IDR_P0_SHIFT 0
120 #define ILR_INTTGT_MASK 0x000000ff
121 #define ILR_INTTGT_INT 0x00
122 #define ILR_INTTGT_CINT 0x01 /* critical */
123 #define ILR_INTTGT_MCP 0x02 /* machine check */
125 /* The currently supported INTTGT values happen to be the same as QEMU's
126 * openpic output codes, but don't depend on this. The output codes
127 * could change (unlikely, but...) or support could be added for
128 * more INTTGT values.
130 static const int inttgt_output[][2] = {
131 { ILR_INTTGT_INT, OPENPIC_OUTPUT_INT },
132 { ILR_INTTGT_CINT, OPENPIC_OUTPUT_CINT },
133 { ILR_INTTGT_MCP, OPENPIC_OUTPUT_MCK },
136 static int inttgt_to_output(int inttgt)
138 int i;
140 for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
141 if (inttgt_output[i][0] == inttgt) {
142 return inttgt_output[i][1];
146 error_report("%s: unsupported inttgt %d", __func__, inttgt);
147 return OPENPIC_OUTPUT_INT;
150 static int output_to_inttgt(int output)
152 int i;
154 for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
155 if (inttgt_output[i][1] == output) {
156 return inttgt_output[i][0];
160 abort();
163 #define MSIIR_OFFSET 0x140
164 #define MSIIR_SRS_SHIFT 29
165 #define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT)
166 #define MSIIR_IBS_SHIFT 24
167 #define MSIIR_IBS_MASK (0x1f << MSIIR_IBS_SHIFT)
169 static int get_current_cpu(void)
171 if (!current_cpu) {
172 return -1;
175 return current_cpu->cpu_index;
178 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
179 int idx);
180 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
181 uint32_t val, int idx);
182 static void openpic_reset(DeviceState *d);
184 /* Convert between openpic clock ticks and nanosecs. In the hardware the clock
185 frequency is driven by board inputs to the PIC which the PIC would then
186 divide by 4 or 8. For now hard code to 25MZ.
188 #define OPENPIC_TIMER_FREQ_MHZ 25
189 #define OPENPIC_TIMER_NS_PER_TICK (1000 / OPENPIC_TIMER_FREQ_MHZ)
190 static inline uint64_t ns_to_ticks(uint64_t ns)
192 return ns / OPENPIC_TIMER_NS_PER_TICK;
194 static inline uint64_t ticks_to_ns(uint64_t ticks)
196 return ticks * OPENPIC_TIMER_NS_PER_TICK;
199 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
201 set_bit(n_IRQ, q->queue);
204 static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
206 clear_bit(n_IRQ, q->queue);
209 static void IRQ_check(OpenPICState *opp, IRQQueue *q)
211 int irq = -1;
212 int next = -1;
213 int priority = -1;
215 for (;;) {
216 irq = find_next_bit(q->queue, opp->max_irq, irq + 1);
217 if (irq == opp->max_irq) {
218 break;
221 DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d",
222 irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
224 if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
225 next = irq;
226 priority = IVPR_PRIORITY(opp->src[irq].ivpr);
230 q->next = next;
231 q->priority = priority;
234 static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
236 /* XXX: optimize */
237 IRQ_check(opp, q);
239 return q->next;
242 static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ,
243 bool active, bool was_active)
245 IRQDest *dst;
246 IRQSource *src;
247 int priority;
249 dst = &opp->dst[n_CPU];
250 src = &opp->src[n_IRQ];
252 DPRINTF("%s: IRQ %d active %d was %d",
253 __func__, n_IRQ, active, was_active);
255 if (src->output != OPENPIC_OUTPUT_INT) {
256 DPRINTF("%s: output %d irq %d active %d was %d count %d",
257 __func__, src->output, n_IRQ, active, was_active,
258 dst->outputs_active[src->output]);
260 /* On Freescale MPIC, critical interrupts ignore priority,
261 * IACK, EOI, etc. Before MPIC v4.1 they also ignore
262 * masking.
264 if (active) {
265 if (!was_active && dst->outputs_active[src->output]++ == 0) {
266 DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d",
267 __func__, src->output, n_CPU, n_IRQ);
268 qemu_irq_raise(dst->irqs[src->output]);
270 } else {
271 if (was_active && --dst->outputs_active[src->output] == 0) {
272 DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d",
273 __func__, src->output, n_CPU, n_IRQ);
274 qemu_irq_lower(dst->irqs[src->output]);
278 return;
281 priority = IVPR_PRIORITY(src->ivpr);
283 /* Even if the interrupt doesn't have enough priority,
284 * it is still raised, in case ctpr is lowered later.
286 if (active) {
287 IRQ_setbit(&dst->raised, n_IRQ);
288 } else {
289 IRQ_resetbit(&dst->raised, n_IRQ);
292 IRQ_check(opp, &dst->raised);
294 if (active && priority <= dst->ctpr) {
295 DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d",
296 __func__, n_IRQ, priority, dst->ctpr, n_CPU);
297 active = 0;
300 if (active) {
301 if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
302 priority <= dst->servicing.priority) {
303 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d",
304 __func__, n_IRQ, dst->servicing.next, n_CPU);
305 } else {
306 DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d",
307 __func__, n_CPU, n_IRQ, dst->raised.next);
308 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
310 } else {
311 IRQ_get_next(opp, &dst->servicing);
312 if (dst->raised.priority > dst->ctpr &&
313 dst->raised.priority > dst->servicing.priority) {
314 DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU %d",
315 __func__, n_IRQ, dst->raised.next, dst->raised.priority,
316 dst->ctpr, dst->servicing.priority, n_CPU);
317 /* IRQ line stays asserted */
318 } else {
319 DPRINTF("%s: IRQ %d inactive, current prio %d/%d, CPU %d",
320 __func__, n_IRQ, dst->ctpr, dst->servicing.priority, n_CPU);
321 qemu_irq_lower(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
326 /* update pic state because registers for n_IRQ have changed value */
327 static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
329 IRQSource *src;
330 bool active, was_active;
331 int i;
333 src = &opp->src[n_IRQ];
334 active = src->pending;
336 if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
337 /* Interrupt source is disabled */
338 DPRINTF("%s: IRQ %d is disabled", __func__, n_IRQ);
339 active = false;
342 was_active = !!(src->ivpr & IVPR_ACTIVITY_MASK);
345 * We don't have a similar check for already-active because
346 * ctpr may have changed and we need to withdraw the interrupt.
348 if (!active && !was_active) {
349 DPRINTF("%s: IRQ %d is already inactive", __func__, n_IRQ);
350 return;
353 if (active) {
354 src->ivpr |= IVPR_ACTIVITY_MASK;
355 } else {
356 src->ivpr &= ~IVPR_ACTIVITY_MASK;
359 if (src->destmask == 0) {
360 /* No target */
361 DPRINTF("%s: IRQ %d has no target", __func__, n_IRQ);
362 return;
365 if (src->destmask == (1 << src->last_cpu)) {
366 /* Only one CPU is allowed to receive this IRQ */
367 IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active);
368 } else if (!(src->ivpr & IVPR_MODE_MASK)) {
369 /* Directed delivery mode */
370 for (i = 0; i < opp->nb_cpus; i++) {
371 if (src->destmask & (1 << i)) {
372 IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
375 } else {
376 /* Distributed delivery mode */
377 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
378 if (i == opp->nb_cpus) {
379 i = 0;
381 if (src->destmask & (1 << i)) {
382 IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
383 src->last_cpu = i;
384 break;
390 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
392 OpenPICState *opp = opaque;
393 IRQSource *src;
395 if (n_IRQ >= OPENPIC_MAX_IRQ) {
396 error_report("%s: IRQ %d out of range", __func__, n_IRQ);
397 abort();
400 src = &opp->src[n_IRQ];
401 DPRINTF("openpic: set irq %d = %d ivpr=0x%08x",
402 n_IRQ, level, src->ivpr);
403 if (src->level) {
404 /* level-sensitive irq */
405 src->pending = level;
406 openpic_update_irq(opp, n_IRQ);
407 } else {
408 /* edge-sensitive irq */
409 if (level) {
410 src->pending = 1;
411 openpic_update_irq(opp, n_IRQ);
414 if (src->output != OPENPIC_OUTPUT_INT) {
415 /* Edge-triggered interrupts shouldn't be used
416 * with non-INT delivery, but just in case,
417 * try to make it do something sane rather than
418 * cause an interrupt storm. This is close to
419 * what you'd probably see happen in real hardware.
421 src->pending = 0;
422 openpic_update_irq(opp, n_IRQ);
427 static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ)
429 return opp->src[n_IRQ].idr;
432 static inline uint32_t read_IRQreg_ilr(OpenPICState *opp, int n_IRQ)
434 if (opp->flags & OPENPIC_FLAG_ILR) {
435 return output_to_inttgt(opp->src[n_IRQ].output);
438 return 0xffffffff;
441 static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
443 return opp->src[n_IRQ].ivpr;
446 static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
448 IRQSource *src = &opp->src[n_IRQ];
449 uint32_t normal_mask = (1UL << opp->nb_cpus) - 1;
450 uint32_t crit_mask = 0;
451 uint32_t mask = normal_mask;
452 int crit_shift = IDR_EP_SHIFT - opp->nb_cpus;
453 int i;
455 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
456 crit_mask = mask << crit_shift;
457 mask |= crit_mask | IDR_EP;
460 src->idr = val & mask;
461 DPRINTF("Set IDR %d to 0x%08x", n_IRQ, src->idr);
463 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
464 if (src->idr & crit_mask) {
465 if (src->idr & normal_mask) {
466 DPRINTF("%s: IRQ configured for multiple output types, using "
467 "critical", __func__);
470 src->output = OPENPIC_OUTPUT_CINT;
471 src->nomask = true;
472 src->destmask = 0;
474 for (i = 0; i < opp->nb_cpus; i++) {
475 int n_ci = IDR_CI0_SHIFT - i;
477 if (src->idr & (1UL << n_ci)) {
478 src->destmask |= 1UL << i;
481 } else {
482 src->output = OPENPIC_OUTPUT_INT;
483 src->nomask = false;
484 src->destmask = src->idr & normal_mask;
486 } else {
487 src->destmask = src->idr;
491 static inline void write_IRQreg_ilr(OpenPICState *opp, int n_IRQ, uint32_t val)
493 if (opp->flags & OPENPIC_FLAG_ILR) {
494 IRQSource *src = &opp->src[n_IRQ];
496 src->output = inttgt_to_output(val & ILR_INTTGT_MASK);
497 DPRINTF("Set ILR %d to 0x%08x, output %d", n_IRQ, src->idr,
498 src->output);
500 /* TODO: on MPIC v4.0 only, set nomask for non-INT */
504 static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
506 uint32_t mask;
508 /* NOTE when implementing newer FSL MPIC models: starting with v4.0,
509 * the polarity bit is read-only on internal interrupts.
511 mask = IVPR_MASK_MASK | IVPR_PRIORITY_MASK | IVPR_SENSE_MASK |
512 IVPR_POLARITY_MASK | opp->vector_mask;
514 /* ACTIVITY bit is read-only */
515 opp->src[n_IRQ].ivpr =
516 (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) | (val & mask);
518 /* For FSL internal interrupts, The sense bit is reserved and zero,
519 * and the interrupt is always level-triggered. Timers and IPIs
520 * have no sense or polarity bits, and are edge-triggered.
522 switch (opp->src[n_IRQ].type) {
523 case IRQ_TYPE_NORMAL:
524 opp->src[n_IRQ].level = !!(opp->src[n_IRQ].ivpr & IVPR_SENSE_MASK);
525 break;
527 case IRQ_TYPE_FSLINT:
528 opp->src[n_IRQ].ivpr &= ~IVPR_SENSE_MASK;
529 break;
531 case IRQ_TYPE_FSLSPECIAL:
532 opp->src[n_IRQ].ivpr &= ~(IVPR_POLARITY_MASK | IVPR_SENSE_MASK);
533 break;
536 openpic_update_irq(opp, n_IRQ);
537 DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x", n_IRQ, val,
538 opp->src[n_IRQ].ivpr);
541 static void openpic_gcr_write(OpenPICState *opp, uint64_t val)
543 bool mpic_proxy = false;
545 if (val & GCR_RESET) {
546 openpic_reset(DEVICE(opp));
547 return;
550 opp->gcr &= ~opp->mpic_mode_mask;
551 opp->gcr |= val & opp->mpic_mode_mask;
553 /* Set external proxy mode */
554 if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
555 mpic_proxy = true;
558 ppce500_set_mpic_proxy(mpic_proxy);
561 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
562 unsigned len)
564 OpenPICState *opp = opaque;
565 IRQDest *dst;
566 int idx;
568 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64,
569 __func__, addr, val);
570 if (addr & 0xF) {
571 return;
573 switch (addr) {
574 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
575 break;
576 case 0x40:
577 case 0x50:
578 case 0x60:
579 case 0x70:
580 case 0x80:
581 case 0x90:
582 case 0xA0:
583 case 0xB0:
584 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
585 break;
586 case 0x1000: /* FRR */
587 break;
588 case 0x1020: /* GCR */
589 openpic_gcr_write(opp, val);
590 break;
591 case 0x1080: /* VIR */
592 break;
593 case 0x1090: /* PIR */
594 for (idx = 0; idx < opp->nb_cpus; idx++) {
595 if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) {
596 DPRINTF("Raise OpenPIC RESET output for CPU %d", idx);
597 dst = &opp->dst[idx];
598 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
599 } else if (!(val & (1 << idx)) && (opp->pir & (1 << idx))) {
600 DPRINTF("Lower OpenPIC RESET output for CPU %d", idx);
601 dst = &opp->dst[idx];
602 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
605 opp->pir = val;
606 break;
607 case 0x10A0: /* IPI_IVPR */
608 case 0x10B0:
609 case 0x10C0:
610 case 0x10D0:
612 int idx;
613 idx = (addr - 0x10A0) >> 4;
614 write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val);
616 break;
617 case 0x10E0: /* SPVE */
618 opp->spve = val & opp->vector_mask;
619 break;
620 default:
621 break;
625 static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
627 OpenPICState *opp = opaque;
628 uint32_t retval;
630 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
631 retval = 0xFFFFFFFF;
632 if (addr & 0xF) {
633 return retval;
635 switch (addr) {
636 case 0x1000: /* FRR */
637 retval = opp->frr;
638 break;
639 case 0x1020: /* GCR */
640 retval = opp->gcr;
641 break;
642 case 0x1080: /* VIR */
643 retval = opp->vir;
644 break;
645 case 0x1090: /* PIR */
646 retval = 0x00000000;
647 break;
648 case 0x00: /* Block Revision Register1 (BRR1) */
649 retval = opp->brr1;
650 break;
651 case 0x40:
652 case 0x50:
653 case 0x60:
654 case 0x70:
655 case 0x80:
656 case 0x90:
657 case 0xA0:
658 case 0xB0:
659 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
660 break;
661 case 0x10A0: /* IPI_IVPR */
662 case 0x10B0:
663 case 0x10C0:
664 case 0x10D0:
666 int idx;
667 idx = (addr - 0x10A0) >> 4;
668 retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx);
670 break;
671 case 0x10E0: /* SPVE */
672 retval = opp->spve;
673 break;
674 default:
675 break;
677 DPRINTF("%s: => 0x%08x", __func__, retval);
679 return retval;
682 static void openpic_tmr_set_tmr(OpenPICTimer *tmr, uint32_t val, bool enabled);
684 static void qemu_timer_cb(void *opaque)
686 OpenPICTimer *tmr = opaque;
687 OpenPICState *opp = tmr->opp;
688 uint32_t n_IRQ = tmr->n_IRQ;
689 uint32_t val = tmr->tbcr & ~TBCR_CI;
690 uint32_t tog = ((tmr->tccr & TCCR_TOG) ^ TCCR_TOG); /* invert toggle. */
692 DPRINTF("%s n_IRQ=%d", __func__, n_IRQ);
693 /* Reload current count from base count and setup timer. */
694 tmr->tccr = val | tog;
695 openpic_tmr_set_tmr(tmr, val, /*enabled=*/true);
696 /* Raise the interrupt. */
697 opp->src[n_IRQ].destmask = read_IRQreg_idr(opp, n_IRQ);
698 openpic_set_irq(opp, n_IRQ, 1);
699 openpic_set_irq(opp, n_IRQ, 0);
702 /* If enabled is true, arranges for an interrupt to be raised val clocks into
703 the future, if enabled is false cancels the timer. */
704 static void openpic_tmr_set_tmr(OpenPICTimer *tmr, uint32_t val, bool enabled)
706 uint64_t ns = ticks_to_ns(val & ~TCCR_TOG);
707 /* A count of zero causes a timer to be set to expire immediately. This
708 effectively stops the simulation since the timer is constantly expiring
709 which prevents guest code execution, so we don't honor that
710 configuration. On real hardware, this situation would generate an
711 interrupt on every clock cycle if the interrupt was unmasked. */
712 if ((ns == 0) || !enabled) {
713 tmr->qemu_timer_active = false;
714 tmr->tccr = tmr->tccr & TCCR_TOG;
715 timer_del(tmr->qemu_timer); /* set timer to never expire. */
716 } else {
717 tmr->qemu_timer_active = true;
718 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
719 tmr->origin_time = now;
720 timer_mod(tmr->qemu_timer, now + ns); /* set timer expiration. */
724 /* Returns the currrent tccr value, i.e., timer value (in clocks) with
725 appropriate TOG. */
726 static uint64_t openpic_tmr_get_timer(OpenPICTimer *tmr)
728 uint64_t retval;
729 if (!tmr->qemu_timer_active) {
730 retval = tmr->tccr;
731 } else {
732 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
733 uint64_t used = now - tmr->origin_time; /* nsecs */
734 uint32_t used_ticks = (uint32_t)ns_to_ticks(used);
735 uint32_t count = (tmr->tccr & ~TCCR_TOG) - used_ticks;
736 retval = (uint32_t)((tmr->tccr & TCCR_TOG) | (count & ~TCCR_TOG));
738 return retval;
741 static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
742 unsigned len)
744 OpenPICState *opp = opaque;
745 int idx;
747 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64,
748 __func__, (addr + 0x10f0), val);
749 if (addr & 0xF) {
750 return;
753 if (addr == 0) {
754 /* TFRR */
755 opp->tfrr = val;
756 return;
758 addr -= 0x10; /* correct for TFRR */
759 idx = (addr >> 6) & 0x3;
761 switch (addr & 0x30) {
762 case 0x00: /* TCCR */
763 break;
764 case 0x10: /* TBCR */
765 /* Did the enable status change? */
766 if ((opp->timers[idx].tbcr & TBCR_CI) != (val & TBCR_CI)) {
767 /* Did "Count Inhibit" transition from 1 to 0? */
768 if ((val & TBCR_CI) == 0) {
769 opp->timers[idx].tccr = val & ~TCCR_TOG;
771 openpic_tmr_set_tmr(&opp->timers[idx],
772 (val & ~TBCR_CI),
773 /*enabled=*/((val & TBCR_CI) == 0));
775 opp->timers[idx].tbcr = val;
776 break;
777 case 0x20: /* TVPR */
778 write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val);
779 break;
780 case 0x30: /* TDR */
781 write_IRQreg_idr(opp, opp->irq_tim0 + idx, val);
782 break;
786 static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
788 OpenPICState *opp = opaque;
789 uint32_t retval = -1;
790 int idx;
792 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr + 0x10f0);
793 if (addr & 0xF) {
794 goto out;
796 if (addr == 0) {
797 /* TFRR */
798 retval = opp->tfrr;
799 goto out;
801 addr -= 0x10; /* correct for TFRR */
802 idx = (addr >> 6) & 0x3;
803 switch (addr & 0x30) {
804 case 0x00: /* TCCR */
805 retval = openpic_tmr_get_timer(&opp->timers[idx]);
806 break;
807 case 0x10: /* TBCR */
808 retval = opp->timers[idx].tbcr;
809 break;
810 case 0x20: /* TVPR */
811 retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
812 break;
813 case 0x30: /* TDR */
814 retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
815 break;
818 out:
819 DPRINTF("%s: => 0x%08x", __func__, retval);
821 return retval;
824 static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
825 unsigned len)
827 OpenPICState *opp = opaque;
828 int idx;
830 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64,
831 __func__, addr, val);
833 addr = addr & 0xffff;
834 idx = addr >> 5;
836 switch (addr & 0x1f) {
837 case 0x00:
838 write_IRQreg_ivpr(opp, idx, val);
839 break;
840 case 0x10:
841 write_IRQreg_idr(opp, idx, val);
842 break;
843 case 0x18:
844 write_IRQreg_ilr(opp, idx, val);
845 break;
849 static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
851 OpenPICState *opp = opaque;
852 uint32_t retval;
853 int idx;
855 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
856 retval = 0xFFFFFFFF;
858 addr = addr & 0xffff;
859 idx = addr >> 5;
861 switch (addr & 0x1f) {
862 case 0x00:
863 retval = read_IRQreg_ivpr(opp, idx);
864 break;
865 case 0x10:
866 retval = read_IRQreg_idr(opp, idx);
867 break;
868 case 0x18:
869 retval = read_IRQreg_ilr(opp, idx);
870 break;
873 DPRINTF("%s: => 0x%08x", __func__, retval);
874 return retval;
877 static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
878 unsigned size)
880 OpenPICState *opp = opaque;
881 int idx = opp->irq_msi;
882 int srs, ibs;
884 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64,
885 __func__, addr, val);
886 if (addr & 0xF) {
887 return;
890 switch (addr) {
891 case MSIIR_OFFSET:
892 srs = val >> MSIIR_SRS_SHIFT;
893 idx += srs;
894 ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT;
895 opp->msi[srs].msir |= 1 << ibs;
896 openpic_set_irq(opp, idx, 1);
897 break;
898 default:
899 /* most registers are read-only, thus ignored */
900 break;
904 static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
906 OpenPICState *opp = opaque;
907 uint64_t r = 0;
908 int i, srs;
910 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
911 if (addr & 0xF) {
912 return -1;
915 srs = addr >> 4;
917 switch (addr) {
918 case 0x00:
919 case 0x10:
920 case 0x20:
921 case 0x30:
922 case 0x40:
923 case 0x50:
924 case 0x60:
925 case 0x70: /* MSIRs */
926 r = opp->msi[srs].msir;
927 /* Clear on read */
928 opp->msi[srs].msir = 0;
929 openpic_set_irq(opp, opp->irq_msi + srs, 0);
930 break;
931 case 0x120: /* MSISR */
932 for (i = 0; i < MAX_MSI; i++) {
933 r |= (opp->msi[i].msir ? 1 : 0) << i;
935 break;
938 return r;
941 static uint64_t openpic_summary_read(void *opaque, hwaddr addr, unsigned size)
943 uint64_t r = 0;
945 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
947 /* TODO: EISR/EIMR */
949 return r;
952 static void openpic_summary_write(void *opaque, hwaddr addr, uint64_t val,
953 unsigned size)
955 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64,
956 __func__, addr, val);
958 /* TODO: EISR/EIMR */
961 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
962 uint32_t val, int idx)
964 OpenPICState *opp = opaque;
965 IRQSource *src;
966 IRQDest *dst;
967 int s_IRQ, n_IRQ;
969 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x", __func__, idx,
970 addr, val);
972 if (idx < 0 || idx >= opp->nb_cpus) {
973 return;
976 if (addr & 0xF) {
977 return;
979 dst = &opp->dst[idx];
980 addr &= 0xFF0;
981 switch (addr) {
982 case 0x40: /* IPIDR */
983 case 0x50:
984 case 0x60:
985 case 0x70:
986 idx = (addr - 0x40) >> 4;
987 /* we use IDE as mask which CPUs to deliver the IPI to still. */
988 opp->src[opp->irq_ipi0 + idx].destmask |= val;
989 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
990 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
991 break;
992 case 0x80: /* CTPR */
993 dst->ctpr = val & 0x0000000F;
995 DPRINTF("%s: set CPU %d ctpr to %d, raised %d servicing %d",
996 __func__, idx, dst->ctpr, dst->raised.priority,
997 dst->servicing.priority);
999 if (dst->raised.priority <= dst->ctpr) {
1000 DPRINTF("%s: Lower OpenPIC INT output cpu %d due to ctpr",
1001 __func__, idx);
1002 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
1003 } else if (dst->raised.priority > dst->servicing.priority) {
1004 DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d",
1005 __func__, idx, dst->raised.next);
1006 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
1009 break;
1010 case 0x90: /* WHOAMI */
1011 /* Read-only register */
1012 break;
1013 case 0xA0: /* IACK */
1014 /* Read-only register */
1015 break;
1016 case 0xB0: /* EOI */
1017 DPRINTF("EOI");
1018 s_IRQ = IRQ_get_next(opp, &dst->servicing);
1020 if (s_IRQ < 0) {
1021 DPRINTF("%s: EOI with no interrupt in service", __func__);
1022 break;
1025 IRQ_resetbit(&dst->servicing, s_IRQ);
1026 /* Set up next servicing IRQ */
1027 s_IRQ = IRQ_get_next(opp, &dst->servicing);
1028 /* Check queued interrupts. */
1029 n_IRQ = IRQ_get_next(opp, &dst->raised);
1030 src = &opp->src[n_IRQ];
1031 if (n_IRQ != -1 &&
1032 (s_IRQ == -1 ||
1033 IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
1034 DPRINTF("Raise OpenPIC INT output cpu %d irq %d",
1035 idx, n_IRQ);
1036 qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
1038 break;
1039 default:
1040 break;
1044 static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
1045 unsigned len)
1047 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
1051 static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
1053 IRQSource *src;
1054 int retval, irq;
1056 DPRINTF("Lower OpenPIC INT output");
1057 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
1059 irq = IRQ_get_next(opp, &dst->raised);
1060 DPRINTF("IACK: irq=%d", irq);
1062 if (irq == -1) {
1063 /* No more interrupt pending */
1064 return opp->spve;
1067 src = &opp->src[irq];
1068 if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
1069 !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
1070 error_report("%s: bad raised IRQ %d ctpr %d ivpr 0x%08x",
1071 __func__, irq, dst->ctpr, src->ivpr);
1072 openpic_update_irq(opp, irq);
1073 retval = opp->spve;
1074 } else {
1075 /* IRQ enter servicing state */
1076 IRQ_setbit(&dst->servicing, irq);
1077 retval = IVPR_VECTOR(opp, src->ivpr);
1080 if (!src->level) {
1081 /* edge-sensitive IRQ */
1082 src->ivpr &= ~IVPR_ACTIVITY_MASK;
1083 src->pending = 0;
1084 IRQ_resetbit(&dst->raised, irq);
1087 /* Timers and IPIs support multicast. */
1088 if (((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + OPENPIC_MAX_IPI))) ||
1089 ((irq >= opp->irq_tim0) && (irq < (opp->irq_tim0 + OPENPIC_MAX_TMR)))) {
1090 DPRINTF("irq is IPI or TMR");
1091 src->destmask &= ~(1 << cpu);
1092 if (src->destmask && !src->level) {
1093 /* trigger on CPUs that didn't know about it yet */
1094 openpic_set_irq(opp, irq, 1);
1095 openpic_set_irq(opp, irq, 0);
1096 /* if all CPUs knew about it, set active bit again */
1097 src->ivpr |= IVPR_ACTIVITY_MASK;
1101 return retval;
1104 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
1105 int idx)
1107 OpenPICState *opp = opaque;
1108 IRQDest *dst;
1109 uint32_t retval;
1111 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx, __func__, idx, addr);
1112 retval = 0xFFFFFFFF;
1114 if (idx < 0 || idx >= opp->nb_cpus) {
1115 return retval;
1118 if (addr & 0xF) {
1119 return retval;
1121 dst = &opp->dst[idx];
1122 addr &= 0xFF0;
1123 switch (addr) {
1124 case 0x80: /* CTPR */
1125 retval = dst->ctpr;
1126 break;
1127 case 0x90: /* WHOAMI */
1128 retval = idx;
1129 break;
1130 case 0xA0: /* IACK */
1131 retval = openpic_iack(opp, dst, idx);
1132 break;
1133 case 0xB0: /* EOI */
1134 retval = 0;
1135 break;
1136 default:
1137 break;
1139 DPRINTF("%s: => 0x%08x", __func__, retval);
1141 return retval;
1144 static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
1146 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
1149 static const MemoryRegionOps openpic_glb_ops_le = {
1150 .write = openpic_gbl_write,
1151 .read = openpic_gbl_read,
1152 .endianness = DEVICE_LITTLE_ENDIAN,
1153 .impl = {
1154 .min_access_size = 4,
1155 .max_access_size = 4,
1159 static const MemoryRegionOps openpic_glb_ops_be = {
1160 .write = openpic_gbl_write,
1161 .read = openpic_gbl_read,
1162 .endianness = DEVICE_BIG_ENDIAN,
1163 .impl = {
1164 .min_access_size = 4,
1165 .max_access_size = 4,
1169 static const MemoryRegionOps openpic_tmr_ops_le = {
1170 .write = openpic_tmr_write,
1171 .read = openpic_tmr_read,
1172 .endianness = DEVICE_LITTLE_ENDIAN,
1173 .impl = {
1174 .min_access_size = 4,
1175 .max_access_size = 4,
1179 static const MemoryRegionOps openpic_tmr_ops_be = {
1180 .write = openpic_tmr_write,
1181 .read = openpic_tmr_read,
1182 .endianness = DEVICE_BIG_ENDIAN,
1183 .impl = {
1184 .min_access_size = 4,
1185 .max_access_size = 4,
1189 static const MemoryRegionOps openpic_cpu_ops_le = {
1190 .write = openpic_cpu_write,
1191 .read = openpic_cpu_read,
1192 .endianness = DEVICE_LITTLE_ENDIAN,
1193 .impl = {
1194 .min_access_size = 4,
1195 .max_access_size = 4,
1199 static const MemoryRegionOps openpic_cpu_ops_be = {
1200 .write = openpic_cpu_write,
1201 .read = openpic_cpu_read,
1202 .endianness = DEVICE_BIG_ENDIAN,
1203 .impl = {
1204 .min_access_size = 4,
1205 .max_access_size = 4,
1209 static const MemoryRegionOps openpic_src_ops_le = {
1210 .write = openpic_src_write,
1211 .read = openpic_src_read,
1212 .endianness = DEVICE_LITTLE_ENDIAN,
1213 .impl = {
1214 .min_access_size = 4,
1215 .max_access_size = 4,
1219 static const MemoryRegionOps openpic_src_ops_be = {
1220 .write = openpic_src_write,
1221 .read = openpic_src_read,
1222 .endianness = DEVICE_BIG_ENDIAN,
1223 .impl = {
1224 .min_access_size = 4,
1225 .max_access_size = 4,
1229 static const MemoryRegionOps openpic_msi_ops_be = {
1230 .read = openpic_msi_read,
1231 .write = openpic_msi_write,
1232 .endianness = DEVICE_BIG_ENDIAN,
1233 .impl = {
1234 .min_access_size = 4,
1235 .max_access_size = 4,
1239 static const MemoryRegionOps openpic_summary_ops_be = {
1240 .read = openpic_summary_read,
1241 .write = openpic_summary_write,
1242 .endianness = DEVICE_BIG_ENDIAN,
1243 .impl = {
1244 .min_access_size = 4,
1245 .max_access_size = 4,
1249 static void openpic_reset(DeviceState *d)
1251 OpenPICState *opp = OPENPIC(d);
1252 int i;
1254 opp->gcr = GCR_RESET;
1255 /* Initialise controller registers */
1256 opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
1257 ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
1258 (opp->vid << FRR_VID_SHIFT);
1260 opp->pir = 0;
1261 opp->spve = -1 & opp->vector_mask;
1262 opp->tfrr = opp->tfrr_reset;
1263 /* Initialise IRQ sources */
1264 for (i = 0; i < opp->max_irq; i++) {
1265 opp->src[i].ivpr = opp->ivpr_reset;
1266 switch (opp->src[i].type) {
1267 case IRQ_TYPE_NORMAL:
1268 opp->src[i].level = !!(opp->ivpr_reset & IVPR_SENSE_MASK);
1269 break;
1271 case IRQ_TYPE_FSLINT:
1272 opp->src[i].ivpr |= IVPR_POLARITY_MASK;
1273 break;
1275 case IRQ_TYPE_FSLSPECIAL:
1276 break;
1279 write_IRQreg_idr(opp, i, opp->idr_reset);
1281 /* Initialise IRQ destinations */
1282 for (i = 0; i < opp->nb_cpus; i++) {
1283 opp->dst[i].ctpr = 15;
1284 opp->dst[i].raised.next = -1;
1285 opp->dst[i].raised.priority = 0;
1286 bitmap_clear(opp->dst[i].raised.queue, 0, IRQQUEUE_SIZE_BITS);
1287 opp->dst[i].servicing.next = -1;
1288 opp->dst[i].servicing.priority = 0;
1289 bitmap_clear(opp->dst[i].servicing.queue, 0, IRQQUEUE_SIZE_BITS);
1291 /* Initialise timers */
1292 for (i = 0; i < OPENPIC_MAX_TMR; i++) {
1293 opp->timers[i].tccr = 0;
1294 opp->timers[i].tbcr = TBCR_CI;
1295 if (opp->timers[i].qemu_timer_active) {
1296 timer_del(opp->timers[i].qemu_timer); /* Inhibit timer */
1297 opp->timers[i].qemu_timer_active = false;
1300 /* Go out of RESET state */
1301 opp->gcr = 0;
1304 typedef struct MemReg {
1305 const char *name;
1306 MemoryRegionOps const *ops;
1307 hwaddr start_addr;
1308 ram_addr_t size;
1309 } MemReg;
1311 static void fsl_common_init(OpenPICState *opp)
1313 int i;
1314 int virq = OPENPIC_MAX_SRC;
1316 opp->vid = VID_REVISION_1_2;
1317 opp->vir = VIR_GENERIC;
1318 opp->vector_mask = 0xFFFF;
1319 opp->tfrr_reset = 0;
1320 opp->ivpr_reset = IVPR_MASK_MASK;
1321 opp->idr_reset = 1 << 0;
1322 opp->max_irq = OPENPIC_MAX_IRQ;
1324 opp->irq_ipi0 = virq;
1325 virq += OPENPIC_MAX_IPI;
1326 opp->irq_tim0 = virq;
1327 virq += OPENPIC_MAX_TMR;
1329 assert(virq <= OPENPIC_MAX_IRQ);
1331 opp->irq_msi = 224;
1333 msi_nonbroken = true;
1334 for (i = 0; i < opp->fsl->max_ext; i++) {
1335 opp->src[i].level = false;
1338 /* Internal interrupts, including message and MSI */
1339 for (i = 16; i < OPENPIC_MAX_SRC; i++) {
1340 opp->src[i].type = IRQ_TYPE_FSLINT;
1341 opp->src[i].level = true;
1344 /* timers and IPIs */
1345 for (i = OPENPIC_MAX_SRC; i < virq; i++) {
1346 opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
1347 opp->src[i].level = false;
1350 for (i = 0; i < OPENPIC_MAX_TMR; i++) {
1351 opp->timers[i].n_IRQ = opp->irq_tim0 + i;
1352 opp->timers[i].qemu_timer_active = false;
1353 opp->timers[i].qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1354 &qemu_timer_cb,
1355 &opp->timers[i]);
1356 opp->timers[i].opp = opp;
1360 static void map_list(OpenPICState *opp, const MemReg *list, int *count)
1362 while (list->name) {
1363 assert(*count < ARRAY_SIZE(opp->sub_io_mem));
1365 memory_region_init_io(&opp->sub_io_mem[*count], OBJECT(opp), list->ops,
1366 opp, list->name, list->size);
1368 memory_region_add_subregion(&opp->mem, list->start_addr,
1369 &opp->sub_io_mem[*count]);
1371 (*count)++;
1372 list++;
1376 static const VMStateDescription vmstate_openpic_irq_queue = {
1377 .name = "openpic_irq_queue",
1378 .version_id = 0,
1379 .minimum_version_id = 0,
1380 .fields = (VMStateField[]) {
1381 VMSTATE_BITMAP(queue, IRQQueue, 0, queue_size),
1382 VMSTATE_INT32(next, IRQQueue),
1383 VMSTATE_INT32(priority, IRQQueue),
1384 VMSTATE_END_OF_LIST()
1388 static const VMStateDescription vmstate_openpic_irqdest = {
1389 .name = "openpic_irqdest",
1390 .version_id = 0,
1391 .minimum_version_id = 0,
1392 .fields = (VMStateField[]) {
1393 VMSTATE_INT32(ctpr, IRQDest),
1394 VMSTATE_STRUCT(raised, IRQDest, 0, vmstate_openpic_irq_queue,
1395 IRQQueue),
1396 VMSTATE_STRUCT(servicing, IRQDest, 0, vmstate_openpic_irq_queue,
1397 IRQQueue),
1398 VMSTATE_UINT32_ARRAY(outputs_active, IRQDest, OPENPIC_OUTPUT_NB),
1399 VMSTATE_END_OF_LIST()
1403 static const VMStateDescription vmstate_openpic_irqsource = {
1404 .name = "openpic_irqsource",
1405 .version_id = 0,
1406 .minimum_version_id = 0,
1407 .fields = (VMStateField[]) {
1408 VMSTATE_UINT32(ivpr, IRQSource),
1409 VMSTATE_UINT32(idr, IRQSource),
1410 VMSTATE_UINT32(destmask, IRQSource),
1411 VMSTATE_INT32(last_cpu, IRQSource),
1412 VMSTATE_INT32(pending, IRQSource),
1413 VMSTATE_END_OF_LIST()
1417 static const VMStateDescription vmstate_openpic_timer = {
1418 .name = "openpic_timer",
1419 .version_id = 0,
1420 .minimum_version_id = 0,
1421 .fields = (VMStateField[]) {
1422 VMSTATE_UINT32(tccr, OpenPICTimer),
1423 VMSTATE_UINT32(tbcr, OpenPICTimer),
1424 VMSTATE_END_OF_LIST()
1428 static const VMStateDescription vmstate_openpic_msi = {
1429 .name = "openpic_msi",
1430 .version_id = 0,
1431 .minimum_version_id = 0,
1432 .fields = (VMStateField[]) {
1433 VMSTATE_UINT32(msir, OpenPICMSI),
1434 VMSTATE_END_OF_LIST()
1438 static int openpic_post_load(void *opaque, int version_id)
1440 OpenPICState *opp = (OpenPICState *)opaque;
1441 int i;
1443 /* Update internal ivpr and idr variables */
1444 for (i = 0; i < opp->max_irq; i++) {
1445 write_IRQreg_idr(opp, i, opp->src[i].idr);
1446 write_IRQreg_ivpr(opp, i, opp->src[i].ivpr);
1449 return 0;
1452 static const VMStateDescription vmstate_openpic = {
1453 .name = "openpic",
1454 .version_id = 3,
1455 .minimum_version_id = 3,
1456 .post_load = openpic_post_load,
1457 .fields = (VMStateField[]) {
1458 VMSTATE_UINT32(gcr, OpenPICState),
1459 VMSTATE_UINT32(vir, OpenPICState),
1460 VMSTATE_UINT32(pir, OpenPICState),
1461 VMSTATE_UINT32(spve, OpenPICState),
1462 VMSTATE_UINT32(tfrr, OpenPICState),
1463 VMSTATE_UINT32(max_irq, OpenPICState),
1464 VMSTATE_STRUCT_VARRAY_UINT32(src, OpenPICState, max_irq, 0,
1465 vmstate_openpic_irqsource, IRQSource),
1466 VMSTATE_UINT32_EQUAL(nb_cpus, OpenPICState, NULL),
1467 VMSTATE_STRUCT_VARRAY_UINT32(dst, OpenPICState, nb_cpus, 0,
1468 vmstate_openpic_irqdest, IRQDest),
1469 VMSTATE_STRUCT_ARRAY(timers, OpenPICState, OPENPIC_MAX_TMR, 0,
1470 vmstate_openpic_timer, OpenPICTimer),
1471 VMSTATE_STRUCT_ARRAY(msi, OpenPICState, MAX_MSI, 0,
1472 vmstate_openpic_msi, OpenPICMSI),
1473 VMSTATE_UINT32(irq_ipi0, OpenPICState),
1474 VMSTATE_UINT32(irq_tim0, OpenPICState),
1475 VMSTATE_UINT32(irq_msi, OpenPICState),
1476 VMSTATE_END_OF_LIST()
1480 static void openpic_init(Object *obj)
1482 OpenPICState *opp = OPENPIC(obj);
1484 memory_region_init(&opp->mem, obj, "openpic", 0x40000);
1487 static void openpic_realize(DeviceState *dev, Error **errp)
1489 SysBusDevice *d = SYS_BUS_DEVICE(dev);
1490 OpenPICState *opp = OPENPIC(dev);
1491 int i, j;
1492 int list_count = 0;
1493 static const MemReg list_le[] = {
1494 {"glb", &openpic_glb_ops_le,
1495 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1496 {"tmr", &openpic_tmr_ops_le,
1497 OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1498 {"src", &openpic_src_ops_le,
1499 OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1500 {"cpu", &openpic_cpu_ops_le,
1501 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1502 {NULL}
1504 static const MemReg list_be[] = {
1505 {"glb", &openpic_glb_ops_be,
1506 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1507 {"tmr", &openpic_tmr_ops_be,
1508 OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1509 {"src", &openpic_src_ops_be,
1510 OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1511 {"cpu", &openpic_cpu_ops_be,
1512 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1513 {NULL}
1515 static const MemReg list_fsl[] = {
1516 {"msi", &openpic_msi_ops_be,
1517 OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1518 {"summary", &openpic_summary_ops_be,
1519 OPENPIC_SUMMARY_REG_START, OPENPIC_SUMMARY_REG_SIZE},
1520 {NULL}
1523 if (opp->nb_cpus > MAX_CPU) {
1524 error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
1525 TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
1526 (uint64_t)0, (uint64_t)MAX_CPU);
1527 return;
1530 switch (opp->model) {
1531 case OPENPIC_MODEL_FSL_MPIC_20:
1532 default:
1533 opp->fsl = &fsl_mpic_20;
1534 opp->brr1 = 0x00400200;
1535 opp->flags |= OPENPIC_FLAG_IDR_CRIT;
1536 opp->nb_irqs = 80;
1537 opp->mpic_mode_mask = GCR_MODE_MIXED;
1539 fsl_common_init(opp);
1540 map_list(opp, list_be, &list_count);
1541 map_list(opp, list_fsl, &list_count);
1543 break;
1545 case OPENPIC_MODEL_FSL_MPIC_42:
1546 opp->fsl = &fsl_mpic_42;
1547 opp->brr1 = 0x00400402;
1548 opp->flags |= OPENPIC_FLAG_ILR;
1549 opp->nb_irqs = 196;
1550 opp->mpic_mode_mask = GCR_MODE_PROXY;
1552 fsl_common_init(opp);
1553 map_list(opp, list_be, &list_count);
1554 map_list(opp, list_fsl, &list_count);
1556 break;
1558 case OPENPIC_MODEL_RAVEN:
1559 opp->nb_irqs = RAVEN_MAX_EXT;
1560 opp->vid = VID_REVISION_1_3;
1561 opp->vir = VIR_GENERIC;
1562 opp->vector_mask = 0xFF;
1563 opp->tfrr_reset = 4160000;
1564 opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
1565 opp->idr_reset = 0;
1566 opp->max_irq = RAVEN_MAX_IRQ;
1567 opp->irq_ipi0 = RAVEN_IPI_IRQ;
1568 opp->irq_tim0 = RAVEN_TMR_IRQ;
1569 opp->brr1 = -1;
1570 opp->mpic_mode_mask = GCR_MODE_MIXED;
1572 if (opp->nb_cpus != 1) {
1573 error_setg(errp, "Only UP supported today");
1574 return;
1577 map_list(opp, list_le, &list_count);
1578 break;
1580 case OPENPIC_MODEL_KEYLARGO:
1581 opp->nb_irqs = KEYLARGO_MAX_EXT;
1582 opp->vid = VID_REVISION_1_2;
1583 opp->vir = VIR_GENERIC;
1584 opp->vector_mask = 0xFF;
1585 opp->tfrr_reset = 4160000;
1586 opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
1587 opp->idr_reset = 0;
1588 opp->max_irq = KEYLARGO_MAX_IRQ;
1589 opp->irq_ipi0 = KEYLARGO_IPI_IRQ;
1590 opp->irq_tim0 = KEYLARGO_TMR_IRQ;
1591 opp->brr1 = -1;
1592 opp->mpic_mode_mask = GCR_MODE_MIXED;
1594 if (opp->nb_cpus != 1) {
1595 error_setg(errp, "Only UP supported today");
1596 return;
1599 map_list(opp, list_le, &list_count);
1600 break;
1603 for (i = 0; i < opp->nb_cpus; i++) {
1604 opp->dst[i].irqs = g_new0(qemu_irq, OPENPIC_OUTPUT_NB);
1605 for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
1606 sysbus_init_irq(d, &opp->dst[i].irqs[j]);
1609 opp->dst[i].raised.queue_size = IRQQUEUE_SIZE_BITS;
1610 opp->dst[i].raised.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
1611 opp->dst[i].servicing.queue_size = IRQQUEUE_SIZE_BITS;
1612 opp->dst[i].servicing.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
1615 sysbus_init_mmio(d, &opp->mem);
1616 qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq);
1619 static Property openpic_properties[] = {
1620 DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_FSL_MPIC_20),
1621 DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1),
1622 DEFINE_PROP_END_OF_LIST(),
1625 static void openpic_class_init(ObjectClass *oc, void *data)
1627 DeviceClass *dc = DEVICE_CLASS(oc);
1629 dc->realize = openpic_realize;
1630 device_class_set_props(dc, openpic_properties);
1631 dc->reset = openpic_reset;
1632 dc->vmsd = &vmstate_openpic;
1633 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
1636 static const TypeInfo openpic_info = {
1637 .name = TYPE_OPENPIC,
1638 .parent = TYPE_SYS_BUS_DEVICE,
1639 .instance_size = sizeof(OpenPICState),
1640 .instance_init = openpic_init,
1641 .class_init = openpic_class_init,
1644 static void openpic_register_types(void)
1646 type_register_static(&openpic_info);
1649 type_init(openpic_register_types)