Lines Matching +full:opp +full:- +full:0

28  * - Motorola MPC8245 & MPC8540 user manuals.
29 * - Motorola Harrier programmer manual
38 #include "hw/qdev-properties.h"
46 #include "qemu/error-report.h"
53 static const int debug_openpic = 0;
61 } while (0)
64 #define OPENPIC_FLAG_IDR_CRIT (1 << 0)
65 #define OPENPIC_FLAG_ILR (2 << 0)
68 #define OPENPIC_GLB_REG_START 0x0
69 #define OPENPIC_GLB_REG_SIZE 0x10F0
70 #define OPENPIC_TMR_REG_START 0x10F0
71 #define OPENPIC_TMR_REG_SIZE 0x220
72 #define OPENPIC_MSI_REG_START 0x1600
73 #define OPENPIC_MSI_REG_SIZE 0x200
74 #define OPENPIC_SUMMARY_REG_START 0x3800
75 #define OPENPIC_SUMMARY_REG_SIZE 0x800
76 #define OPENPIC_SRC_REG_START 0x10000
77 #define OPENPIC_SRC_REG_SIZE (OPENPIC_MAX_SRC * 0x20)
78 #define OPENPIC_CPU_REG_START 0x20000
79 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
91 #define FRR_VID_SHIFT 0
96 #define VIR_GENERIC 0x00000000 /* Generic Vendor ID */
97 #define VIR_MPIC2A 0x00004614 /* IBM MPIC-2A */
99 #define GCR_RESET 0x80000000
100 #define GCR_MODE_PASS 0x00000000
101 #define GCR_MODE_MIXED 0x20000000
102 #define GCR_MODE_PROXY 0x60000000
104 #define TBCR_CI 0x80000000 /* count inhibit */
105 #define TCCR_TOG 0x80000000 /* toggles when decrement to zero */
112 #define IDR_P0_SHIFT 0
114 #define ILR_INTTGT_MASK 0x000000ff
115 #define ILR_INTTGT_INT 0x00
116 #define ILR_INTTGT_CINT 0x01 /* critical */
117 #define ILR_INTTGT_MCP 0x02 /* machine check */
135 for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) { in inttgt_to_output()
136 if (inttgt_output[i][0] == inttgt) { in inttgt_to_output()
149 for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) { in output_to_inttgt()
151 return inttgt_output[i][0]; in output_to_inttgt()
158 #define MSIIR_OFFSET 0x140
160 #define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT)
162 #define MSIIR_IBS_MASK (0x1f << MSIIR_IBS_SHIFT)
167 return -1; in get_current_cpu()
170 return current_cpu->cpu_index; in get_current_cpu()
197 set_bit(n_IRQ, q->queue); in IRQ_setbit()
202 clear_bit(n_IRQ, q->queue); in IRQ_resetbit()
205 static void IRQ_check(OpenPICState *opp, IRQQueue *q) in IRQ_check() argument
207 int irq = -1; in IRQ_check()
208 int next = -1; in IRQ_check()
209 int priority = -1; in IRQ_check()
212 irq = find_next_bit(q->queue, opp->max_irq, irq + 1); in IRQ_check()
213 if (irq == opp->max_irq) { in IRQ_check()
218 irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority); in IRQ_check()
220 if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) { in IRQ_check()
222 priority = IVPR_PRIORITY(opp->src[irq].ivpr); in IRQ_check()
226 q->next = next; in IRQ_check()
227 q->priority = priority; in IRQ_check()
230 static int IRQ_get_next(OpenPICState *opp, IRQQueue *q) in IRQ_get_next() argument
233 IRQ_check(opp, q); in IRQ_get_next()
235 return q->next; in IRQ_get_next()
238 static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ, in IRQ_local_pipe() argument
245 dst = &opp->dst[n_CPU]; in IRQ_local_pipe()
246 src = &opp->src[n_IRQ]; in IRQ_local_pipe()
251 if (src->output != OPENPIC_OUTPUT_INT) { in IRQ_local_pipe()
253 __func__, src->output, n_IRQ, active, was_active, in IRQ_local_pipe()
254 dst->outputs_active[src->output]); in IRQ_local_pipe()
262 if (!was_active && dst->outputs_active[src->output]++ == 0) { in IRQ_local_pipe()
264 __func__, src->output, n_CPU, n_IRQ); in IRQ_local_pipe()
265 qemu_irq_raise(dst->irqs[src->output]); in IRQ_local_pipe()
268 if (was_active && --dst->outputs_active[src->output] == 0) { in IRQ_local_pipe()
270 __func__, src->output, n_CPU, n_IRQ); in IRQ_local_pipe()
271 qemu_irq_lower(dst->irqs[src->output]); in IRQ_local_pipe()
278 priority = IVPR_PRIORITY(src->ivpr); in IRQ_local_pipe()
285 IRQ_setbit(&dst->raised, n_IRQ); in IRQ_local_pipe()
287 IRQ_resetbit(&dst->raised, n_IRQ); in IRQ_local_pipe()
290 IRQ_check(opp, &dst->raised); in IRQ_local_pipe()
292 if (active && priority <= dst->ctpr) { in IRQ_local_pipe()
294 __func__, n_IRQ, priority, dst->ctpr, n_CPU); in IRQ_local_pipe()
295 active = 0; in IRQ_local_pipe()
299 if (IRQ_get_next(opp, &dst->servicing) >= 0 && in IRQ_local_pipe()
300 priority <= dst->servicing.priority) { in IRQ_local_pipe()
302 __func__, n_IRQ, dst->servicing.next, n_CPU); in IRQ_local_pipe()
305 __func__, n_CPU, n_IRQ, dst->raised.next); in IRQ_local_pipe()
306 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); in IRQ_local_pipe()
309 IRQ_get_next(opp, &dst->servicing); in IRQ_local_pipe()
310 if (dst->raised.priority > dst->ctpr && in IRQ_local_pipe()
311 dst->raised.priority > dst->servicing.priority) { in IRQ_local_pipe()
313 __func__, n_IRQ, dst->raised.next, dst->raised.priority, in IRQ_local_pipe()
314 dst->ctpr, dst->servicing.priority, n_CPU); in IRQ_local_pipe()
318 __func__, n_IRQ, dst->ctpr, dst->servicing.priority, n_CPU); in IRQ_local_pipe()
319 qemu_irq_lower(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); in IRQ_local_pipe()
325 static void openpic_update_irq(OpenPICState *opp, int n_IRQ) in openpic_update_irq() argument
331 src = &opp->src[n_IRQ]; in openpic_update_irq()
332 active = src->pending; in openpic_update_irq()
334 if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) { in openpic_update_irq()
340 was_active = !!(src->ivpr & IVPR_ACTIVITY_MASK); in openpic_update_irq()
343 * We don't have a similar check for already-active because in openpic_update_irq()
352 src->ivpr |= IVPR_ACTIVITY_MASK; in openpic_update_irq()
354 src->ivpr &= ~IVPR_ACTIVITY_MASK; in openpic_update_irq()
357 if (src->destmask == 0) { in openpic_update_irq()
363 if (src->destmask == (1 << src->last_cpu)) { in openpic_update_irq()
365 IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active); in openpic_update_irq()
366 } else if (!(src->ivpr & IVPR_MODE_MASK)) { in openpic_update_irq()
368 for (i = 0; i < opp->nb_cpus; i++) { in openpic_update_irq()
369 if (src->destmask & (1 << i)) { in openpic_update_irq()
370 IRQ_local_pipe(opp, i, n_IRQ, active, was_active); in openpic_update_irq()
375 for (i = src->last_cpu + 1; i != src->last_cpu; i++) { in openpic_update_irq()
376 if (i == opp->nb_cpus) { in openpic_update_irq()
377 i = 0; in openpic_update_irq()
379 if (src->destmask & (1 << i)) { in openpic_update_irq()
380 IRQ_local_pipe(opp, i, n_IRQ, active, was_active); in openpic_update_irq()
381 src->last_cpu = i; in openpic_update_irq()
390 OpenPICState *opp = opaque; in openpic_set_irq() local
398 src = &opp->src[n_IRQ]; in openpic_set_irq()
399 DPRINTF("openpic: set irq %d = %d ivpr=0x%08x", in openpic_set_irq()
400 n_IRQ, level, src->ivpr); in openpic_set_irq()
401 if (src->level) { in openpic_set_irq()
402 /* level-sensitive irq */ in openpic_set_irq()
403 src->pending = level; in openpic_set_irq()
404 openpic_update_irq(opp, n_IRQ); in openpic_set_irq()
406 /* edge-sensitive irq */ in openpic_set_irq()
408 src->pending = 1; in openpic_set_irq()
409 openpic_update_irq(opp, n_IRQ); in openpic_set_irq()
412 if (src->output != OPENPIC_OUTPUT_INT) { in openpic_set_irq()
414 * Edge-triggered interrupts shouldn't be used in openpic_set_irq()
415 * with non-INT delivery, but just in case, in openpic_set_irq()
420 src->pending = 0; in openpic_set_irq()
421 openpic_update_irq(opp, n_IRQ); in openpic_set_irq()
426 static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ) in read_IRQreg_idr() argument
428 return opp->src[n_IRQ].idr; in read_IRQreg_idr()
431 static inline uint32_t read_IRQreg_ilr(OpenPICState *opp, int n_IRQ) in read_IRQreg_ilr() argument
433 if (opp->flags & OPENPIC_FLAG_ILR) { in read_IRQreg_ilr()
434 return output_to_inttgt(opp->src[n_IRQ].output); in read_IRQreg_ilr()
437 return 0xffffffff; in read_IRQreg_ilr()
440 static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ) in read_IRQreg_ivpr() argument
442 return opp->src[n_IRQ].ivpr; in read_IRQreg_ivpr()
445 static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val) in write_IRQreg_idr() argument
447 IRQSource *src = &opp->src[n_IRQ]; in write_IRQreg_idr()
448 uint32_t normal_mask = (1UL << opp->nb_cpus) - 1; in write_IRQreg_idr()
449 uint32_t crit_mask = 0; in write_IRQreg_idr()
451 int crit_shift = IDR_EP_SHIFT - opp->nb_cpus; in write_IRQreg_idr()
454 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) { in write_IRQreg_idr()
459 src->idr = val & mask; in write_IRQreg_idr()
460 DPRINTF("Set IDR %d to 0x%08x", n_IRQ, src->idr); in write_IRQreg_idr()
462 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) { in write_IRQreg_idr()
463 if (src->idr & crit_mask) { in write_IRQreg_idr()
464 if (src->idr & normal_mask) { in write_IRQreg_idr()
469 src->output = OPENPIC_OUTPUT_CINT; in write_IRQreg_idr()
470 src->nomask = true; in write_IRQreg_idr()
471 src->destmask = 0; in write_IRQreg_idr()
473 for (i = 0; i < opp->nb_cpus; i++) { in write_IRQreg_idr()
474 int n_ci = IDR_CI0_SHIFT - i; in write_IRQreg_idr()
476 if (src->idr & (1UL << n_ci)) { in write_IRQreg_idr()
477 src->destmask |= 1UL << i; in write_IRQreg_idr()
481 src->output = OPENPIC_OUTPUT_INT; in write_IRQreg_idr()
482 src->nomask = false; in write_IRQreg_idr()
483 src->destmask = src->idr & normal_mask; in write_IRQreg_idr()
486 src->destmask = src->idr; in write_IRQreg_idr()
490 static inline void write_IRQreg_ilr(OpenPICState *opp, int n_IRQ, uint32_t val) in write_IRQreg_ilr() argument
492 if (opp->flags & OPENPIC_FLAG_ILR) { in write_IRQreg_ilr()
493 IRQSource *src = &opp->src[n_IRQ]; in write_IRQreg_ilr()
495 src->output = inttgt_to_output(val & ILR_INTTGT_MASK); in write_IRQreg_ilr()
496 DPRINTF("Set ILR %d to 0x%08x, output %d", n_IRQ, src->idr, in write_IRQreg_ilr()
497 src->output); in write_IRQreg_ilr()
499 /* TODO: on MPIC v4.0 only, set nomask for non-INT */ in write_IRQreg_ilr()
503 static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val) in write_IRQreg_ivpr() argument
508 * NOTE when implementing newer FSL MPIC models: starting with v4.0, in write_IRQreg_ivpr()
509 * the polarity bit is read-only on internal interrupts. in write_IRQreg_ivpr()
512 IVPR_POLARITY_MASK | opp->vector_mask; in write_IRQreg_ivpr()
514 /* ACTIVITY bit is read-only */ in write_IRQreg_ivpr()
515 opp->src[n_IRQ].ivpr = in write_IRQreg_ivpr()
516 (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) | (val & mask); in write_IRQreg_ivpr()
520 * and the interrupt is always level-triggered. Timers and IPIs in write_IRQreg_ivpr()
521 * have no sense or polarity bits, and are edge-triggered. in write_IRQreg_ivpr()
523 switch (opp->src[n_IRQ].type) { in write_IRQreg_ivpr()
525 opp->src[n_IRQ].level = !!(opp->src[n_IRQ].ivpr & IVPR_SENSE_MASK); in write_IRQreg_ivpr()
529 opp->src[n_IRQ].ivpr &= ~IVPR_SENSE_MASK; in write_IRQreg_ivpr()
533 opp->src[n_IRQ].ivpr &= ~(IVPR_POLARITY_MASK | IVPR_SENSE_MASK); in write_IRQreg_ivpr()
537 openpic_update_irq(opp, n_IRQ); in write_IRQreg_ivpr()
538 DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x", n_IRQ, val, in write_IRQreg_ivpr()
539 opp->src[n_IRQ].ivpr); in write_IRQreg_ivpr()
542 static void openpic_gcr_write(OpenPICState *opp, uint64_t val) in openpic_gcr_write() argument
547 openpic_reset(DEVICE(opp)); in openpic_gcr_write()
551 opp->gcr &= ~opp->mpic_mode_mask; in openpic_gcr_write()
552 opp->gcr |= val & opp->mpic_mode_mask; in openpic_gcr_write()
555 if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) { in openpic_gcr_write()
565 OpenPICState *opp = opaque; in openpic_gbl_write() local
571 if (addr & 0xF) { in openpic_gbl_write()
575 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */ in openpic_gbl_write()
577 case 0x40: in openpic_gbl_write()
578 case 0x50: in openpic_gbl_write()
579 case 0x60: in openpic_gbl_write()
580 case 0x70: in openpic_gbl_write()
581 case 0x80: in openpic_gbl_write()
582 case 0x90: in openpic_gbl_write()
583 case 0xA0: in openpic_gbl_write()
584 case 0xB0: in openpic_gbl_write()
585 openpic_cpu_write_internal(opp, addr, val, get_current_cpu()); in openpic_gbl_write()
587 case 0x1000: /* FRR */ in openpic_gbl_write()
589 case 0x1020: /* GCR */ in openpic_gbl_write()
590 openpic_gcr_write(opp, val); in openpic_gbl_write()
592 case 0x1080: /* VIR */ in openpic_gbl_write()
594 case 0x1090: /* PIR */ in openpic_gbl_write()
595 for (idx = 0; idx < opp->nb_cpus; idx++) { in openpic_gbl_write()
596 if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) { in openpic_gbl_write()
598 dst = &opp->dst[idx]; in openpic_gbl_write()
599 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]); in openpic_gbl_write()
600 } else if (!(val & (1 << idx)) && (opp->pir & (1 << idx))) { in openpic_gbl_write()
602 dst = &opp->dst[idx]; in openpic_gbl_write()
603 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]); in openpic_gbl_write()
606 opp->pir = val; in openpic_gbl_write()
608 case 0x10A0: /* IPI_IVPR */ in openpic_gbl_write()
609 case 0x10B0: in openpic_gbl_write()
610 case 0x10C0: in openpic_gbl_write()
611 case 0x10D0: in openpic_gbl_write()
612 idx = (addr - 0x10A0) >> 4; in openpic_gbl_write()
613 write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val); in openpic_gbl_write()
615 case 0x10E0: /* SPVE */ in openpic_gbl_write()
616 opp->spve = val & opp->vector_mask; in openpic_gbl_write()
625 OpenPICState *opp = opaque; in openpic_gbl_read() local
629 retval = 0xFFFFFFFF; in openpic_gbl_read()
630 if (addr & 0xF) { in openpic_gbl_read()
634 case 0x1000: /* FRR */ in openpic_gbl_read()
635 retval = opp->frr; in openpic_gbl_read()
637 case 0x1020: /* GCR */ in openpic_gbl_read()
638 retval = opp->gcr; in openpic_gbl_read()
640 case 0x1080: /* VIR */ in openpic_gbl_read()
641 retval = opp->vir; in openpic_gbl_read()
643 case 0x1090: /* PIR */ in openpic_gbl_read()
644 retval = 0x00000000; in openpic_gbl_read()
646 case 0x00: /* Block Revision Register1 (BRR1) */ in openpic_gbl_read()
647 retval = opp->brr1; in openpic_gbl_read()
649 case 0x40: in openpic_gbl_read()
650 case 0x50: in openpic_gbl_read()
651 case 0x60: in openpic_gbl_read()
652 case 0x70: in openpic_gbl_read()
653 case 0x80: in openpic_gbl_read()
654 case 0x90: in openpic_gbl_read()
655 case 0xA0: in openpic_gbl_read()
656 case 0xB0: in openpic_gbl_read()
657 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu()); in openpic_gbl_read()
659 case 0x10A0: /* IPI_IVPR */ in openpic_gbl_read()
660 case 0x10B0: in openpic_gbl_read()
661 case 0x10C0: in openpic_gbl_read()
662 case 0x10D0: in openpic_gbl_read()
665 idx = (addr - 0x10A0) >> 4; in openpic_gbl_read()
666 retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx); in openpic_gbl_read()
669 case 0x10E0: /* SPVE */ in openpic_gbl_read()
670 retval = opp->spve; in openpic_gbl_read()
675 DPRINTF("%s: => 0x%08x", __func__, retval); in openpic_gbl_read()
685 OpenPICState *opp = tmr->opp; in qemu_timer_cb() local
686 uint32_t n_IRQ = tmr->n_IRQ; in qemu_timer_cb()
687 uint32_t val = tmr->tbcr & ~TBCR_CI; in qemu_timer_cb()
688 uint32_t tog = ((tmr->tccr & TCCR_TOG) ^ TCCR_TOG); /* invert toggle. */ in qemu_timer_cb()
692 tmr->tccr = val | tog; in qemu_timer_cb()
695 opp->src[n_IRQ].destmask = read_IRQreg_idr(opp, n_IRQ); in qemu_timer_cb()
696 openpic_set_irq(opp, n_IRQ, 1); in qemu_timer_cb()
697 openpic_set_irq(opp, n_IRQ, 0); in qemu_timer_cb()
714 if ((ns == 0) || !enabled) { in openpic_tmr_set_tmr()
715 tmr->qemu_timer_active = false; in openpic_tmr_set_tmr()
716 tmr->tccr = tmr->tccr & TCCR_TOG; in openpic_tmr_set_tmr()
717 timer_del(tmr->qemu_timer); /* set timer to never expire. */ in openpic_tmr_set_tmr()
719 tmr->qemu_timer_active = true; in openpic_tmr_set_tmr()
721 tmr->origin_time = now; in openpic_tmr_set_tmr()
722 timer_mod(tmr->qemu_timer, now + ns); /* set timer expiration. */ in openpic_tmr_set_tmr()
733 if (!tmr->qemu_timer_active) { in openpic_tmr_get_timer()
734 retval = tmr->tccr; in openpic_tmr_get_timer()
737 uint64_t used = now - tmr->origin_time; /* nsecs */ in openpic_tmr_get_timer()
739 uint32_t count = (tmr->tccr & ~TCCR_TOG) - used_ticks; in openpic_tmr_get_timer()
740 retval = (uint32_t)((tmr->tccr & TCCR_TOG) | (count & ~TCCR_TOG)); in openpic_tmr_get_timer()
748 OpenPICState *opp = opaque; in openpic_tmr_write() local
752 __func__, (addr + 0x10f0), val); in openpic_tmr_write()
753 if (addr & 0xF) { in openpic_tmr_write()
757 if (addr == 0) { in openpic_tmr_write()
759 opp->tfrr = val; in openpic_tmr_write()
762 addr -= 0x10; /* correct for TFRR */ in openpic_tmr_write()
763 idx = (addr >> 6) & 0x3; in openpic_tmr_write()
765 switch (addr & 0x30) { in openpic_tmr_write()
766 case 0x00: /* TCCR */ in openpic_tmr_write()
768 case 0x10: /* TBCR */ in openpic_tmr_write()
770 if ((opp->timers[idx].tbcr & TBCR_CI) != (val & TBCR_CI)) { in openpic_tmr_write()
771 /* Did "Count Inhibit" transition from 1 to 0? */ in openpic_tmr_write()
772 if ((val & TBCR_CI) == 0) { in openpic_tmr_write()
773 opp->timers[idx].tccr = val & ~TCCR_TOG; in openpic_tmr_write()
775 openpic_tmr_set_tmr(&opp->timers[idx], in openpic_tmr_write()
777 /*enabled=*/((val & TBCR_CI) == 0)); in openpic_tmr_write()
779 opp->timers[idx].tbcr = val; in openpic_tmr_write()
781 case 0x20: /* TVPR */ in openpic_tmr_write()
782 write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val); in openpic_tmr_write()
784 case 0x30: /* TDR */ in openpic_tmr_write()
785 write_IRQreg_idr(opp, opp->irq_tim0 + idx, val); in openpic_tmr_write()
792 OpenPICState *opp = opaque; in openpic_tmr_read() local
793 uint32_t retval = -1; in openpic_tmr_read()
796 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr + 0x10f0); in openpic_tmr_read()
797 if (addr & 0xF) { in openpic_tmr_read()
800 if (addr == 0) { in openpic_tmr_read()
802 retval = opp->tfrr; in openpic_tmr_read()
805 addr -= 0x10; /* correct for TFRR */ in openpic_tmr_read()
806 idx = (addr >> 6) & 0x3; in openpic_tmr_read()
807 switch (addr & 0x30) { in openpic_tmr_read()
808 case 0x00: /* TCCR */ in openpic_tmr_read()
809 retval = openpic_tmr_get_timer(&opp->timers[idx]); in openpic_tmr_read()
811 case 0x10: /* TBCR */ in openpic_tmr_read()
812 retval = opp->timers[idx].tbcr; in openpic_tmr_read()
814 case 0x20: /* TVPR */ in openpic_tmr_read()
815 retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx); in openpic_tmr_read()
817 case 0x30: /* TDR */ in openpic_tmr_read()
818 retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx); in openpic_tmr_read()
823 DPRINTF("%s: => 0x%08x", __func__, retval); in openpic_tmr_read()
831 OpenPICState *opp = opaque; in openpic_src_write() local
837 addr = addr & 0xffff; in openpic_src_write()
840 switch (addr & 0x1f) { in openpic_src_write()
841 case 0x00: in openpic_src_write()
842 write_IRQreg_ivpr(opp, idx, val); in openpic_src_write()
844 case 0x10: in openpic_src_write()
845 write_IRQreg_idr(opp, idx, val); in openpic_src_write()
847 case 0x18: in openpic_src_write()
848 write_IRQreg_ilr(opp, idx, val); in openpic_src_write()
855 OpenPICState *opp = opaque; in openpic_src_read() local
860 retval = 0xFFFFFFFF; in openpic_src_read()
862 addr = addr & 0xffff; in openpic_src_read()
865 switch (addr & 0x1f) { in openpic_src_read()
866 case 0x00: in openpic_src_read()
867 retval = read_IRQreg_ivpr(opp, idx); in openpic_src_read()
869 case 0x10: in openpic_src_read()
870 retval = read_IRQreg_idr(opp, idx); in openpic_src_read()
872 case 0x18: in openpic_src_read()
873 retval = read_IRQreg_ilr(opp, idx); in openpic_src_read()
877 DPRINTF("%s: => 0x%08x", __func__, retval); in openpic_src_read()
884 OpenPICState *opp = opaque; in openpic_msi_write() local
885 int idx = opp->irq_msi; in openpic_msi_write()
888 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64, in openpic_msi_write()
890 if (addr & 0xF) { in openpic_msi_write()
899 opp->msi[srs].msir |= 1 << ibs; in openpic_msi_write()
900 openpic_set_irq(opp, idx, 1); in openpic_msi_write()
903 /* most registers are read-only, thus ignored */ in openpic_msi_write()
910 OpenPICState *opp = opaque; in openpic_msi_read() local
911 uint64_t r = 0; in openpic_msi_read()
915 if (addr & 0xF) { in openpic_msi_read()
916 return -1; in openpic_msi_read()
922 case 0x00: in openpic_msi_read()
923 case 0x10: in openpic_msi_read()
924 case 0x20: in openpic_msi_read()
925 case 0x30: in openpic_msi_read()
926 case 0x40: in openpic_msi_read()
927 case 0x50: in openpic_msi_read()
928 case 0x60: in openpic_msi_read()
929 case 0x70: /* MSIRs */ in openpic_msi_read()
930 r = opp->msi[srs].msir; in openpic_msi_read()
932 opp->msi[srs].msir = 0; in openpic_msi_read()
933 openpic_set_irq(opp, opp->irq_msi + srs, 0); in openpic_msi_read()
935 case 0x120: /* MSISR */ in openpic_msi_read()
936 for (i = 0; i < MAX_MSI; i++) { in openpic_msi_read()
937 r |= (opp->msi[i].msir ? 1 : 0) << i; in openpic_msi_read()
947 uint64_t r = 0; in openpic_summary_read()
959 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64, in openpic_summary_write()
968 OpenPICState *opp = opaque; in openpic_cpu_write_internal() local
973 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x", __func__, idx, in openpic_cpu_write_internal()
976 if (idx < 0 || idx >= opp->nb_cpus) { in openpic_cpu_write_internal()
980 if (addr & 0xF) { in openpic_cpu_write_internal()
983 dst = &opp->dst[idx]; in openpic_cpu_write_internal()
984 addr &= 0xFF0; in openpic_cpu_write_internal()
986 case 0x40: /* IPIDR */ in openpic_cpu_write_internal()
987 case 0x50: in openpic_cpu_write_internal()
988 case 0x60: in openpic_cpu_write_internal()
989 case 0x70: in openpic_cpu_write_internal()
990 idx = (addr - 0x40) >> 4; in openpic_cpu_write_internal()
992 opp->src[opp->irq_ipi0 + idx].destmask |= val; in openpic_cpu_write_internal()
993 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1); in openpic_cpu_write_internal()
994 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0); in openpic_cpu_write_internal()
996 case 0x80: /* CTPR */ in openpic_cpu_write_internal()
997 dst->ctpr = val & 0x0000000F; in openpic_cpu_write_internal()
1000 __func__, idx, dst->ctpr, dst->raised.priority, in openpic_cpu_write_internal()
1001 dst->servicing.priority); in openpic_cpu_write_internal()
1003 if (dst->raised.priority <= dst->ctpr) { in openpic_cpu_write_internal()
1006 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]); in openpic_cpu_write_internal()
1007 } else if (dst->raised.priority > dst->servicing.priority) { in openpic_cpu_write_internal()
1009 __func__, idx, dst->raised.next); in openpic_cpu_write_internal()
1010 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]); in openpic_cpu_write_internal()
1014 case 0x90: /* WHOAMI */ in openpic_cpu_write_internal()
1015 /* Read-only register */ in openpic_cpu_write_internal()
1017 case 0xA0: /* IACK */ in openpic_cpu_write_internal()
1018 /* Read-only register */ in openpic_cpu_write_internal()
1020 case 0xB0: /* EOI */ in openpic_cpu_write_internal()
1022 s_IRQ = IRQ_get_next(opp, &dst->servicing); in openpic_cpu_write_internal()
1024 if (s_IRQ < 0) { in openpic_cpu_write_internal()
1029 IRQ_resetbit(&dst->servicing, s_IRQ); in openpic_cpu_write_internal()
1031 s_IRQ = IRQ_get_next(opp, &dst->servicing); in openpic_cpu_write_internal()
1033 n_IRQ = IRQ_get_next(opp, &dst->raised); in openpic_cpu_write_internal()
1034 if (n_IRQ != -1) { in openpic_cpu_write_internal()
1035 src = &opp->src[n_IRQ]; in openpic_cpu_write_internal()
1036 if (s_IRQ == -1 || in openpic_cpu_write_internal()
1037 IVPR_PRIORITY(src->ivpr) > dst->servicing.priority) { in openpic_cpu_write_internal()
1040 qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]); in openpic_cpu_write_internal()
1052 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12); in openpic_cpu_write()
1056 static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu) in openpic_iack() argument
1062 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]); in openpic_iack()
1064 irq = IRQ_get_next(opp, &dst->raised); in openpic_iack()
1067 if (irq == -1) { in openpic_iack()
1069 return opp->spve; in openpic_iack()
1072 src = &opp->src[irq]; in openpic_iack()
1073 if (!(src->ivpr & IVPR_ACTIVITY_MASK) || in openpic_iack()
1074 !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) { in openpic_iack()
1075 error_report("%s: bad raised IRQ %d ctpr %d ivpr 0x%08x", in openpic_iack()
1076 __func__, irq, dst->ctpr, src->ivpr); in openpic_iack()
1077 openpic_update_irq(opp, irq); in openpic_iack()
1078 retval = opp->spve; in openpic_iack()
1081 IRQ_setbit(&dst->servicing, irq); in openpic_iack()
1082 retval = IVPR_VECTOR(opp, src->ivpr); in openpic_iack()
1085 if (!src->level) { in openpic_iack()
1086 /* edge-sensitive IRQ */ in openpic_iack()
1087 src->ivpr &= ~IVPR_ACTIVITY_MASK; in openpic_iack()
1088 src->pending = 0; in openpic_iack()
1089 IRQ_resetbit(&dst->raised, irq); in openpic_iack()
1093 if (((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + OPENPIC_MAX_IPI))) || in openpic_iack()
1094 ((irq >= opp->irq_tim0) && (irq < (opp->irq_tim0 + OPENPIC_MAX_TMR)))) { in openpic_iack()
1096 src->destmask &= ~(1 << cpu); in openpic_iack()
1097 if (src->destmask && !src->level) { in openpic_iack()
1099 openpic_set_irq(opp, irq, 1); in openpic_iack()
1100 openpic_set_irq(opp, irq, 0); in openpic_iack()
1102 src->ivpr |= IVPR_ACTIVITY_MASK; in openpic_iack()
1112 OpenPICState *opp = opaque; in openpic_cpu_read_internal() local
1117 retval = 0xFFFFFFFF; in openpic_cpu_read_internal()
1119 if (idx < 0 || idx >= opp->nb_cpus) { in openpic_cpu_read_internal()
1123 if (addr & 0xF) { in openpic_cpu_read_internal()
1126 dst = &opp->dst[idx]; in openpic_cpu_read_internal()
1127 addr &= 0xFF0; in openpic_cpu_read_internal()
1129 case 0x80: /* CTPR */ in openpic_cpu_read_internal()
1130 retval = dst->ctpr; in openpic_cpu_read_internal()
1132 case 0x90: /* WHOAMI */ in openpic_cpu_read_internal()
1135 case 0xA0: /* IACK */ in openpic_cpu_read_internal()
1136 retval = openpic_iack(opp, dst, idx); in openpic_cpu_read_internal()
1138 case 0xB0: /* EOI */ in openpic_cpu_read_internal()
1139 retval = 0; in openpic_cpu_read_internal()
1144 DPRINTF("%s: => 0x%08x", __func__, retval); in openpic_cpu_read_internal()
1151 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12); in openpic_cpu_read()
1256 OpenPICState *opp = OPENPIC(d); in openpic_reset() local
1259 opp->gcr = GCR_RESET; in openpic_reset()
1261 opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) | in openpic_reset()
1262 ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) | in openpic_reset()
1263 (opp->vid << FRR_VID_SHIFT); in openpic_reset()
1265 opp->pir = 0; in openpic_reset()
1266 opp->spve = -1 & opp->vector_mask; in openpic_reset()
1267 opp->tfrr = opp->tfrr_reset; in openpic_reset()
1269 for (i = 0; i < opp->max_irq; i++) { in openpic_reset()
1270 opp->src[i].ivpr = opp->ivpr_reset; in openpic_reset()
1271 switch (opp->src[i].type) { in openpic_reset()
1273 opp->src[i].level = !!(opp->ivpr_reset & IVPR_SENSE_MASK); in openpic_reset()
1277 opp->src[i].ivpr |= IVPR_POLARITY_MASK; in openpic_reset()
1285 if ((opp->model == OPENPIC_MODEL_FSL_MPIC_20) || in openpic_reset()
1286 (opp->model == OPENPIC_MODEL_FSL_MPIC_42)) { in openpic_reset()
1287 if (i >= opp->irq_ipi0 && i < opp->irq_tim0) { in openpic_reset()
1288 write_IRQreg_idr(opp, i, 0); in openpic_reset()
1293 write_IRQreg_idr(opp, i, opp->idr_reset); in openpic_reset()
1296 for (i = 0; i < opp->nb_cpus; i++) { in openpic_reset()
1297 opp->dst[i].ctpr = 15; in openpic_reset()
1298 opp->dst[i].raised.next = -1; in openpic_reset()
1299 opp->dst[i].raised.priority = 0; in openpic_reset()
1300 bitmap_clear(opp->dst[i].raised.queue, 0, IRQQUEUE_SIZE_BITS); in openpic_reset()
1301 opp->dst[i].servicing.next = -1; in openpic_reset()
1302 opp->dst[i].servicing.priority = 0; in openpic_reset()
1303 bitmap_clear(opp->dst[i].servicing.queue, 0, IRQQUEUE_SIZE_BITS); in openpic_reset()
1306 for (i = 0; i < OPENPIC_MAX_TMR; i++) { in openpic_reset()
1307 opp->timers[i].tccr = 0; in openpic_reset()
1308 opp->timers[i].tbcr = TBCR_CI; in openpic_reset()
1309 if (opp->timers[i].qemu_timer_active) { in openpic_reset()
1310 timer_del(opp->timers[i].qemu_timer); /* Inhibit timer */ in openpic_reset()
1311 opp->timers[i].qemu_timer_active = false; in openpic_reset()
1315 opp->gcr = 0; in openpic_reset()
1325 static void fsl_common_init(OpenPICState *opp) in fsl_common_init() argument
1330 opp->vid = VID_REVISION_1_2; in fsl_common_init()
1331 opp->vir = VIR_GENERIC; in fsl_common_init()
1332 opp->vector_mask = 0xFFFF; in fsl_common_init()
1333 opp->tfrr_reset = 0; in fsl_common_init()
1334 opp->ivpr_reset = IVPR_MASK_MASK; in fsl_common_init()
1335 opp->idr_reset = 1 << 0; in fsl_common_init()
1336 opp->max_irq = OPENPIC_MAX_IRQ; in fsl_common_init()
1338 opp->irq_ipi0 = virq; in fsl_common_init()
1340 opp->irq_tim0 = virq; in fsl_common_init()
1345 opp->irq_msi = 224; in fsl_common_init()
1348 for (i = 0; i < opp->fsl->max_ext; i++) { in fsl_common_init()
1349 opp->src[i].level = false; in fsl_common_init()
1354 opp->src[i].type = IRQ_TYPE_FSLINT; in fsl_common_init()
1355 opp->src[i].level = true; in fsl_common_init()
1360 opp->src[i].type = IRQ_TYPE_FSLSPECIAL; in fsl_common_init()
1361 opp->src[i].level = false; in fsl_common_init()
1364 for (i = 0; i < OPENPIC_MAX_TMR; i++) { in fsl_common_init()
1365 opp->timers[i].n_IRQ = opp->irq_tim0 + i; in fsl_common_init()
1366 opp->timers[i].qemu_timer_active = false; in fsl_common_init()
1367 opp->timers[i].qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, in fsl_common_init()
1369 &opp->timers[i]); in fsl_common_init()
1370 opp->timers[i].opp = opp; in fsl_common_init()
1374 static void map_list(OpenPICState *opp, const MemReg *list, int *count) in map_list() argument
1376 while (list->name) { in map_list()
1377 assert(*count < ARRAY_SIZE(opp->sub_io_mem)); in map_list()
1379 memory_region_init_io(&opp->sub_io_mem[*count], OBJECT(opp), list->ops, in map_list()
1380 opp, list->name, list->size); in map_list()
1382 memory_region_add_subregion(&opp->mem, list->start_addr, in map_list()
1383 &opp->sub_io_mem[*count]); in map_list()
1392 .version_id = 0,
1393 .minimum_version_id = 0,
1395 VMSTATE_BITMAP(queue, IRQQueue, 0, queue_size),
1404 .version_id = 0,
1405 .minimum_version_id = 0,
1408 VMSTATE_STRUCT(raised, IRQDest, 0, vmstate_openpic_irq_queue,
1410 VMSTATE_STRUCT(servicing, IRQDest, 0, vmstate_openpic_irq_queue,
1419 .version_id = 0,
1420 .minimum_version_id = 0,
1433 .version_id = 0,
1434 .minimum_version_id = 0,
1444 .version_id = 0,
1445 .minimum_version_id = 0,
1454 OpenPICState *opp = (OpenPICState *)opaque; in openpic_post_load() local
1458 for (i = 0; i < opp->max_irq; i++) { in openpic_post_load()
1459 write_IRQreg_idr(opp, i, opp->src[i].idr); in openpic_post_load()
1460 write_IRQreg_ivpr(opp, i, opp->src[i].ivpr); in openpic_post_load()
1463 return 0; in openpic_post_load()
1478 VMSTATE_STRUCT_VARRAY_UINT32(src, OpenPICState, max_irq, 0,
1481 VMSTATE_STRUCT_VARRAY_UINT32(dst, OpenPICState, nb_cpus, 0,
1483 VMSTATE_STRUCT_ARRAY(timers, OpenPICState, OPENPIC_MAX_TMR, 0,
1485 VMSTATE_STRUCT_ARRAY(msi, OpenPICState, MAX_MSI, 0,
1496 OpenPICState *opp = OPENPIC(obj); in openpic_init() local
1498 memory_region_init(&opp->mem, obj, "openpic", 0x40000); in openpic_init()
1504 OpenPICState *opp = OPENPIC(dev); in openpic_realize() local
1506 int list_count = 0; in openpic_realize()
1537 if (opp->nb_cpus > MAX_CPU) { in openpic_realize()
1542 switch (opp->model) { in openpic_realize()
1545 opp->fsl = &fsl_mpic_20; in openpic_realize()
1546 opp->brr1 = 0x00400200; in openpic_realize()
1547 opp->flags |= OPENPIC_FLAG_IDR_CRIT; in openpic_realize()
1548 opp->nb_irqs = 80; in openpic_realize()
1549 opp->mpic_mode_mask = GCR_MODE_MIXED; in openpic_realize()
1551 fsl_common_init(opp); in openpic_realize()
1552 map_list(opp, list_be, &list_count); in openpic_realize()
1553 map_list(opp, list_fsl, &list_count); in openpic_realize()
1558 opp->fsl = &fsl_mpic_42; in openpic_realize()
1559 opp->brr1 = 0x00400402; in openpic_realize()
1560 opp->flags |= OPENPIC_FLAG_ILR; in openpic_realize()
1561 opp->nb_irqs = 196; in openpic_realize()
1562 opp->mpic_mode_mask = GCR_MODE_PROXY; in openpic_realize()
1564 fsl_common_init(opp); in openpic_realize()
1565 map_list(opp, list_be, &list_count); in openpic_realize()
1566 map_list(opp, list_fsl, &list_count); in openpic_realize()
1571 opp->nb_irqs = KEYLARGO_MAX_EXT; in openpic_realize()
1572 opp->vid = VID_REVISION_1_2; in openpic_realize()
1573 opp->vir = VIR_GENERIC; in openpic_realize()
1574 opp->vector_mask = 0xFF; in openpic_realize()
1575 opp->tfrr_reset = 4160000; in openpic_realize()
1576 opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK; in openpic_realize()
1577 opp->idr_reset = 0; in openpic_realize()
1578 opp->max_irq = KEYLARGO_MAX_IRQ; in openpic_realize()
1579 opp->irq_ipi0 = KEYLARGO_IPI_IRQ; in openpic_realize()
1580 opp->irq_tim0 = KEYLARGO_TMR_IRQ; in openpic_realize()
1581 opp->brr1 = -1; in openpic_realize()
1582 opp->mpic_mode_mask = GCR_MODE_MIXED; in openpic_realize()
1584 if (opp->nb_cpus != 1) { in openpic_realize()
1589 map_list(opp, list_le, &list_count); in openpic_realize()
1593 for (i = 0; i < opp->nb_cpus; i++) { in openpic_realize()
1594 opp->dst[i].irqs = g_new0(qemu_irq, OPENPIC_OUTPUT_NB); in openpic_realize()
1595 for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { in openpic_realize()
1596 sysbus_init_irq(d, &opp->dst[i].irqs[j]); in openpic_realize()
1599 opp->dst[i].raised.queue_size = IRQQUEUE_SIZE_BITS; in openpic_realize()
1600 opp->dst[i].raised.queue = bitmap_new(IRQQUEUE_SIZE_BITS); in openpic_realize()
1601 opp->dst[i].servicing.queue_size = IRQQUEUE_SIZE_BITS; in openpic_realize()
1602 opp->dst[i].servicing.queue = bitmap_new(IRQQUEUE_SIZE_BITS); in openpic_realize()
1605 sysbus_init_mmio(d, &opp->mem); in openpic_realize()
1606 qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq); in openpic_realize()
1619 dc->realize = openpic_realize; in openpic_class_init()
1622 dc->vmsd = &vmstate_openpic; in openpic_class_init()
1623 set_bit(DEVICE_CATEGORY_MISC, dc->categories); in openpic_class_init()