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 openpic_t
{
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 */
240 /* IRQ out is used when in bypass mode (not implemented) */
247 static void openpic_irq_raise(openpic_t
*opp
, int n_CPU
, IRQ_src_t
*src
);
249 static inline void IRQ_setbit (IRQ_queue_t
*q
, int n_IRQ
)
251 set_bit(q
->queue
, n_IRQ
);
254 static inline void IRQ_resetbit (IRQ_queue_t
*q
, int n_IRQ
)
256 reset_bit(q
->queue
, n_IRQ
);
259 static inline int IRQ_testbit (IRQ_queue_t
*q
, int n_IRQ
)
261 return test_bit(q
->queue
, n_IRQ
);
264 static void IRQ_check (openpic_t
*opp
, IRQ_queue_t
*q
)
271 for (i
= 0; i
< opp
->max_irq
; i
++) {
272 if (IRQ_testbit(q
, i
)) {
273 DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
274 i
, IPVP_PRIORITY(opp
->src
[i
].ipvp
), priority
);
275 if (IPVP_PRIORITY(opp
->src
[i
].ipvp
) > priority
) {
277 priority
= IPVP_PRIORITY(opp
->src
[i
].ipvp
);
282 q
->priority
= priority
;
285 static int IRQ_get_next (openpic_t
*opp
, IRQ_queue_t
*q
)
295 static void IRQ_local_pipe (openpic_t
*opp
, int n_CPU
, int n_IRQ
)
301 dst
= &opp
->dst
[n_CPU
];
302 src
= &opp
->src
[n_IRQ
];
303 priority
= IPVP_PRIORITY(src
->ipvp
);
304 if (priority
<= dst
->pctp
) {
305 /* Too low priority */
306 DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
307 __func__
, n_IRQ
, n_CPU
);
310 if (IRQ_testbit(&dst
->raised
, n_IRQ
)) {
312 DPRINTF("%s: IRQ %d was missed on CPU %d\n",
313 __func__
, n_IRQ
, n_CPU
);
316 src
->ipvp
|= IPVP_ACTIVITY_MASK
;
317 IRQ_setbit(&dst
->raised
, n_IRQ
);
318 if (priority
< dst
->raised
.priority
) {
319 /* An higher priority IRQ is already raised */
320 DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
321 __func__
, n_IRQ
, dst
->raised
.next
, n_CPU
);
324 IRQ_get_next(opp
, &dst
->raised
);
325 if (IRQ_get_next(opp
, &dst
->servicing
) != -1 &&
326 priority
<= dst
->servicing
.priority
) {
327 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
328 __func__
, n_IRQ
, dst
->servicing
.next
, n_CPU
);
329 /* Already servicing a higher priority IRQ */
332 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU
, n_IRQ
);
333 openpic_irq_raise(opp
, n_CPU
, src
);
336 /* update pic state because registers for n_IRQ have changed value */
337 static void openpic_update_irq(openpic_t
*opp
, int n_IRQ
)
342 src
= &opp
->src
[n_IRQ
];
346 DPRINTF("%s: IRQ %d is not pending\n", __func__
, n_IRQ
);
349 if (src
->ipvp
& IPVP_MASK_MASK
) {
350 /* Interrupt source is disabled */
351 DPRINTF("%s: IRQ %d is disabled\n", __func__
, n_IRQ
);
354 if (IPVP_PRIORITY(src
->ipvp
) == 0) {
355 /* Priority set to zero */
356 DPRINTF("%s: IRQ %d has 0 priority\n", __func__
, n_IRQ
);
359 if (src
->ipvp
& IPVP_ACTIVITY_MASK
) {
360 /* IRQ already active */
361 DPRINTF("%s: IRQ %d is already active\n", __func__
, n_IRQ
);
364 if (src
->ide
== 0x00000000) {
366 DPRINTF("%s: IRQ %d has no target\n", __func__
, n_IRQ
);
370 if (src
->ide
== (1 << src
->last_cpu
)) {
371 /* Only one CPU is allowed to receive this IRQ */
372 IRQ_local_pipe(opp
, src
->last_cpu
, n_IRQ
);
373 } else if (!(src
->ipvp
& IPVP_MODE_MASK
)) {
374 /* Directed delivery mode */
375 for (i
= 0; i
< opp
->nb_cpus
; i
++) {
376 if (src
->ide
& (1 << i
)) {
377 IRQ_local_pipe(opp
, i
, n_IRQ
);
381 /* Distributed delivery mode */
382 for (i
= src
->last_cpu
+ 1; i
!= src
->last_cpu
; i
++) {
383 if (i
== opp
->nb_cpus
)
385 if (src
->ide
& (1 << i
)) {
386 IRQ_local_pipe(opp
, i
, n_IRQ
);
394 static void openpic_set_irq(void *opaque
, int n_IRQ
, int level
)
396 openpic_t
*opp
= opaque
;
399 src
= &opp
->src
[n_IRQ
];
400 DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
401 n_IRQ
, level
, src
->ipvp
);
402 if (src
->ipvp
& IPVP_SENSE_MASK
) {
403 /* level-sensitive irq */
404 src
->pending
= level
;
406 src
->ipvp
&= ~IPVP_ACTIVITY_MASK
;
409 /* edge-sensitive irq */
413 openpic_update_irq(opp
, n_IRQ
);
416 static void openpic_reset (void *opaque
)
418 openpic_t
*opp
= (openpic_t
*)opaque
;
421 opp
->glbc
= 0x80000000;
422 /* Initialise controller registers */
423 opp
->frep
= ((opp
->nb_irqs
-1) << FREP_NIRQ_SHIFT
) |
424 ((opp
->nb_cpus
-1) << FREP_NCPU_SHIFT
) |
425 (opp
->vid
<< FREP_VID_SHIFT
);
427 opp
->pint
= 0x00000000;
428 opp
->spve
= -1 & opp
->spve_mask
;
429 opp
->tifr
= opp
->tifr_reset
;
430 /* Initialise IRQ sources */
431 for (i
= 0; i
< opp
->max_irq
; i
++) {
432 opp
->src
[i
].ipvp
= opp
->ipvp_reset
;
433 opp
->src
[i
].ide
= opp
->ide_reset
;
435 /* Initialise IRQ destinations */
436 for (i
= 0; i
< MAX_CPU
; i
++) {
437 opp
->dst
[i
].pctp
= 0x0000000F;
438 opp
->dst
[i
].pcsr
= 0x00000000;
439 memset(&opp
->dst
[i
].raised
, 0, sizeof(IRQ_queue_t
));
440 opp
->dst
[i
].raised
.next
= -1;
441 memset(&opp
->dst
[i
].servicing
, 0, sizeof(IRQ_queue_t
));
442 opp
->dst
[i
].servicing
.next
= -1;
444 /* Initialise timers */
445 for (i
= 0; i
< MAX_TMR
; i
++) {
446 opp
->timers
[i
].ticc
= 0x00000000;
447 opp
->timers
[i
].tibc
= 0x80000000;
449 /* Go out of RESET state */
450 opp
->glbc
= 0x00000000;
453 static inline uint32_t read_IRQreg_ide(openpic_t
*opp
, int n_IRQ
)
455 return opp
->src
[n_IRQ
].ide
;
458 static inline uint32_t read_IRQreg_ipvp(openpic_t
*opp
, int n_IRQ
)
460 return opp
->src
[n_IRQ
].ipvp
;
463 static inline void write_IRQreg_ide(openpic_t
*opp
, int n_IRQ
, uint32_t val
)
467 tmp
= val
& 0xC0000000;
468 tmp
|= val
& ((1ULL << MAX_CPU
) - 1);
469 opp
->src
[n_IRQ
].ide
= tmp
;
470 DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ
, opp
->src
[n_IRQ
].ide
);
473 static inline void write_IRQreg_ipvp(openpic_t
*opp
, int n_IRQ
, uint32_t val
)
475 /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
476 /* ACTIVITY bit is read-only */
477 opp
->src
[n_IRQ
].ipvp
= (opp
->src
[n_IRQ
].ipvp
& 0x40000000)
478 | (val
& 0x800F00FF);
479 openpic_update_irq(opp
, n_IRQ
);
480 DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ
, val
,
481 opp
->src
[n_IRQ
].ipvp
);
484 static void openpic_gbl_write(void *opaque
, hwaddr addr
, uint64_t val
,
487 openpic_t
*opp
= opaque
;
491 DPRINTF("%s: addr " TARGET_FMT_plx
" <= %08x\n", __func__
, addr
, val
);
495 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
505 openpic_cpu_write_internal(opp
, addr
, val
, get_current_cpu());
507 case 0x1000: /* FREP */
509 case 0x1020: /* GLBC */
510 if (val
& 0x80000000) {
514 case 0x1080: /* VENI */
516 case 0x1090: /* PINT */
517 for (idx
= 0; idx
< opp
->nb_cpus
; idx
++) {
518 if ((val
& (1 << idx
)) && !(opp
->pint
& (1 << idx
))) {
519 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx
);
520 dst
= &opp
->dst
[idx
];
521 qemu_irq_raise(dst
->irqs
[OPENPIC_OUTPUT_RESET
]);
522 } else if (!(val
& (1 << idx
)) && (opp
->pint
& (1 << idx
))) {
523 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx
);
524 dst
= &opp
->dst
[idx
];
525 qemu_irq_lower(dst
->irqs
[OPENPIC_OUTPUT_RESET
]);
530 case 0x10A0: /* IPI_IPVP */
536 idx
= (addr
- 0x10A0) >> 4;
537 write_IRQreg_ipvp(opp
, opp
->irq_ipi0
+ idx
, val
);
540 case 0x10E0: /* SPVE */
541 opp
->spve
= val
& opp
->spve_mask
;
548 static uint64_t openpic_gbl_read(void *opaque
, hwaddr addr
, unsigned len
)
550 openpic_t
*opp
= opaque
;
553 DPRINTF("%s: addr " TARGET_FMT_plx
"\n", __func__
, addr
);
558 case 0x1000: /* FREP */
561 case 0x1020: /* GLBC */
564 case 0x1080: /* VENI */
567 case 0x1090: /* PINT */
570 case 0x00: /* Block Revision Register1 (BRR1) */
579 retval
= openpic_cpu_read_internal(opp
, addr
, get_current_cpu());
581 case 0x10A0: /* IPI_IPVP */
587 idx
= (addr
- 0x10A0) >> 4;
588 retval
= read_IRQreg_ipvp(opp
, opp
->irq_ipi0
+ idx
);
591 case 0x10E0: /* SPVE */
597 DPRINTF("%s: => %08x\n", __func__
, retval
);
602 static void openpic_timer_write(void *opaque
, hwaddr addr
, uint64_t val
,
605 openpic_t
*opp
= opaque
;
608 DPRINTF("%s: addr %08x <= %08x\n", __func__
, addr
, val
);
611 idx
= (addr
>> 6) & 0x3;
619 switch (addr
& 0x30) {
620 case 0x00: /* TICC (GTCCR) */
622 case 0x10: /* TIBC (GTBCR) */
623 if ((opp
->timers
[idx
].ticc
& 0x80000000) != 0 &&
624 (val
& 0x80000000) == 0 &&
625 (opp
->timers
[idx
].tibc
& 0x80000000) != 0)
626 opp
->timers
[idx
].ticc
&= ~0x80000000;
627 opp
->timers
[idx
].tibc
= val
;
629 case 0x20: /* TIVP (GTIVPR) */
630 write_IRQreg_ipvp(opp
, opp
->irq_tim0
+ idx
, val
);
632 case 0x30: /* TIDE (GTIDR) */
633 write_IRQreg_ide(opp
, opp
->irq_tim0
+ idx
, val
);
638 static uint64_t openpic_timer_read(void *opaque
, hwaddr addr
, unsigned len
)
640 openpic_t
*opp
= opaque
;
641 uint32_t retval
= -1;
644 DPRINTF("%s: addr %08x\n", __func__
, addr
);
648 idx
= (addr
>> 6) & 0x3;
654 switch (addr
& 0x30) {
655 case 0x00: /* TICC (GTCCR) */
656 retval
= opp
->timers
[idx
].ticc
;
658 case 0x10: /* TIBC (GTBCR) */
659 retval
= opp
->timers
[idx
].tibc
;
661 case 0x20: /* TIPV (TIPV) */
662 retval
= read_IRQreg_ipvp(opp
, opp
->irq_tim0
+ idx
);
664 case 0x30: /* TIDE (TIDR) */
665 retval
= read_IRQreg_ide(opp
, opp
->irq_tim0
+ idx
);
670 DPRINTF("%s: => %08x\n", __func__
, retval
);
675 static void openpic_src_write(void *opaque
, hwaddr addr
, uint64_t val
,
678 openpic_t
*opp
= opaque
;
681 DPRINTF("%s: addr %08x <= %08x\n", __func__
, addr
, val
);
684 addr
= addr
& 0xFFF0;
687 /* EXDE / IFEDE / IEEDE */
688 write_IRQreg_ide(opp
, idx
, val
);
690 /* EXVP / IFEVP / IEEVP */
691 write_IRQreg_ipvp(opp
, idx
, val
);
695 static uint64_t openpic_src_read(void *opaque
, uint64_t addr
, unsigned len
)
697 openpic_t
*opp
= opaque
;
701 DPRINTF("%s: addr %08x\n", __func__
, addr
);
705 addr
= addr
& 0xFFF0;
708 /* EXDE / IFEDE / IEEDE */
709 retval
= read_IRQreg_ide(opp
, idx
);
711 /* EXVP / IFEVP / IEEVP */
712 retval
= read_IRQreg_ipvp(opp
, idx
);
714 DPRINTF("%s: => %08x\n", __func__
, retval
);
719 static void openpic_cpu_write_internal(void *opaque
, hwaddr addr
,
720 uint32_t val
, int idx
)
722 openpic_t
*opp
= opaque
;
727 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx
" <= %08x\n", __func__
, idx
,
731 dst
= &opp
->dst
[idx
];
734 case 0x40: /* IPIDR */
738 idx
= (addr
- 0x40) >> 4;
739 /* we use IDE as mask which CPUs to deliver the IPI to still. */
740 write_IRQreg_ide(opp
, opp
->irq_ipi0
+ idx
,
741 opp
->src
[opp
->irq_ipi0
+ idx
].ide
| val
);
742 openpic_set_irq(opp
, opp
->irq_ipi0
+ idx
, 1);
743 openpic_set_irq(opp
, opp
->irq_ipi0
+ idx
, 0);
745 case 0x80: /* PCTP */
746 dst
->pctp
= val
& 0x0000000F;
748 case 0x90: /* WHOAMI */
749 /* Read-only register */
751 case 0xA0: /* PIAC */
752 /* Read-only register */
754 case 0xB0: /* PEOI */
756 s_IRQ
= IRQ_get_next(opp
, &dst
->servicing
);
757 IRQ_resetbit(&dst
->servicing
, s_IRQ
);
758 dst
->servicing
.next
= -1;
759 /* Set up next servicing IRQ */
760 s_IRQ
= IRQ_get_next(opp
, &dst
->servicing
);
761 /* Check queued interrupts. */
762 n_IRQ
= IRQ_get_next(opp
, &dst
->raised
);
763 src
= &opp
->src
[n_IRQ
];
766 IPVP_PRIORITY(src
->ipvp
) > dst
->servicing
.priority
)) {
767 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
769 openpic_irq_raise(opp
, idx
, src
);
777 static void openpic_cpu_write(void *opaque
, hwaddr addr
, uint64_t val
,
780 openpic_cpu_write_internal(opaque
, addr
, val
, (addr
& 0x1f000) >> 12);
783 static uint32_t openpic_cpu_read_internal(void *opaque
, hwaddr addr
,
786 openpic_t
*opp
= opaque
;
792 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx
"\n", __func__
, idx
, addr
);
796 dst
= &opp
->dst
[idx
];
799 case 0x00: /* Block Revision Register1 (BRR1) */
800 retval
= FSL_BRR1_IPID
| FSL_BRR1_IPMJ
| FSL_BRR1_IPMN
;
802 case 0x80: /* PCTP */
805 case 0x90: /* WHOAMI */
808 case 0xA0: /* PIAC */
809 DPRINTF("Lower OpenPIC INT output\n");
810 qemu_irq_lower(dst
->irqs
[OPENPIC_OUTPUT_INT
]);
811 n_IRQ
= IRQ_get_next(opp
, &dst
->raised
);
812 DPRINTF("PIAC: irq=%d\n", n_IRQ
);
814 /* No more interrupt pending */
815 retval
= IPVP_VECTOR(opp
->spve
);
817 src
= &opp
->src
[n_IRQ
];
818 if (!(src
->ipvp
& IPVP_ACTIVITY_MASK
) ||
819 !(IPVP_PRIORITY(src
->ipvp
) > dst
->pctp
)) {
820 /* - Spurious level-sensitive IRQ
821 * - Priorities has been changed
822 * and the pending IRQ isn't allowed anymore
824 src
->ipvp
&= ~IPVP_ACTIVITY_MASK
;
825 retval
= IPVP_VECTOR(opp
->spve
);
827 /* IRQ enter servicing state */
828 IRQ_setbit(&dst
->servicing
, n_IRQ
);
829 retval
= IPVP_VECTOR(src
->ipvp
);
831 IRQ_resetbit(&dst
->raised
, n_IRQ
);
832 dst
->raised
.next
= -1;
833 if (!(src
->ipvp
& IPVP_SENSE_MASK
)) {
834 /* edge-sensitive IRQ */
835 src
->ipvp
&= ~IPVP_ACTIVITY_MASK
;
839 if ((n_IRQ
>= opp
->irq_ipi0
) && (n_IRQ
< (opp
->irq_ipi0
+ MAX_IPI
))) {
840 src
->ide
&= ~(1 << idx
);
841 if (src
->ide
&& !(src
->ipvp
& IPVP_SENSE_MASK
)) {
842 /* trigger on CPUs that didn't know about it yet */
843 openpic_set_irq(opp
, n_IRQ
, 1);
844 openpic_set_irq(opp
, n_IRQ
, 0);
845 /* if all CPUs knew about it, set active bit again */
846 src
->ipvp
|= IPVP_ACTIVITY_MASK
;
851 case 0xB0: /* PEOI */
857 DPRINTF("%s: => %08x\n", __func__
, retval
);
862 static uint64_t openpic_cpu_read(void *opaque
, hwaddr addr
, unsigned len
)
864 return openpic_cpu_read_internal(opaque
, addr
, (addr
& 0x1f000) >> 12);
867 static const MemoryRegionOps openpic_glb_ops_le
= {
868 .write
= openpic_gbl_write
,
869 .read
= openpic_gbl_read
,
870 .endianness
= DEVICE_LITTLE_ENDIAN
,
872 .min_access_size
= 4,
873 .max_access_size
= 4,
877 static const MemoryRegionOps openpic_glb_ops_be
= {
878 .write
= openpic_gbl_write
,
879 .read
= openpic_gbl_read
,
880 .endianness
= DEVICE_BIG_ENDIAN
,
882 .min_access_size
= 4,
883 .max_access_size
= 4,
887 static const MemoryRegionOps openpic_tmr_ops_le
= {
888 .write
= openpic_timer_write
,
889 .read
= openpic_timer_read
,
890 .endianness
= DEVICE_LITTLE_ENDIAN
,
892 .min_access_size
= 4,
893 .max_access_size
= 4,
897 static const MemoryRegionOps openpic_tmr_ops_be
= {
898 .write
= openpic_timer_write
,
899 .read
= openpic_timer_read
,
900 .endianness
= DEVICE_BIG_ENDIAN
,
902 .min_access_size
= 4,
903 .max_access_size
= 4,
907 static const MemoryRegionOps openpic_cpu_ops_le
= {
908 .write
= openpic_cpu_write
,
909 .read
= openpic_cpu_read
,
910 .endianness
= DEVICE_LITTLE_ENDIAN
,
912 .min_access_size
= 4,
913 .max_access_size
= 4,
917 static const MemoryRegionOps openpic_cpu_ops_be
= {
918 .write
= openpic_cpu_write
,
919 .read
= openpic_cpu_read
,
920 .endianness
= DEVICE_BIG_ENDIAN
,
922 .min_access_size
= 4,
923 .max_access_size
= 4,
927 static const MemoryRegionOps openpic_src_ops_le
= {
928 .write
= openpic_src_write
,
929 .read
= openpic_src_read
,
930 .endianness
= DEVICE_LITTLE_ENDIAN
,
932 .min_access_size
= 4,
933 .max_access_size
= 4,
937 static const MemoryRegionOps openpic_src_ops_be
= {
938 .write
= openpic_src_write
,
939 .read
= openpic_src_read
,
940 .endianness
= DEVICE_BIG_ENDIAN
,
942 .min_access_size
= 4,
943 .max_access_size
= 4,
947 static void openpic_save_IRQ_queue(QEMUFile
* f
, IRQ_queue_t
*q
)
951 for (i
= 0; i
< BF_WIDTH(MAX_IRQ
); i
++)
952 qemu_put_be32s(f
, &q
->queue
[i
]);
954 qemu_put_sbe32s(f
, &q
->next
);
955 qemu_put_sbe32s(f
, &q
->priority
);
958 static void openpic_save(QEMUFile
* f
, void *opaque
)
960 openpic_t
*opp
= (openpic_t
*)opaque
;
963 qemu_put_be32s(f
, &opp
->glbc
);
964 qemu_put_be32s(f
, &opp
->veni
);
965 qemu_put_be32s(f
, &opp
->pint
);
966 qemu_put_be32s(f
, &opp
->spve
);
967 qemu_put_be32s(f
, &opp
->tifr
);
969 for (i
= 0; i
< opp
->max_irq
; i
++) {
970 qemu_put_be32s(f
, &opp
->src
[i
].ipvp
);
971 qemu_put_be32s(f
, &opp
->src
[i
].ide
);
972 qemu_put_sbe32s(f
, &opp
->src
[i
].last_cpu
);
973 qemu_put_sbe32s(f
, &opp
->src
[i
].pending
);
976 qemu_put_sbe32s(f
, &opp
->nb_cpus
);
978 for (i
= 0; i
< opp
->nb_cpus
; i
++) {
979 qemu_put_be32s(f
, &opp
->dst
[i
].pctp
);
980 qemu_put_be32s(f
, &opp
->dst
[i
].pcsr
);
981 openpic_save_IRQ_queue(f
, &opp
->dst
[i
].raised
);
982 openpic_save_IRQ_queue(f
, &opp
->dst
[i
].servicing
);
985 for (i
= 0; i
< MAX_TMR
; i
++) {
986 qemu_put_be32s(f
, &opp
->timers
[i
].ticc
);
987 qemu_put_be32s(f
, &opp
->timers
[i
].tibc
);
990 pci_device_save(&opp
->pci_dev
, f
);
993 static void openpic_load_IRQ_queue(QEMUFile
* f
, IRQ_queue_t
*q
)
997 for (i
= 0; i
< BF_WIDTH(MAX_IRQ
); i
++)
998 qemu_get_be32s(f
, &q
->queue
[i
]);
1000 qemu_get_sbe32s(f
, &q
->next
);
1001 qemu_get_sbe32s(f
, &q
->priority
);
1004 static int openpic_load(QEMUFile
* f
, void *opaque
, int version_id
)
1006 openpic_t
*opp
= (openpic_t
*)opaque
;
1009 if (version_id
!= 1)
1012 qemu_get_be32s(f
, &opp
->glbc
);
1013 qemu_get_be32s(f
, &opp
->veni
);
1014 qemu_get_be32s(f
, &opp
->pint
);
1015 qemu_get_be32s(f
, &opp
->spve
);
1016 qemu_get_be32s(f
, &opp
->tifr
);
1018 for (i
= 0; i
< opp
->max_irq
; i
++) {
1019 qemu_get_be32s(f
, &opp
->src
[i
].ipvp
);
1020 qemu_get_be32s(f
, &opp
->src
[i
].ide
);
1021 qemu_get_sbe32s(f
, &opp
->src
[i
].last_cpu
);
1022 qemu_get_sbe32s(f
, &opp
->src
[i
].pending
);
1025 qemu_get_sbe32s(f
, &opp
->nb_cpus
);
1027 for (i
= 0; i
< opp
->nb_cpus
; i
++) {
1028 qemu_get_be32s(f
, &opp
->dst
[i
].pctp
);
1029 qemu_get_be32s(f
, &opp
->dst
[i
].pcsr
);
1030 openpic_load_IRQ_queue(f
, &opp
->dst
[i
].raised
);
1031 openpic_load_IRQ_queue(f
, &opp
->dst
[i
].servicing
);
1034 for (i
= 0; i
< MAX_TMR
; i
++) {
1035 qemu_get_be32s(f
, &opp
->timers
[i
].ticc
);
1036 qemu_get_be32s(f
, &opp
->timers
[i
].tibc
);
1039 return pci_device_load(&opp
->pci_dev
, f
);
1042 static void openpic_irq_raise(openpic_t
*opp
, int n_CPU
, IRQ_src_t
*src
)
1044 int n_ci
= IDR_CI0_SHIFT
- n_CPU
;
1046 if ((opp
->flags
& OPENPIC_FLAG_IDE_CRIT
) && (src
->ide
& (1 << n_ci
))) {
1047 qemu_irq_raise(opp
->dst
[n_CPU
].irqs
[OPENPIC_OUTPUT_CINT
]);
1049 qemu_irq_raise(opp
->dst
[n_CPU
].irqs
[OPENPIC_OUTPUT_INT
]);
1053 qemu_irq
*openpic_init (MemoryRegion
**pmem
, int nb_cpus
,
1054 qemu_irq
**irqs
, qemu_irq irq_out
)
1060 MemoryRegionOps
const *ops
;
1064 {"glb", &openpic_glb_ops_le
, OPENPIC_GLB_REG_START
,
1065 OPENPIC_GLB_REG_SIZE
},
1066 {"tmr", &openpic_tmr_ops_le
, OPENPIC_TMR_REG_START
,
1067 OPENPIC_TMR_REG_SIZE
},
1068 {"src", &openpic_src_ops_le
, OPENPIC_SRC_REG_START
,
1069 OPENPIC_SRC_REG_SIZE
},
1070 {"cpu", &openpic_cpu_ops_le
, OPENPIC_CPU_REG_START
,
1071 OPENPIC_CPU_REG_SIZE
},
1074 /* XXX: for now, only one CPU is supported */
1077 opp
= g_malloc0(sizeof(openpic_t
));
1079 memory_region_init(&opp
->mem
, "openpic", 0x40000);
1081 for (i
= 0; i
< ARRAY_SIZE(list
); i
++) {
1083 memory_region_init_io(&opp
->sub_io_mem
[i
], list
[i
].ops
, opp
,
1084 list
[i
].name
, list
[i
].size
);
1086 memory_region_add_subregion(&opp
->mem
, list
[i
].start_addr
,
1087 &opp
->sub_io_mem
[i
]);
1090 // isu_base &= 0xFFFC0000;
1091 opp
->nb_cpus
= nb_cpus
;
1092 opp
->nb_irqs
= OPENPIC_EXT_IRQ
;
1094 opp
->veni
= VENI_GENERIC
;
1095 opp
->spve_mask
= 0xFF;
1096 opp
->tifr_reset
= 0x003F7A00;
1097 opp
->max_irq
= OPENPIC_MAX_IRQ
;
1098 opp
->irq_ipi0
= OPENPIC_IRQ_IPI0
;
1099 opp
->irq_tim0
= OPENPIC_IRQ_TIM0
;
1101 for (i
= 0; i
< nb_cpus
; i
++)
1102 opp
->dst
[i
].irqs
= irqs
[i
];
1103 opp
->irq_out
= irq_out
;
1105 register_savevm(&opp
->pci_dev
.qdev
, "openpic", 0, 2,
1106 openpic_save
, openpic_load
, opp
);
1107 qemu_register_reset(openpic_reset
, opp
);
1112 return qemu_allocate_irqs(openpic_set_irq
, opp
, opp
->max_irq
);
1115 qemu_irq
*mpic_init (MemoryRegion
*address_space
, hwaddr base
,
1116 int nb_cpus
, qemu_irq
**irqs
, qemu_irq irq_out
)
1122 MemoryRegionOps
const *ops
;
1126 {"glb", &openpic_glb_ops_be
, MPIC_GLB_REG_START
, MPIC_GLB_REG_SIZE
},
1127 {"tmr", &openpic_tmr_ops_be
, MPIC_TMR_REG_START
, MPIC_TMR_REG_SIZE
},
1128 {"src", &openpic_src_ops_be
, MPIC_SRC_REG_START
, MPIC_SRC_REG_SIZE
},
1129 {"cpu", &openpic_cpu_ops_be
, MPIC_CPU_REG_START
, MPIC_CPU_REG_SIZE
},
1132 mpp
= g_malloc0(sizeof(openpic_t
));
1134 memory_region_init(&mpp
->mem
, "mpic", 0x40000);
1135 memory_region_add_subregion(address_space
, base
, &mpp
->mem
);
1137 for (i
= 0; i
< sizeof(list
)/sizeof(list
[0]); i
++) {
1139 memory_region_init_io(&mpp
->sub_io_mem
[i
], list
[i
].ops
, mpp
,
1140 list
[i
].name
, list
[i
].size
);
1142 memory_region_add_subregion(&mpp
->mem
, list
[i
].start_addr
,
1143 &mpp
->sub_io_mem
[i
]);
1146 mpp
->nb_cpus
= nb_cpus
;
1147 /* 12 external sources, 48 internal sources , 4 timer sources,
1148 4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */
1150 mpp
->vid
= VID_REVISION_1_2
;
1151 mpp
->veni
= VENI_GENERIC
;
1152 mpp
->spve_mask
= 0xFFFF;
1153 mpp
->tifr_reset
= 0x00000000;
1154 mpp
->ipvp_reset
= 0x80000000;
1155 mpp
->ide_reset
= 0x00000001;
1156 mpp
->max_irq
= MPIC_MAX_IRQ
;
1157 mpp
->irq_ipi0
= MPIC_IPI_IRQ
;
1158 mpp
->irq_tim0
= MPIC_TMR_IRQ
;
1160 for (i
= 0; i
< nb_cpus
; i
++)
1161 mpp
->dst
[i
].irqs
= irqs
[i
];
1162 mpp
->irq_out
= irq_out
;
1164 /* Enable critical interrupt support */
1165 mpp
->flags
|= OPENPIC_FLAG_IDE_CRIT
;
1167 register_savevm(NULL
, "mpic", 0, 2, openpic_save
, openpic_load
, mpp
);
1168 qemu_register_reset(openpic_reset
, mpp
);
1170 return qemu_allocate_irqs(openpic_set_irq
, mpp
, mpp
->max_irq
);