4 * Copyright (c) 2004 Jocelyn Mayer
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
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.
41 //#define DEBUG_OPENPIC
44 #define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
46 #define DPRINTF(fmt, ...) do { } while (0)
54 #define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR)
55 #define VID 0x03 /* MPIC version ID */
63 #define OPENPIC_MAX_CPU 2
64 #define OPENPIC_MAX_IRQ 64
65 #define OPENPIC_EXT_IRQ 48
66 #define OPENPIC_MAX_TMR MAX_TMR
67 #define OPENPIC_MAX_IPI MAX_IPI
69 /* Interrupt definitions */
70 #define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
71 #define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
72 #define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
73 #if OPENPIC_MAX_IPI > 0
74 #define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
75 #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
77 #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
78 #define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
81 #define OPENPIC_GLB_REG_START 0x0
82 #define OPENPIC_GLB_REG_SIZE 0x10F0
83 #define OPENPIC_TMR_REG_START 0x10F0
84 #define OPENPIC_TMR_REG_SIZE 0x220
85 #define OPENPIC_SRC_REG_START 0x10000
86 #define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
87 #define OPENPIC_CPU_REG_START 0x20000
88 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
91 #define MPIC_MAX_CPU 1
92 #define MPIC_MAX_EXT 12
93 #define MPIC_MAX_INT 64
94 #define MPIC_MAX_IRQ MAX_IRQ
96 /* Interrupt definitions */
97 /* IRQs, accessible through the IRQ region */
98 #define MPIC_EXT_IRQ 0x00
99 #define MPIC_INT_IRQ 0x10
100 #define MPIC_MSG_IRQ 0xb0
101 #define MPIC_MSI_IRQ 0xe0
102 /* These are available through separate regions, but
103 for simplicity's sake mapped into the same number space */
104 #define MPIC_TMR_IRQ 0x100
105 #define MPIC_IPI_IRQ 0x104
107 #define MPIC_GLB_REG_START 0x0
108 #define MPIC_GLB_REG_SIZE 0x10F0
109 #define MPIC_TMR_REG_START 0x10F0
110 #define MPIC_TMR_REG_SIZE 0x220
111 #define MPIC_SRC_REG_START 0x10000
112 #define MPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
113 #define MPIC_CPU_REG_START 0x20000
114 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
117 * Block Revision Register1 (BRR1): QEMU does not fully emulate
118 * any version on MPIC. So to start with, set the IP version to 0.
120 * NOTE: This is Freescale MPIC specific register. Keep it here till
121 * this code is refactored for different variants of OPENPIC and MPIC.
123 #define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
124 #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
125 #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
127 #define FREP_NIRQ_SHIFT 16
128 #define FREP_NCPU_SHIFT 8
129 #define FREP_VID_SHIFT 0
131 #define VID_REVISION_1_2 2
133 #define VENI_GENERIC 0x00000000 /* Generic Vendor ID */
143 #define BF_WIDTH(_bits_) \
144 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
146 static inline void set_bit (uint32_t *field, int bit)
148 field[bit >> 5] |= 1 << (bit & 0x1F);
151 static inline void reset_bit (uint32_t *field, int bit)
153 field[bit >> 5] &= ~(1 << (bit & 0x1F));
156 static inline int test_bit (uint32_t *field, int bit)
158 return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
161 static int get_current_cpu(void)
163 return cpu_single_env->cpu_index;
166 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
168 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
169 uint32_t val, int idx);
171 typedef struct IRQ_queue_t {
172 uint32_t queue[BF_WIDTH(MAX_IRQ)];
177 typedef struct IRQ_src_t {
178 uint32_t ipvp; /* IRQ vector/priority register */
179 uint32_t ide; /* IRQ destination register */
181 int pending; /* TRUE if IRQ is pending */
191 #define IPVP_PRIORITY_MASK (0x1F << 16)
192 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
193 #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
194 #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
196 typedef struct IRQ_dst_t {
197 uint32_t pctp; /* CPU current task priority */
198 uint32_t pcsr; /* CPU sensitivity register */
200 IRQ_queue_t servicing;
204 typedef struct openpic_t {
208 /* Behavior control */
212 uint32_t veni; /* Vendor identification register */
219 MemoryRegion sub_io_mem[7];
221 /* Global registers */
222 uint32_t frep; /* Feature reporting register */
223 uint32_t glbc; /* Global configuration register */
224 uint32_t pint; /* Processor initialization register */
225 uint32_t spve; /* Spurious vector register */
226 uint32_t tifr; /* Timer frequency reporting register */
227 /* Source registers */
228 IRQ_src_t src[MAX_IRQ];
229 /* Local registers per output pin */
230 IRQ_dst_t dst[MAX_CPU];
232 /* Timer registers */
234 uint32_t ticc; /* Global timer current count register */
235 uint32_t tibc; /* Global timer base count register */
237 /* IRQ out is used when in bypass mode (not implemented) */
244 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src);
246 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
248 set_bit(q->queue, n_IRQ);
251 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
253 reset_bit(q->queue, n_IRQ);
256 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
258 return test_bit(q->queue, n_IRQ);
261 static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
268 for (i = 0; i < opp->max_irq; i++) {
269 if (IRQ_testbit(q, i)) {
270 DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
271 i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
272 if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
274 priority = IPVP_PRIORITY(opp->src[i].ipvp);
279 q->priority = priority;
282 static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
292 static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
298 dst = &opp->dst[n_CPU];
299 src = &opp->src[n_IRQ];
300 priority = IPVP_PRIORITY(src->ipvp);
301 if (priority <= dst->pctp) {
302 /* Too low priority */
303 DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
304 __func__, n_IRQ, n_CPU);
307 if (IRQ_testbit(&dst->raised, n_IRQ)) {
309 DPRINTF("%s: IRQ %d was missed on CPU %d\n",
310 __func__, n_IRQ, n_CPU);
313 set_bit(&src->ipvp, IPVP_ACTIVITY);
314 IRQ_setbit(&dst->raised, n_IRQ);
315 if (priority < dst->raised.priority) {
316 /* An higher priority IRQ is already raised */
317 DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
318 __func__, n_IRQ, dst->raised.next, n_CPU);
321 IRQ_get_next(opp, &dst->raised);
322 if (IRQ_get_next(opp, &dst->servicing) != -1 &&
323 priority <= dst->servicing.priority) {
324 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
325 __func__, n_IRQ, dst->servicing.next, n_CPU);
326 /* Already servicing a higher priority IRQ */
329 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
330 openpic_irq_raise(opp, n_CPU, src);
333 /* update pic state because registers for n_IRQ have changed value */
334 static void openpic_update_irq(openpic_t *opp, int n_IRQ)
339 src = &opp->src[n_IRQ];
343 DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
346 if (test_bit(&src->ipvp, IPVP_MASK)) {
347 /* Interrupt source is disabled */
348 DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
351 if (IPVP_PRIORITY(src->ipvp) == 0) {
352 /* Priority set to zero */
353 DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
356 if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
357 /* IRQ already active */
358 DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
361 if (src->ide == 0x00000000) {
363 DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
367 if (src->ide == (1 << src->last_cpu)) {
368 /* Only one CPU is allowed to receive this IRQ */
369 IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
370 } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
371 /* Directed delivery mode */
372 for (i = 0; i < opp->nb_cpus; i++) {
373 if (test_bit(&src->ide, i))
374 IRQ_local_pipe(opp, i, n_IRQ);
377 /* Distributed delivery mode */
378 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
379 if (i == opp->nb_cpus)
381 if (test_bit(&src->ide, i)) {
382 IRQ_local_pipe(opp, i, n_IRQ);
390 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
392 openpic_t *opp = opaque;
395 src = &opp->src[n_IRQ];
396 DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
397 n_IRQ, level, src->ipvp);
398 if (test_bit(&src->ipvp, IPVP_SENSE)) {
399 /* level-sensitive irq */
400 src->pending = level;
402 reset_bit(&src->ipvp, IPVP_ACTIVITY);
404 /* edge-sensitive irq */
408 openpic_update_irq(opp, n_IRQ);
411 static void openpic_reset (void *opaque)
413 openpic_t *opp = (openpic_t *)opaque;
416 opp->glbc = 0x80000000;
417 /* Initialise controller registers */
418 opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
419 ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
420 (opp->vid << FREP_VID_SHIFT);
422 opp->pint = 0x00000000;
423 opp->spve = -1 & opp->spve_mask;
424 opp->tifr = opp->tifr_reset;
425 /* Initialise IRQ sources */
426 for (i = 0; i < opp->max_irq; i++) {
427 opp->src[i].ipvp = opp->ipvp_reset;
428 opp->src[i].ide = opp->ide_reset;
430 /* Initialise IRQ destinations */
431 for (i = 0; i < MAX_CPU; i++) {
432 opp->dst[i].pctp = 0x0000000F;
433 opp->dst[i].pcsr = 0x00000000;
434 memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
435 opp->dst[i].raised.next = -1;
436 memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
437 opp->dst[i].servicing.next = -1;
439 /* Initialise timers */
440 for (i = 0; i < MAX_TMR; i++) {
441 opp->timers[i].ticc = 0x00000000;
442 opp->timers[i].tibc = 0x80000000;
444 /* Go out of RESET state */
445 opp->glbc = 0x00000000;
448 static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
450 return opp->src[n_IRQ].ide;
453 static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
455 return opp->src[n_IRQ].ipvp;
458 static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
462 tmp = val & 0xC0000000;
463 tmp |= val & ((1ULL << MAX_CPU) - 1);
464 opp->src[n_IRQ].ide = tmp;
465 DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
468 static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
470 /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
471 /* ACTIVITY bit is read-only */
472 opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
473 | (val & 0x800F00FF);
474 openpic_update_irq(opp, n_IRQ);
475 DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
476 opp->src[n_IRQ].ipvp);
479 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
482 openpic_t *opp = opaque;
486 DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
490 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
500 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
502 case 0x1000: /* FREP */
504 case 0x1020: /* GLBC */
505 if (val & 0x80000000) {
509 case 0x1080: /* VENI */
511 case 0x1090: /* PINT */
512 for (idx = 0; idx < opp->nb_cpus; idx++) {
513 if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
514 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
515 dst = &opp->dst[idx];
516 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
517 } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
518 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
519 dst = &opp->dst[idx];
520 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
525 case 0x10A0: /* IPI_IPVP */
531 idx = (addr - 0x10A0) >> 4;
532 write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
535 case 0x10E0: /* SPVE */
536 opp->spve = val & opp->spve_mask;
543 static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
545 openpic_t *opp = opaque;
548 DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
553 case 0x1000: /* FREP */
556 case 0x1020: /* GLBC */
559 case 0x1080: /* VENI */
562 case 0x1090: /* PINT */
565 case 0x00: /* Block Revision Register1 (BRR1) */
574 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
576 case 0x10A0: /* IPI_IPVP */
582 idx = (addr - 0x10A0) >> 4;
583 retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
586 case 0x10E0: /* SPVE */
592 DPRINTF("%s: => %08x\n", __func__, retval);
597 static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val,
600 openpic_t *opp = opaque;
603 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
606 idx = (addr >> 6) & 0x3;
614 switch (addr & 0x30) {
615 case 0x00: /* TICC (GTCCR) */
617 case 0x10: /* TIBC (GTBCR) */
618 if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
619 (val & 0x80000000) == 0 &&
620 (opp->timers[idx].tibc & 0x80000000) != 0)
621 opp->timers[idx].ticc &= ~0x80000000;
622 opp->timers[idx].tibc = val;
624 case 0x20: /* TIVP (GTIVPR) */
625 write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
627 case 0x30: /* TIDE (GTIDR) */
628 write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
633 static uint64_t openpic_timer_read(void *opaque, hwaddr addr, unsigned len)
635 openpic_t *opp = opaque;
636 uint32_t retval = -1;
639 DPRINTF("%s: addr %08x\n", __func__, addr);
643 idx = (addr >> 6) & 0x3;
649 switch (addr & 0x30) {
650 case 0x00: /* TICC (GTCCR) */
651 retval = opp->timers[idx].ticc;
653 case 0x10: /* TIBC (GTBCR) */
654 retval = opp->timers[idx].tibc;
656 case 0x20: /* TIPV (TIPV) */
657 retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
659 case 0x30: /* TIDE (TIDR) */
660 retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
665 DPRINTF("%s: => %08x\n", __func__, retval);
670 static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
673 openpic_t *opp = opaque;
676 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
679 addr = addr & 0xFFF0;
682 /* EXDE / IFEDE / IEEDE */
683 write_IRQreg_ide(opp, idx, val);
685 /* EXVP / IFEVP / IEEVP */
686 write_IRQreg_ipvp(opp, idx, val);
690 static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
692 openpic_t *opp = opaque;
696 DPRINTF("%s: addr %08x\n", __func__, addr);
700 addr = addr & 0xFFF0;
703 /* EXDE / IFEDE / IEEDE */
704 retval = read_IRQreg_ide(opp, idx);
706 /* EXVP / IFEVP / IEEVP */
707 retval = read_IRQreg_ipvp(opp, idx);
709 DPRINTF("%s: => %08x\n", __func__, retval);
714 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
715 uint32_t val, int idx)
717 openpic_t *opp = opaque;
722 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
726 dst = &opp->dst[idx];
729 case 0x40: /* IPIDR */
733 idx = (addr - 0x40) >> 4;
734 /* we use IDE as mask which CPUs to deliver the IPI to still. */
735 write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
736 opp->src[opp->irq_ipi0 + idx].ide | val);
737 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
738 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
740 case 0x80: /* PCTP */
741 dst->pctp = val & 0x0000000F;
743 case 0x90: /* WHOAMI */
744 /* Read-only register */
746 case 0xA0: /* PIAC */
747 /* Read-only register */
749 case 0xB0: /* PEOI */
751 s_IRQ = IRQ_get_next(opp, &dst->servicing);
752 IRQ_resetbit(&dst->servicing, s_IRQ);
753 dst->servicing.next = -1;
754 /* Set up next servicing IRQ */
755 s_IRQ = IRQ_get_next(opp, &dst->servicing);
756 /* Check queued interrupts. */
757 n_IRQ = IRQ_get_next(opp, &dst->raised);
758 src = &opp->src[n_IRQ];
761 IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
762 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
764 openpic_irq_raise(opp, idx, src);
772 static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
775 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
778 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
781 openpic_t *opp = opaque;
787 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
791 dst = &opp->dst[idx];
794 case 0x00: /* Block Revision Register1 (BRR1) */
795 retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
797 case 0x80: /* PCTP */
800 case 0x90: /* WHOAMI */
803 case 0xA0: /* PIAC */
804 DPRINTF("Lower OpenPIC INT output\n");
805 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
806 n_IRQ = IRQ_get_next(opp, &dst->raised);
807 DPRINTF("PIAC: irq=%d\n", n_IRQ);
809 /* No more interrupt pending */
810 retval = IPVP_VECTOR(opp->spve);
812 src = &opp->src[n_IRQ];
813 if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
814 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
815 /* - Spurious level-sensitive IRQ
816 * - Priorities has been changed
817 * and the pending IRQ isn't allowed anymore
819 reset_bit(&src->ipvp, IPVP_ACTIVITY);
820 retval = IPVP_VECTOR(opp->spve);
822 /* IRQ enter servicing state */
823 IRQ_setbit(&dst->servicing, n_IRQ);
824 retval = IPVP_VECTOR(src->ipvp);
826 IRQ_resetbit(&dst->raised, n_IRQ);
827 dst->raised.next = -1;
828 if (!test_bit(&src->ipvp, IPVP_SENSE)) {
829 /* edge-sensitive IRQ */
830 reset_bit(&src->ipvp, IPVP_ACTIVITY);
834 if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
835 src->ide &= ~(1 << idx);
836 if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
837 /* trigger on CPUs that didn't know about it yet */
838 openpic_set_irq(opp, n_IRQ, 1);
839 openpic_set_irq(opp, n_IRQ, 0);
840 /* if all CPUs knew about it, set active bit again */
841 set_bit(&src->ipvp, IPVP_ACTIVITY);
846 case 0xB0: /* PEOI */
852 DPRINTF("%s: => %08x\n", __func__, retval);
857 static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
859 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
862 static const MemoryRegionOps openpic_glb_ops_le = {
863 .write = openpic_gbl_write,
864 .read = openpic_gbl_read,
865 .endianness = DEVICE_LITTLE_ENDIAN,
867 .min_access_size = 4,
868 .max_access_size = 4,
872 static const MemoryRegionOps openpic_glb_ops_be = {
873 .write = openpic_gbl_write,
874 .read = openpic_gbl_read,
875 .endianness = DEVICE_BIG_ENDIAN,
877 .min_access_size = 4,
878 .max_access_size = 4,
882 static const MemoryRegionOps openpic_tmr_ops_le = {
883 .write = openpic_timer_write,
884 .read = openpic_timer_read,
885 .endianness = DEVICE_LITTLE_ENDIAN,
887 .min_access_size = 4,
888 .max_access_size = 4,
892 static const MemoryRegionOps openpic_tmr_ops_be = {
893 .write = openpic_timer_write,
894 .read = openpic_timer_read,
895 .endianness = DEVICE_BIG_ENDIAN,
897 .min_access_size = 4,
898 .max_access_size = 4,
902 static const MemoryRegionOps openpic_cpu_ops_le = {
903 .write = openpic_cpu_write,
904 .read = openpic_cpu_read,
905 .endianness = DEVICE_LITTLE_ENDIAN,
907 .min_access_size = 4,
908 .max_access_size = 4,
912 static const MemoryRegionOps openpic_cpu_ops_be = {
913 .write = openpic_cpu_write,
914 .read = openpic_cpu_read,
915 .endianness = DEVICE_BIG_ENDIAN,
917 .min_access_size = 4,
918 .max_access_size = 4,
922 static const MemoryRegionOps openpic_src_ops_le = {
923 .write = openpic_src_write,
924 .read = openpic_src_read,
925 .endianness = DEVICE_LITTLE_ENDIAN,
927 .min_access_size = 4,
928 .max_access_size = 4,
932 static const MemoryRegionOps openpic_src_ops_be = {
933 .write = openpic_src_write,
934 .read = openpic_src_read,
935 .endianness = DEVICE_BIG_ENDIAN,
937 .min_access_size = 4,
938 .max_access_size = 4,
942 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
946 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
947 qemu_put_be32s(f, &q->queue[i]);
949 qemu_put_sbe32s(f, &q->next);
950 qemu_put_sbe32s(f, &q->priority);
953 static void openpic_save(QEMUFile* f, void *opaque)
955 openpic_t *opp = (openpic_t *)opaque;
958 qemu_put_be32s(f, &opp->glbc);
959 qemu_put_be32s(f, &opp->veni);
960 qemu_put_be32s(f, &opp->pint);
961 qemu_put_be32s(f, &opp->spve);
962 qemu_put_be32s(f, &opp->tifr);
964 for (i = 0; i < opp->max_irq; i++) {
965 qemu_put_be32s(f, &opp->src[i].ipvp);
966 qemu_put_be32s(f, &opp->src[i].ide);
967 qemu_put_sbe32s(f, &opp->src[i].last_cpu);
968 qemu_put_sbe32s(f, &opp->src[i].pending);
971 qemu_put_sbe32s(f, &opp->nb_cpus);
973 for (i = 0; i < opp->nb_cpus; i++) {
974 qemu_put_be32s(f, &opp->dst[i].pctp);
975 qemu_put_be32s(f, &opp->dst[i].pcsr);
976 openpic_save_IRQ_queue(f, &opp->dst[i].raised);
977 openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
980 for (i = 0; i < MAX_TMR; i++) {
981 qemu_put_be32s(f, &opp->timers[i].ticc);
982 qemu_put_be32s(f, &opp->timers[i].tibc);
985 pci_device_save(&opp->pci_dev, f);
988 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
992 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
993 qemu_get_be32s(f, &q->queue[i]);
995 qemu_get_sbe32s(f, &q->next);
996 qemu_get_sbe32s(f, &q->priority);
999 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1001 openpic_t *opp = (openpic_t *)opaque;
1004 if (version_id != 1)
1007 qemu_get_be32s(f, &opp->glbc);
1008 qemu_get_be32s(f, &opp->veni);
1009 qemu_get_be32s(f, &opp->pint);
1010 qemu_get_be32s(f, &opp->spve);
1011 qemu_get_be32s(f, &opp->tifr);
1013 for (i = 0; i < opp->max_irq; i++) {
1014 qemu_get_be32s(f, &opp->src[i].ipvp);
1015 qemu_get_be32s(f, &opp->src[i].ide);
1016 qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1017 qemu_get_sbe32s(f, &opp->src[i].pending);
1020 qemu_get_sbe32s(f, &opp->nb_cpus);
1022 for (i = 0; i < opp->nb_cpus; i++) {
1023 qemu_get_be32s(f, &opp->dst[i].pctp);
1024 qemu_get_be32s(f, &opp->dst[i].pcsr);
1025 openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1026 openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1029 for (i = 0; i < MAX_TMR; i++) {
1030 qemu_get_be32s(f, &opp->timers[i].ticc);
1031 qemu_get_be32s(f, &opp->timers[i].tibc);
1034 return pci_device_load(&opp->pci_dev, f);
1037 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1039 int n_ci = IDR_CI0 - n_CPU;
1041 if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && test_bit(&src->ide, n_ci)) {
1042 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1044 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1048 qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
1049 qemu_irq **irqs, qemu_irq irq_out)
1055 MemoryRegionOps const *ops;
1059 {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START,
1060 OPENPIC_GLB_REG_SIZE},
1061 {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START,
1062 OPENPIC_TMR_REG_SIZE},
1063 {"src", &openpic_src_ops_le, OPENPIC_SRC_REG_START,
1064 OPENPIC_SRC_REG_SIZE},
1065 {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START,
1066 OPENPIC_CPU_REG_SIZE},
1069 /* XXX: for now, only one CPU is supported */
1072 opp = g_malloc0(sizeof(openpic_t));
1074 memory_region_init(&opp->mem, "openpic", 0x40000);
1076 for (i = 0; i < ARRAY_SIZE(list); i++) {
1078 memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1079 list[i].name, list[i].size);
1081 memory_region_add_subregion(&opp->mem, list[i].start_addr,
1082 &opp->sub_io_mem[i]);
1085 // isu_base &= 0xFFFC0000;
1086 opp->nb_cpus = nb_cpus;
1087 opp->nb_irqs = OPENPIC_EXT_IRQ;
1089 opp->veni = VENI_GENERIC;
1090 opp->spve_mask = 0xFF;
1091 opp->tifr_reset = 0x003F7A00;
1092 opp->max_irq = OPENPIC_MAX_IRQ;
1093 opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1094 opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1096 for (i = 0; i < nb_cpus; i++)
1097 opp->dst[i].irqs = irqs[i];
1098 opp->irq_out = irq_out;
1100 register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1101 openpic_save, openpic_load, opp);
1102 qemu_register_reset(openpic_reset, opp);
1107 return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1110 qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
1111 int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1117 MemoryRegionOps const *ops;
1121 {"glb", &openpic_glb_ops_be, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1122 {"tmr", &openpic_tmr_ops_be, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1123 {"src", &openpic_src_ops_be, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE},
1124 {"cpu", &openpic_cpu_ops_be, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1127 mpp = g_malloc0(sizeof(openpic_t));
1129 memory_region_init(&mpp->mem, "mpic", 0x40000);
1130 memory_region_add_subregion(address_space, base, &mpp->mem);
1132 for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1134 memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1135 list[i].name, list[i].size);
1137 memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1138 &mpp->sub_io_mem[i]);
1141 mpp->nb_cpus = nb_cpus;
1142 /* 12 external sources, 48 internal sources , 4 timer sources,
1143 4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */
1145 mpp->vid = VID_REVISION_1_2;
1146 mpp->veni = VENI_GENERIC;
1147 mpp->spve_mask = 0xFFFF;
1148 mpp->tifr_reset = 0x00000000;
1149 mpp->ipvp_reset = 0x80000000;
1150 mpp->ide_reset = 0x00000001;
1151 mpp->max_irq = MPIC_MAX_IRQ;
1152 mpp->irq_ipi0 = MPIC_IPI_IRQ;
1153 mpp->irq_tim0 = MPIC_TMR_IRQ;
1155 for (i = 0; i < nb_cpus; i++)
1156 mpp->dst[i].irqs = irqs[i];
1157 mpp->irq_out = irq_out;
1159 /* Enable critical interrupt support */
1160 mpp->flags |= OPENPIC_FLAG_IDE_CRIT;
1162 register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1163 qemu_register_reset(openpic_reset, mpp);
1165 return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);