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 */
135 #define IDR_EP_SHIFT 31
136 #define IDR_EP_MASK (1 << IDR_EP_SHIFT)
137 #define IDR_CI0_SHIFT 30
138 #define IDR_CI1_SHIFT 29
139 #define IDR_P1_SHIFT 1
140 #define IDR_P0_SHIFT 0
142 #define BF_WIDTH(_bits_) \
143 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
145 static inline void set_bit (uint32_t *field, int bit)
147 field[bit >> 5] |= 1 << (bit & 0x1F);
150 static inline void reset_bit (uint32_t *field, int bit)
152 field[bit >> 5] &= ~(1 << (bit & 0x1F));
155 static inline int test_bit (uint32_t *field, int bit)
157 return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
160 static int get_current_cpu(void)
162 return cpu_single_env->cpu_index;
165 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
167 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
168 uint32_t val, int idx);
170 typedef struct IRQ_queue_t {
171 uint32_t queue[BF_WIDTH(MAX_IRQ)];
176 typedef struct IRQ_src_t {
177 uint32_t ipvp; /* IRQ vector/priority register */
178 uint32_t ide; /* IRQ destination register */
180 int pending; /* TRUE if IRQ is pending */
183 #define IPVP_MASK_SHIFT 31
184 #define IPVP_MASK_MASK (1 << IPVP_MASK_SHIFT)
185 #define IPVP_ACTIVITY_SHIFT 30
186 #define IPVP_ACTIVITY_MASK (1 << IPVP_ACTIVITY_SHIFT)
187 #define IPVP_MODE_SHIFT 29
188 #define IPVP_MODE_MASK (1 << IPVP_MODE_SHIFT)
189 #define IPVP_POLARITY_SHIFT 23
190 #define IPVP_POLARITY_MASK (1 << IPVP_POLARITY_SHIFT)
191 #define IPVP_SENSE_SHIFT 22
192 #define IPVP_SENSE_MASK (1 << IPVP_SENSE_SHIFT)
194 #define IPVP_PRIORITY_MASK (0x1F << 16)
195 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
196 #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
197 #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
199 typedef struct IRQ_dst_t {
200 uint32_t pctp; /* CPU current task priority */
201 uint32_t pcsr; /* CPU sensitivity register */
203 IRQ_queue_t servicing;
207 typedef struct OpenPICState {
211 /* Behavior control */
215 uint32_t veni; /* Vendor identification register */
222 MemoryRegion sub_io_mem[7];
224 /* Global registers */
225 uint32_t frep; /* Feature reporting register */
226 uint32_t glbc; /* Global configuration register */
227 uint32_t pint; /* Processor initialization register */
228 uint32_t spve; /* Spurious vector register */
229 uint32_t tifr; /* Timer frequency reporting register */
230 /* Source registers */
231 IRQ_src_t src[MAX_IRQ];
232 /* Local registers per output pin */
233 IRQ_dst_t dst[MAX_CPU];
235 /* Timer registers */
237 uint32_t ticc; /* Global timer current count register */
238 uint32_t tibc; /* Global timer base count register */
245 static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
247 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
249 set_bit(q->queue, n_IRQ);
252 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
254 reset_bit(q->queue, n_IRQ);
257 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
259 return test_bit(q->queue, n_IRQ);
262 static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q)
269 for (i = 0; i < opp->max_irq; i++) {
270 if (IRQ_testbit(q, i)) {
271 DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
272 i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
273 if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
275 priority = IPVP_PRIORITY(opp->src[i].ipvp);
280 q->priority = priority;
283 static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
293 static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
299 dst = &opp->dst[n_CPU];
300 src = &opp->src[n_IRQ];
301 priority = IPVP_PRIORITY(src->ipvp);
302 if (priority <= dst->pctp) {
303 /* Too low priority */
304 DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
305 __func__, n_IRQ, n_CPU);
308 if (IRQ_testbit(&dst->raised, n_IRQ)) {
310 DPRINTF("%s: IRQ %d was missed on CPU %d\n",
311 __func__, n_IRQ, n_CPU);
314 src->ipvp |= IPVP_ACTIVITY_MASK;
315 IRQ_setbit(&dst->raised, n_IRQ);
316 if (priority < dst->raised.priority) {
317 /* An higher priority IRQ is already raised */
318 DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
319 __func__, n_IRQ, dst->raised.next, n_CPU);
322 IRQ_get_next(opp, &dst->raised);
323 if (IRQ_get_next(opp, &dst->servicing) != -1 &&
324 priority <= dst->servicing.priority) {
325 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
326 __func__, n_IRQ, dst->servicing.next, n_CPU);
327 /* Already servicing a higher priority IRQ */
330 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
331 openpic_irq_raise(opp, n_CPU, src);
334 /* update pic state because registers for n_IRQ have changed value */
335 static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
340 src = &opp->src[n_IRQ];
344 DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
347 if (src->ipvp & IPVP_MASK_MASK) {
348 /* Interrupt source is disabled */
349 DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
352 if (IPVP_PRIORITY(src->ipvp) == 0) {
353 /* Priority set to zero */
354 DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
357 if (src->ipvp & IPVP_ACTIVITY_MASK) {
358 /* IRQ already active */
359 DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
362 if (src->ide == 0x00000000) {
364 DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
368 if (src->ide == (1 << src->last_cpu)) {
369 /* Only one CPU is allowed to receive this IRQ */
370 IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
371 } else if (!(src->ipvp & IPVP_MODE_MASK)) {
372 /* Directed delivery mode */
373 for (i = 0; i < opp->nb_cpus; i++) {
374 if (src->ide & (1 << i)) {
375 IRQ_local_pipe(opp, i, n_IRQ);
379 /* Distributed delivery mode */
380 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
381 if (i == opp->nb_cpus)
383 if (src->ide & (1 << i)) {
384 IRQ_local_pipe(opp, i, n_IRQ);
392 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
394 OpenPICState *opp = opaque;
397 src = &opp->src[n_IRQ];
398 DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
399 n_IRQ, level, src->ipvp);
400 if (src->ipvp & IPVP_SENSE_MASK) {
401 /* level-sensitive irq */
402 src->pending = level;
404 src->ipvp &= ~IPVP_ACTIVITY_MASK;
407 /* edge-sensitive irq */
411 openpic_update_irq(opp, n_IRQ);
414 static void openpic_reset (void *opaque)
416 OpenPICState *opp = (OpenPICState *)opaque;
419 opp->glbc = 0x80000000;
420 /* Initialise controller registers */
421 opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
422 ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
423 (opp->vid << FREP_VID_SHIFT);
425 opp->pint = 0x00000000;
426 opp->spve = -1 & opp->spve_mask;
427 opp->tifr = opp->tifr_reset;
428 /* Initialise IRQ sources */
429 for (i = 0; i < opp->max_irq; i++) {
430 opp->src[i].ipvp = opp->ipvp_reset;
431 opp->src[i].ide = opp->ide_reset;
433 /* Initialise IRQ destinations */
434 for (i = 0; i < MAX_CPU; i++) {
435 opp->dst[i].pctp = 0x0000000F;
436 opp->dst[i].pcsr = 0x00000000;
437 memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
438 opp->dst[i].raised.next = -1;
439 memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
440 opp->dst[i].servicing.next = -1;
442 /* Initialise timers */
443 for (i = 0; i < MAX_TMR; i++) {
444 opp->timers[i].ticc = 0x00000000;
445 opp->timers[i].tibc = 0x80000000;
447 /* Go out of RESET state */
448 opp->glbc = 0x00000000;
451 static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
453 return opp->src[n_IRQ].ide;
456 static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
458 return opp->src[n_IRQ].ipvp;
461 static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
465 tmp = val & 0xC0000000;
466 tmp |= val & ((1ULL << MAX_CPU) - 1);
467 opp->src[n_IRQ].ide = tmp;
468 DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
471 static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
473 /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
474 /* ACTIVITY bit is read-only */
475 opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
476 | (val & 0x800F00FF);
477 openpic_update_irq(opp, n_IRQ);
478 DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
479 opp->src[n_IRQ].ipvp);
482 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
485 OpenPICState *opp = opaque;
489 DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
493 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
503 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
505 case 0x1000: /* FREP */
507 case 0x1020: /* GLBC */
508 if (val & 0x80000000) {
512 case 0x1080: /* VENI */
514 case 0x1090: /* PINT */
515 for (idx = 0; idx < opp->nb_cpus; idx++) {
516 if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
517 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
518 dst = &opp->dst[idx];
519 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
520 } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
521 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
522 dst = &opp->dst[idx];
523 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
528 case 0x10A0: /* IPI_IPVP */
534 idx = (addr - 0x10A0) >> 4;
535 write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
538 case 0x10E0: /* SPVE */
539 opp->spve = val & opp->spve_mask;
546 static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
548 OpenPICState *opp = opaque;
551 DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
556 case 0x1000: /* FREP */
559 case 0x1020: /* GLBC */
562 case 0x1080: /* VENI */
565 case 0x1090: /* PINT */
568 case 0x00: /* Block Revision Register1 (BRR1) */
577 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
579 case 0x10A0: /* IPI_IPVP */
585 idx = (addr - 0x10A0) >> 4;
586 retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
589 case 0x10E0: /* SPVE */
595 DPRINTF("%s: => %08x\n", __func__, retval);
600 static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
603 OpenPICState *opp = opaque;
606 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
609 idx = (addr >> 6) & 0x3;
617 switch (addr & 0x30) {
618 case 0x00: /* TICC (GTCCR) */
620 case 0x10: /* TIBC (GTBCR) */
621 if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
622 (val & 0x80000000) == 0 &&
623 (opp->timers[idx].tibc & 0x80000000) != 0)
624 opp->timers[idx].ticc &= ~0x80000000;
625 opp->timers[idx].tibc = val;
627 case 0x20: /* TIVP (GTIVPR) */
628 write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
630 case 0x30: /* TIDE (GTIDR) */
631 write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
636 static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
638 OpenPICState *opp = opaque;
639 uint32_t retval = -1;
642 DPRINTF("%s: addr %08x\n", __func__, addr);
646 idx = (addr >> 6) & 0x3;
652 switch (addr & 0x30) {
653 case 0x00: /* TICC (GTCCR) */
654 retval = opp->timers[idx].ticc;
656 case 0x10: /* TIBC (GTBCR) */
657 retval = opp->timers[idx].tibc;
659 case 0x20: /* TIPV (TIPV) */
660 retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
662 case 0x30: /* TIDE (TIDR) */
663 retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
668 DPRINTF("%s: => %08x\n", __func__, retval);
673 static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
676 OpenPICState *opp = opaque;
679 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
682 addr = addr & 0xFFF0;
685 /* EXDE / IFEDE / IEEDE */
686 write_IRQreg_ide(opp, idx, val);
688 /* EXVP / IFEVP / IEEVP */
689 write_IRQreg_ipvp(opp, idx, val);
693 static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
695 OpenPICState *opp = opaque;
699 DPRINTF("%s: addr %08x\n", __func__, addr);
703 addr = addr & 0xFFF0;
706 /* EXDE / IFEDE / IEEDE */
707 retval = read_IRQreg_ide(opp, idx);
709 /* EXVP / IFEVP / IEEVP */
710 retval = read_IRQreg_ipvp(opp, idx);
712 DPRINTF("%s: => %08x\n", __func__, retval);
717 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
718 uint32_t val, int idx)
720 OpenPICState *opp = opaque;
725 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
729 dst = &opp->dst[idx];
732 case 0x40: /* IPIDR */
736 idx = (addr - 0x40) >> 4;
737 /* we use IDE as mask which CPUs to deliver the IPI to still. */
738 write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
739 opp->src[opp->irq_ipi0 + idx].ide | val);
740 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
741 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
743 case 0x80: /* PCTP */
744 dst->pctp = val & 0x0000000F;
746 case 0x90: /* WHOAMI */
747 /* Read-only register */
749 case 0xA0: /* PIAC */
750 /* Read-only register */
752 case 0xB0: /* PEOI */
754 s_IRQ = IRQ_get_next(opp, &dst->servicing);
755 IRQ_resetbit(&dst->servicing, s_IRQ);
756 dst->servicing.next = -1;
757 /* Set up next servicing IRQ */
758 s_IRQ = IRQ_get_next(opp, &dst->servicing);
759 /* Check queued interrupts. */
760 n_IRQ = IRQ_get_next(opp, &dst->raised);
761 src = &opp->src[n_IRQ];
764 IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
765 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
767 openpic_irq_raise(opp, idx, src);
775 static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
778 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
781 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
784 OpenPICState *opp = opaque;
790 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
794 dst = &opp->dst[idx];
797 case 0x00: /* Block Revision Register1 (BRR1) */
798 retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
800 case 0x80: /* PCTP */
803 case 0x90: /* WHOAMI */
806 case 0xA0: /* PIAC */
807 DPRINTF("Lower OpenPIC INT output\n");
808 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
809 n_IRQ = IRQ_get_next(opp, &dst->raised);
810 DPRINTF("PIAC: irq=%d\n", n_IRQ);
812 /* No more interrupt pending */
813 retval = IPVP_VECTOR(opp->spve);
815 src = &opp->src[n_IRQ];
816 if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
817 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
818 /* - Spurious level-sensitive IRQ
819 * - Priorities has been changed
820 * and the pending IRQ isn't allowed anymore
822 src->ipvp &= ~IPVP_ACTIVITY_MASK;
823 retval = IPVP_VECTOR(opp->spve);
825 /* IRQ enter servicing state */
826 IRQ_setbit(&dst->servicing, n_IRQ);
827 retval = IPVP_VECTOR(src->ipvp);
829 IRQ_resetbit(&dst->raised, n_IRQ);
830 dst->raised.next = -1;
831 if (!(src->ipvp & IPVP_SENSE_MASK)) {
832 /* edge-sensitive IRQ */
833 src->ipvp &= ~IPVP_ACTIVITY_MASK;
837 if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
838 src->ide &= ~(1 << idx);
839 if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
840 /* trigger on CPUs that didn't know about it yet */
841 openpic_set_irq(opp, n_IRQ, 1);
842 openpic_set_irq(opp, n_IRQ, 0);
843 /* if all CPUs knew about it, set active bit again */
844 src->ipvp |= IPVP_ACTIVITY_MASK;
849 case 0xB0: /* PEOI */
855 DPRINTF("%s: => %08x\n", __func__, retval);
860 static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
862 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
865 static const MemoryRegionOps openpic_glb_ops_le = {
866 .write = openpic_gbl_write,
867 .read = openpic_gbl_read,
868 .endianness = DEVICE_LITTLE_ENDIAN,
870 .min_access_size = 4,
871 .max_access_size = 4,
875 static const MemoryRegionOps openpic_glb_ops_be = {
876 .write = openpic_gbl_write,
877 .read = openpic_gbl_read,
878 .endianness = DEVICE_BIG_ENDIAN,
880 .min_access_size = 4,
881 .max_access_size = 4,
885 static const MemoryRegionOps openpic_tmr_ops_le = {
886 .write = openpic_tmr_write,
887 .read = openpic_tmr_read,
888 .endianness = DEVICE_LITTLE_ENDIAN,
890 .min_access_size = 4,
891 .max_access_size = 4,
895 static const MemoryRegionOps openpic_tmr_ops_be = {
896 .write = openpic_tmr_write,
897 .read = openpic_tmr_read,
898 .endianness = DEVICE_BIG_ENDIAN,
900 .min_access_size = 4,
901 .max_access_size = 4,
905 static const MemoryRegionOps openpic_cpu_ops_le = {
906 .write = openpic_cpu_write,
907 .read = openpic_cpu_read,
908 .endianness = DEVICE_LITTLE_ENDIAN,
910 .min_access_size = 4,
911 .max_access_size = 4,
915 static const MemoryRegionOps openpic_cpu_ops_be = {
916 .write = openpic_cpu_write,
917 .read = openpic_cpu_read,
918 .endianness = DEVICE_BIG_ENDIAN,
920 .min_access_size = 4,
921 .max_access_size = 4,
925 static const MemoryRegionOps openpic_src_ops_le = {
926 .write = openpic_src_write,
927 .read = openpic_src_read,
928 .endianness = DEVICE_LITTLE_ENDIAN,
930 .min_access_size = 4,
931 .max_access_size = 4,
935 static const MemoryRegionOps openpic_src_ops_be = {
936 .write = openpic_src_write,
937 .read = openpic_src_read,
938 .endianness = DEVICE_BIG_ENDIAN,
940 .min_access_size = 4,
941 .max_access_size = 4,
945 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
949 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
950 qemu_put_be32s(f, &q->queue[i]);
952 qemu_put_sbe32s(f, &q->next);
953 qemu_put_sbe32s(f, &q->priority);
956 static void openpic_save(QEMUFile* f, void *opaque)
958 OpenPICState *opp = (OpenPICState *)opaque;
961 qemu_put_be32s(f, &opp->glbc);
962 qemu_put_be32s(f, &opp->veni);
963 qemu_put_be32s(f, &opp->pint);
964 qemu_put_be32s(f, &opp->spve);
965 qemu_put_be32s(f, &opp->tifr);
967 for (i = 0; i < opp->max_irq; i++) {
968 qemu_put_be32s(f, &opp->src[i].ipvp);
969 qemu_put_be32s(f, &opp->src[i].ide);
970 qemu_put_sbe32s(f, &opp->src[i].last_cpu);
971 qemu_put_sbe32s(f, &opp->src[i].pending);
974 qemu_put_sbe32s(f, &opp->nb_cpus);
976 for (i = 0; i < opp->nb_cpus; i++) {
977 qemu_put_be32s(f, &opp->dst[i].pctp);
978 qemu_put_be32s(f, &opp->dst[i].pcsr);
979 openpic_save_IRQ_queue(f, &opp->dst[i].raised);
980 openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
983 for (i = 0; i < MAX_TMR; i++) {
984 qemu_put_be32s(f, &opp->timers[i].ticc);
985 qemu_put_be32s(f, &opp->timers[i].tibc);
988 pci_device_save(&opp->pci_dev, f);
991 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
995 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
996 qemu_get_be32s(f, &q->queue[i]);
998 qemu_get_sbe32s(f, &q->next);
999 qemu_get_sbe32s(f, &q->priority);
1002 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1004 OpenPICState *opp = (OpenPICState *)opaque;
1007 if (version_id != 1)
1010 qemu_get_be32s(f, &opp->glbc);
1011 qemu_get_be32s(f, &opp->veni);
1012 qemu_get_be32s(f, &opp->pint);
1013 qemu_get_be32s(f, &opp->spve);
1014 qemu_get_be32s(f, &opp->tifr);
1016 for (i = 0; i < opp->max_irq; i++) {
1017 qemu_get_be32s(f, &opp->src[i].ipvp);
1018 qemu_get_be32s(f, &opp->src[i].ide);
1019 qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1020 qemu_get_sbe32s(f, &opp->src[i].pending);
1023 qemu_get_sbe32s(f, &opp->nb_cpus);
1025 for (i = 0; i < opp->nb_cpus; i++) {
1026 qemu_get_be32s(f, &opp->dst[i].pctp);
1027 qemu_get_be32s(f, &opp->dst[i].pcsr);
1028 openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1029 openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1032 for (i = 0; i < MAX_TMR; i++) {
1033 qemu_get_be32s(f, &opp->timers[i].ticc);
1034 qemu_get_be32s(f, &opp->timers[i].tibc);
1037 return pci_device_load(&opp->pci_dev, f);
1040 static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
1042 int n_ci = IDR_CI0_SHIFT - n_CPU;
1044 if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
1045 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1047 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1051 qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
1058 MemoryRegionOps const *ops;
1062 {"glb", &openpic_glb_ops_le, OPENPIC_GLB_REG_START,
1063 OPENPIC_GLB_REG_SIZE},
1064 {"tmr", &openpic_tmr_ops_le, OPENPIC_TMR_REG_START,
1065 OPENPIC_TMR_REG_SIZE},
1066 {"src", &openpic_src_ops_le, OPENPIC_SRC_REG_START,
1067 OPENPIC_SRC_REG_SIZE},
1068 {"cpu", &openpic_cpu_ops_le, OPENPIC_CPU_REG_START,
1069 OPENPIC_CPU_REG_SIZE},
1072 /* XXX: for now, only one CPU is supported */
1075 opp = g_malloc0(sizeof(OpenPICState));
1077 memory_region_init(&opp->mem, "openpic", 0x40000);
1079 for (i = 0; i < ARRAY_SIZE(list); i++) {
1081 memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1082 list[i].name, list[i].size);
1084 memory_region_add_subregion(&opp->mem, list[i].start_addr,
1085 &opp->sub_io_mem[i]);
1088 // isu_base &= 0xFFFC0000;
1089 opp->nb_cpus = nb_cpus;
1090 opp->nb_irqs = OPENPIC_EXT_IRQ;
1092 opp->veni = VENI_GENERIC;
1093 opp->spve_mask = 0xFF;
1094 opp->tifr_reset = 0x003F7A00;
1095 opp->max_irq = OPENPIC_MAX_IRQ;
1096 opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1097 opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1099 for (i = 0; i < nb_cpus; i++)
1100 opp->dst[i].irqs = irqs[i];
1102 register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1103 openpic_save, openpic_load, opp);
1104 qemu_register_reset(openpic_reset, opp);
1109 return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1112 qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
1113 int nb_cpus, qemu_irq **irqs)
1119 MemoryRegionOps const *ops;
1123 {"glb", &openpic_glb_ops_be, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1124 {"tmr", &openpic_tmr_ops_be, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1125 {"src", &openpic_src_ops_be, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE},
1126 {"cpu", &openpic_cpu_ops_be, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1129 mpp = g_malloc0(sizeof(OpenPICState));
1131 memory_region_init(&mpp->mem, "mpic", 0x40000);
1132 memory_region_add_subregion(address_space, base, &mpp->mem);
1134 for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1136 memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1137 list[i].name, list[i].size);
1139 memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1140 &mpp->sub_io_mem[i]);
1143 mpp->nb_cpus = nb_cpus;
1144 /* 12 external sources, 48 internal sources , 4 timer sources,
1145 4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */
1147 mpp->vid = VID_REVISION_1_2;
1148 mpp->veni = VENI_GENERIC;
1149 mpp->spve_mask = 0xFFFF;
1150 mpp->tifr_reset = 0x00000000;
1151 mpp->ipvp_reset = 0x80000000;
1152 mpp->ide_reset = 0x00000001;
1153 mpp->max_irq = MPIC_MAX_IRQ;
1154 mpp->irq_ipi0 = MPIC_IPI_IRQ;
1155 mpp->irq_tim0 = MPIC_TMR_IRQ;
1157 for (i = 0; i < nb_cpus; i++)
1158 mpp->dst[i].irqs = irqs[i];
1160 /* Enable critical interrupt support */
1161 mpp->flags |= OPENPIC_FLAG_IDE_CRIT;
1163 register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1164 qemu_register_reset(openpic_reset, mpp);
1166 return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);