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 */
56 #define VENI 0x00000000 /* Vendor ID */
64 #define OPENPIC_MAX_CPU 2
65 #define OPENPIC_MAX_IRQ 64
66 #define OPENPIC_EXT_IRQ 48
67 #define OPENPIC_MAX_TMR MAX_TMR
68 #define OPENPIC_MAX_IPI MAX_IPI
70 /* Interrupt definitions */
71 #define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
72 #define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
73 #define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
74 #if OPENPIC_MAX_IPI > 0
75 #define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
76 #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
78 #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
79 #define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
82 #define OPENPIC_GLB_REG_START 0x0
83 #define OPENPIC_GLB_REG_SIZE 0x10F0
84 #define OPENPIC_TMR_REG_START 0x10F0
85 #define OPENPIC_TMR_REG_SIZE 0x220
86 #define OPENPIC_SRC_REG_START 0x10000
87 #define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
88 #define OPENPIC_CPU_REG_START 0x20000
89 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
92 #define MPIC_MAX_CPU 1
93 #define MPIC_MAX_EXT 12
94 #define MPIC_MAX_INT 64
95 #define MPIC_MAX_IRQ MAX_IRQ
97 /* Interrupt definitions */
98 /* IRQs, accessible through the IRQ region */
99 #define MPIC_EXT_IRQ 0x00
100 #define MPIC_INT_IRQ 0x10
101 #define MPIC_MSG_IRQ 0xb0
102 #define MPIC_MSI_IRQ 0xe0
103 /* These are available through separate regions, but
104 for simplicity's sake mapped into the same number space */
105 #define MPIC_TMR_IRQ 0x100
106 #define MPIC_IPI_IRQ 0x104
108 #define MPIC_GLB_REG_START 0x0
109 #define MPIC_GLB_REG_SIZE 0x10F0
110 #define MPIC_TMR_REG_START 0x10F0
111 #define MPIC_TMR_REG_SIZE 0x220
112 #define MPIC_SRC_REG_START 0x10000
113 #define MPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
114 #define MPIC_CPU_REG_START 0x20000
115 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
118 * Block Revision Register1 (BRR1): QEMU does not fully emulate
119 * any version on MPIC. So to start with, set the IP version to 0.
121 * NOTE: This is Freescale MPIC specific register. Keep it here till
122 * this code is refactored for different variants of OPENPIC and MPIC.
124 #define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
125 #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
126 #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
136 #define BF_WIDTH(_bits_) \
137 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
139 static inline void set_bit (uint32_t *field
, int bit
)
141 field
[bit
>> 5] |= 1 << (bit
& 0x1F);
144 static inline void reset_bit (uint32_t *field
, int bit
)
146 field
[bit
>> 5] &= ~(1 << (bit
& 0x1F));
149 static inline int test_bit (uint32_t *field
, int bit
)
151 return (field
[bit
>> 5] & 1 << (bit
& 0x1F)) != 0;
154 static int get_current_cpu(void)
156 return cpu_single_env
->cpu_index
;
159 static uint32_t openpic_cpu_read_internal(void *opaque
, hwaddr addr
,
161 static void openpic_cpu_write_internal(void *opaque
, hwaddr addr
,
162 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 */
182 int pending
; /* TRUE if IRQ is pending */
192 #define IPVP_PRIORITY_MASK (0x1F << 16)
193 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
194 #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
195 #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
197 typedef struct IRQ_dst_t
{
199 uint32_t pctp
; /* CPU current task priority */
200 uint32_t pcsr
; /* CPU sensitivity register */
202 IRQ_queue_t servicing
;
206 typedef struct openpic_t
{
211 MemoryRegion sub_io_mem
[7];
213 /* Global registers */
214 uint32_t frep
; /* Feature reporting register */
215 uint32_t glbc
; /* Global configuration register */
216 uint32_t micr
; /* MPIC interrupt configuration register */
217 uint32_t veni
; /* Vendor identification register */
218 uint32_t pint
; /* Processor initialization register */
219 uint32_t spve
; /* Spurious vector register */
220 uint32_t tifr
; /* Timer frequency reporting register */
221 /* Source registers */
222 IRQ_src_t src
[MAX_IRQ
];
223 /* Local registers per output pin */
224 IRQ_dst_t dst
[MAX_CPU
];
226 /* Timer registers */
228 uint32_t ticc
; /* Global timer current count register */
229 uint32_t tibc
; /* Global timer base count register */
231 /* IRQ out is used when in bypass mode (not implemented) */
236 void (*reset
) (void *);
237 void (*irq_raise
) (struct openpic_t
*, int, IRQ_src_t
*);
240 static inline void IRQ_setbit (IRQ_queue_t
*q
, int n_IRQ
)
242 set_bit(q
->queue
, n_IRQ
);
245 static inline void IRQ_resetbit (IRQ_queue_t
*q
, int n_IRQ
)
247 reset_bit(q
->queue
, n_IRQ
);
250 static inline int IRQ_testbit (IRQ_queue_t
*q
, int n_IRQ
)
252 return test_bit(q
->queue
, n_IRQ
);
255 static void IRQ_check (openpic_t
*opp
, IRQ_queue_t
*q
)
262 for (i
= 0; i
< opp
->max_irq
; i
++) {
263 if (IRQ_testbit(q
, i
)) {
264 DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
265 i
, IPVP_PRIORITY(opp
->src
[i
].ipvp
), priority
);
266 if (IPVP_PRIORITY(opp
->src
[i
].ipvp
) > priority
) {
268 priority
= IPVP_PRIORITY(opp
->src
[i
].ipvp
);
273 q
->priority
= priority
;
276 static int IRQ_get_next (openpic_t
*opp
, IRQ_queue_t
*q
)
286 static void IRQ_local_pipe (openpic_t
*opp
, int n_CPU
, int n_IRQ
)
292 dst
= &opp
->dst
[n_CPU
];
293 src
= &opp
->src
[n_IRQ
];
294 priority
= IPVP_PRIORITY(src
->ipvp
);
295 if (priority
<= dst
->pctp
) {
296 /* Too low priority */
297 DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
298 __func__
, n_IRQ
, n_CPU
);
301 if (IRQ_testbit(&dst
->raised
, n_IRQ
)) {
303 DPRINTF("%s: IRQ %d was missed on CPU %d\n",
304 __func__
, n_IRQ
, n_CPU
);
307 set_bit(&src
->ipvp
, IPVP_ACTIVITY
);
308 IRQ_setbit(&dst
->raised
, n_IRQ
);
309 if (priority
< dst
->raised
.priority
) {
310 /* An higher priority IRQ is already raised */
311 DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
312 __func__
, n_IRQ
, dst
->raised
.next
, n_CPU
);
315 IRQ_get_next(opp
, &dst
->raised
);
316 if (IRQ_get_next(opp
, &dst
->servicing
) != -1 &&
317 priority
<= dst
->servicing
.priority
) {
318 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
319 __func__
, n_IRQ
, dst
->servicing
.next
, n_CPU
);
320 /* Already servicing a higher priority IRQ */
323 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU
, n_IRQ
);
324 opp
->irq_raise(opp
, n_CPU
, src
);
327 /* update pic state because registers for n_IRQ have changed value */
328 static void openpic_update_irq(openpic_t
*opp
, int n_IRQ
)
333 src
= &opp
->src
[n_IRQ
];
337 DPRINTF("%s: IRQ %d is not pending\n", __func__
, n_IRQ
);
340 if (test_bit(&src
->ipvp
, IPVP_MASK
)) {
341 /* Interrupt source is disabled */
342 DPRINTF("%s: IRQ %d is disabled\n", __func__
, n_IRQ
);
345 if (IPVP_PRIORITY(src
->ipvp
) == 0) {
346 /* Priority set to zero */
347 DPRINTF("%s: IRQ %d has 0 priority\n", __func__
, n_IRQ
);
350 if (test_bit(&src
->ipvp
, IPVP_ACTIVITY
)) {
351 /* IRQ already active */
352 DPRINTF("%s: IRQ %d is already active\n", __func__
, n_IRQ
);
355 if (src
->ide
== 0x00000000) {
357 DPRINTF("%s: IRQ %d has no target\n", __func__
, n_IRQ
);
361 if (src
->ide
== (1 << src
->last_cpu
)) {
362 /* Only one CPU is allowed to receive this IRQ */
363 IRQ_local_pipe(opp
, src
->last_cpu
, n_IRQ
);
364 } else if (!test_bit(&src
->ipvp
, IPVP_MODE
)) {
365 /* Directed delivery mode */
366 for (i
= 0; i
< opp
->nb_cpus
; i
++) {
367 if (test_bit(&src
->ide
, i
))
368 IRQ_local_pipe(opp
, i
, n_IRQ
);
371 /* Distributed delivery mode */
372 for (i
= src
->last_cpu
+ 1; i
!= src
->last_cpu
; i
++) {
373 if (i
== opp
->nb_cpus
)
375 if (test_bit(&src
->ide
, i
)) {
376 IRQ_local_pipe(opp
, i
, n_IRQ
);
384 static void openpic_set_irq(void *opaque
, int n_IRQ
, int level
)
386 openpic_t
*opp
= opaque
;
389 src
= &opp
->src
[n_IRQ
];
390 DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
391 n_IRQ
, level
, src
->ipvp
);
392 if (test_bit(&src
->ipvp
, IPVP_SENSE
)) {
393 /* level-sensitive irq */
394 src
->pending
= level
;
396 reset_bit(&src
->ipvp
, IPVP_ACTIVITY
);
398 /* edge-sensitive irq */
402 openpic_update_irq(opp
, n_IRQ
);
405 static void openpic_reset (void *opaque
)
407 openpic_t
*opp
= (openpic_t
*)opaque
;
410 opp
->glbc
= 0x80000000;
411 /* Initialise controller registers */
412 opp
->frep
= ((OPENPIC_EXT_IRQ
- 1) << 16) | ((MAX_CPU
- 1) << 8) | VID
;
414 opp
->pint
= 0x00000000;
415 opp
->spve
= 0x000000FF;
416 opp
->tifr
= 0x003F7A00;
418 opp
->micr
= 0x00000000;
419 /* Initialise IRQ sources */
420 for (i
= 0; i
< opp
->max_irq
; i
++) {
421 opp
->src
[i
].ipvp
= 0xA0000000;
422 opp
->src
[i
].ide
= 0x00000000;
424 /* Initialise IRQ destinations */
425 for (i
= 0; i
< MAX_CPU
; i
++) {
426 opp
->dst
[i
].pctp
= 0x0000000F;
427 opp
->dst
[i
].pcsr
= 0x00000000;
428 memset(&opp
->dst
[i
].raised
, 0, sizeof(IRQ_queue_t
));
429 opp
->dst
[i
].raised
.next
= -1;
430 memset(&opp
->dst
[i
].servicing
, 0, sizeof(IRQ_queue_t
));
431 opp
->dst
[i
].servicing
.next
= -1;
433 /* Initialise timers */
434 for (i
= 0; i
< MAX_TMR
; i
++) {
435 opp
->timers
[i
].ticc
= 0x00000000;
436 opp
->timers
[i
].tibc
= 0x80000000;
438 /* Go out of RESET state */
439 opp
->glbc
= 0x00000000;
442 static inline uint32_t read_IRQreg_ide(openpic_t
*opp
, int n_IRQ
)
444 return opp
->src
[n_IRQ
].ide
;
447 static inline uint32_t read_IRQreg_ipvp(openpic_t
*opp
, int n_IRQ
)
449 return opp
->src
[n_IRQ
].ipvp
;
452 static inline void write_IRQreg_ide(openpic_t
*opp
, int n_IRQ
, uint32_t val
)
456 tmp
= val
& 0xC0000000;
457 tmp
|= val
& ((1ULL << MAX_CPU
) - 1);
458 opp
->src
[n_IRQ
].ide
= tmp
;
459 DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ
, opp
->src
[n_IRQ
].ide
);
462 static inline void write_IRQreg_ipvp(openpic_t
*opp
, int n_IRQ
, uint32_t val
)
464 /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
465 /* ACTIVITY bit is read-only */
466 opp
->src
[n_IRQ
].ipvp
= (opp
->src
[n_IRQ
].ipvp
& 0x40000000)
467 | (val
& 0x800F00FF);
468 openpic_update_irq(opp
, n_IRQ
);
469 DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ
, val
,
470 opp
->src
[n_IRQ
].ipvp
);
473 static void openpic_gbl_write(void *opaque
, hwaddr addr
, uint64_t val
,
476 openpic_t
*opp
= opaque
;
480 DPRINTF("%s: addr " TARGET_FMT_plx
" <= %08x\n", __func__
, addr
, val
);
484 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
494 openpic_cpu_write_internal(opp
, addr
, val
, get_current_cpu());
496 case 0x1000: /* FREP */
498 case 0x1020: /* GLBC */
499 if (val
& 0x80000000 && opp
->reset
)
501 opp
->glbc
= val
& ~0x80000000;
503 case 0x1080: /* VENI */
505 case 0x1090: /* PINT */
506 for (idx
= 0; idx
< opp
->nb_cpus
; idx
++) {
507 if ((val
& (1 << idx
)) && !(opp
->pint
& (1 << idx
))) {
508 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx
);
509 dst
= &opp
->dst
[idx
];
510 qemu_irq_raise(dst
->irqs
[OPENPIC_OUTPUT_RESET
]);
511 } else if (!(val
& (1 << idx
)) && (opp
->pint
& (1 << idx
))) {
512 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx
);
513 dst
= &opp
->dst
[idx
];
514 qemu_irq_lower(dst
->irqs
[OPENPIC_OUTPUT_RESET
]);
519 case 0x10A0: /* IPI_IPVP */
525 idx
= (addr
- 0x10A0) >> 4;
526 write_IRQreg_ipvp(opp
, opp
->irq_ipi0
+ idx
, val
);
529 case 0x10E0: /* SPVE */
530 opp
->spve
= val
& 0x000000FF;
532 case 0x10F0: /* TIFR */
540 static uint64_t openpic_gbl_read(void *opaque
, hwaddr addr
, unsigned len
)
542 openpic_t
*opp
= opaque
;
545 DPRINTF("%s: addr " TARGET_FMT_plx
"\n", __func__
, addr
);
550 case 0x1000: /* FREP */
553 case 0x1020: /* GLBC */
556 case 0x1080: /* VENI */
559 case 0x1090: /* PINT */
562 case 0x00: /* Block Revision Register1 (BRR1) */
571 retval
= openpic_cpu_read_internal(opp
, addr
, get_current_cpu());
573 case 0x10A0: /* IPI_IPVP */
579 idx
= (addr
- 0x10A0) >> 4;
580 retval
= read_IRQreg_ipvp(opp
, opp
->irq_ipi0
+ idx
);
583 case 0x10E0: /* SPVE */
586 case 0x10F0: /* TIFR */
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
);
608 idx
= (addr
& 0xFFF0) >> 6;
611 case 0x00: /* TICC */
613 case 0x10: /* TIBC */
614 if ((opp
->timers
[idx
].ticc
& 0x80000000) != 0 &&
615 (val
& 0x80000000) == 0 &&
616 (opp
->timers
[idx
].tibc
& 0x80000000) != 0)
617 opp
->timers
[idx
].ticc
&= ~0x80000000;
618 opp
->timers
[idx
].tibc
= val
;
620 case 0x20: /* TIVP */
621 write_IRQreg_ipvp(opp
, opp
->irq_tim0
+ idx
, val
);
623 case 0x30: /* TIDE */
624 write_IRQreg_ide(opp
, opp
->irq_tim0
+ idx
, val
);
629 static uint64_t openpic_timer_read(void *opaque
, hwaddr addr
, unsigned len
)
631 openpic_t
*opp
= opaque
;
635 DPRINTF("%s: addr %08x\n", __func__
, addr
);
641 idx
= (addr
& 0xFFF0) >> 6;
644 case 0x00: /* TICC */
645 retval
= opp
->timers
[idx
].ticc
;
647 case 0x10: /* TIBC */
648 retval
= opp
->timers
[idx
].tibc
;
650 case 0x20: /* TIPV */
651 retval
= read_IRQreg_ipvp(opp
, opp
->irq_tim0
+ idx
);
653 case 0x30: /* TIDE */
654 retval
= read_IRQreg_ide(opp
, opp
->irq_tim0
+ idx
);
657 DPRINTF("%s: => %08x\n", __func__
, retval
);
662 static void openpic_src_write(void *opaque
, hwaddr addr
, uint64_t val
,
665 openpic_t
*opp
= opaque
;
668 DPRINTF("%s: addr %08x <= %08x\n", __func__
, addr
, val
);
671 addr
= addr
& 0xFFF0;
674 /* EXDE / IFEDE / IEEDE */
675 write_IRQreg_ide(opp
, idx
, val
);
677 /* EXVP / IFEVP / IEEVP */
678 write_IRQreg_ipvp(opp
, idx
, val
);
682 static uint64_t openpic_src_read(void *opaque
, uint64_t addr
, unsigned len
)
684 openpic_t
*opp
= opaque
;
688 DPRINTF("%s: addr %08x\n", __func__
, addr
);
692 addr
= addr
& 0xFFF0;
695 /* EXDE / IFEDE / IEEDE */
696 retval
= read_IRQreg_ide(opp
, idx
);
698 /* EXVP / IFEVP / IEEVP */
699 retval
= read_IRQreg_ipvp(opp
, idx
);
701 DPRINTF("%s: => %08x\n", __func__
, retval
);
706 static void openpic_cpu_write_internal(void *opaque
, hwaddr addr
,
707 uint32_t val
, int idx
)
709 openpic_t
*opp
= opaque
;
714 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx
" <= %08x\n", __func__
, idx
,
718 dst
= &opp
->dst
[idx
];
721 case 0x40: /* IPIDR */
725 idx
= (addr
- 0x40) >> 4;
726 /* we use IDE as mask which CPUs to deliver the IPI to still. */
727 write_IRQreg_ide(opp
, opp
->irq_ipi0
+ idx
,
728 opp
->src
[opp
->irq_ipi0
+ idx
].ide
| val
);
729 openpic_set_irq(opp
, opp
->irq_ipi0
+ idx
, 1);
730 openpic_set_irq(opp
, opp
->irq_ipi0
+ idx
, 0);
732 case 0x80: /* PCTP */
733 dst
->pctp
= val
& 0x0000000F;
735 case 0x90: /* WHOAMI */
736 /* Read-only register */
738 case 0xA0: /* PIAC */
739 /* Read-only register */
741 case 0xB0: /* PEOI */
743 s_IRQ
= IRQ_get_next(opp
, &dst
->servicing
);
744 IRQ_resetbit(&dst
->servicing
, s_IRQ
);
745 dst
->servicing
.next
= -1;
746 /* Set up next servicing IRQ */
747 s_IRQ
= IRQ_get_next(opp
, &dst
->servicing
);
748 /* Check queued interrupts. */
749 n_IRQ
= IRQ_get_next(opp
, &dst
->raised
);
750 src
= &opp
->src
[n_IRQ
];
753 IPVP_PRIORITY(src
->ipvp
) > dst
->servicing
.priority
)) {
754 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
756 opp
->irq_raise(opp
, idx
, src
);
764 static void openpic_cpu_write(void *opaque
, hwaddr addr
, uint64_t val
,
767 openpic_cpu_write_internal(opaque
, addr
, val
, (addr
& 0x1f000) >> 12);
770 static uint32_t openpic_cpu_read_internal(void *opaque
, hwaddr addr
,
773 openpic_t
*opp
= opaque
;
779 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx
"\n", __func__
, idx
, addr
);
783 dst
= &opp
->dst
[idx
];
786 case 0x00: /* Block Revision Register1 (BRR1) */
787 retval
= FSL_BRR1_IPID
| FSL_BRR1_IPMJ
| FSL_BRR1_IPMN
;
789 case 0x80: /* PCTP */
792 case 0x90: /* WHOAMI */
795 case 0xA0: /* PIAC */
796 DPRINTF("Lower OpenPIC INT output\n");
797 qemu_irq_lower(dst
->irqs
[OPENPIC_OUTPUT_INT
]);
798 n_IRQ
= IRQ_get_next(opp
, &dst
->raised
);
799 DPRINTF("PIAC: irq=%d\n", n_IRQ
);
801 /* No more interrupt pending */
802 retval
= IPVP_VECTOR(opp
->spve
);
804 src
= &opp
->src
[n_IRQ
];
805 if (!test_bit(&src
->ipvp
, IPVP_ACTIVITY
) ||
806 !(IPVP_PRIORITY(src
->ipvp
) > dst
->pctp
)) {
807 /* - Spurious level-sensitive IRQ
808 * - Priorities has been changed
809 * and the pending IRQ isn't allowed anymore
811 reset_bit(&src
->ipvp
, IPVP_ACTIVITY
);
812 retval
= IPVP_VECTOR(opp
->spve
);
814 /* IRQ enter servicing state */
815 IRQ_setbit(&dst
->servicing
, n_IRQ
);
816 retval
= IPVP_VECTOR(src
->ipvp
);
818 IRQ_resetbit(&dst
->raised
, n_IRQ
);
819 dst
->raised
.next
= -1;
820 if (!test_bit(&src
->ipvp
, IPVP_SENSE
)) {
821 /* edge-sensitive IRQ */
822 reset_bit(&src
->ipvp
, IPVP_ACTIVITY
);
826 if ((n_IRQ
>= opp
->irq_ipi0
) && (n_IRQ
< (opp
->irq_ipi0
+ MAX_IPI
))) {
827 src
->ide
&= ~(1 << idx
);
828 if (src
->ide
&& !test_bit(&src
->ipvp
, IPVP_SENSE
)) {
829 /* trigger on CPUs that didn't know about it yet */
830 openpic_set_irq(opp
, n_IRQ
, 1);
831 openpic_set_irq(opp
, n_IRQ
, 0);
832 /* if all CPUs knew about it, set active bit again */
833 set_bit(&src
->ipvp
, IPVP_ACTIVITY
);
838 case 0xB0: /* PEOI */
844 DPRINTF("%s: => %08x\n", __func__
, retval
);
849 static uint64_t openpic_cpu_read(void *opaque
, hwaddr addr
, unsigned len
)
851 return openpic_cpu_read_internal(opaque
, addr
, (addr
& 0x1f000) >> 12);
854 static const MemoryRegionOps openpic_glb_ops
= {
855 .write
= openpic_gbl_write
,
856 .read
= openpic_gbl_read
,
857 .endianness
= DEVICE_LITTLE_ENDIAN
,
859 .min_access_size
= 4,
860 .max_access_size
= 4,
864 static const MemoryRegionOps openpic_tmr_ops
= {
865 .write
= openpic_timer_write
,
866 .read
= openpic_timer_read
,
867 .endianness
= DEVICE_LITTLE_ENDIAN
,
869 .min_access_size
= 4,
870 .max_access_size
= 4,
874 static const MemoryRegionOps openpic_cpu_ops
= {
875 .write
= openpic_cpu_write
,
876 .read
= openpic_cpu_read
,
877 .endianness
= DEVICE_LITTLE_ENDIAN
,
879 .min_access_size
= 4,
880 .max_access_size
= 4,
884 static const MemoryRegionOps openpic_src_ops
= {
885 .write
= openpic_src_write
,
886 .read
= openpic_src_read
,
887 .endianness
= DEVICE_LITTLE_ENDIAN
,
889 .min_access_size
= 4,
890 .max_access_size
= 4,
894 static void openpic_save_IRQ_queue(QEMUFile
* f
, IRQ_queue_t
*q
)
898 for (i
= 0; i
< BF_WIDTH(MAX_IRQ
); i
++)
899 qemu_put_be32s(f
, &q
->queue
[i
]);
901 qemu_put_sbe32s(f
, &q
->next
);
902 qemu_put_sbe32s(f
, &q
->priority
);
905 static void openpic_save(QEMUFile
* f
, void *opaque
)
907 openpic_t
*opp
= (openpic_t
*)opaque
;
910 qemu_put_be32s(f
, &opp
->frep
);
911 qemu_put_be32s(f
, &opp
->glbc
);
912 qemu_put_be32s(f
, &opp
->micr
);
913 qemu_put_be32s(f
, &opp
->veni
);
914 qemu_put_be32s(f
, &opp
->pint
);
915 qemu_put_be32s(f
, &opp
->spve
);
916 qemu_put_be32s(f
, &opp
->tifr
);
918 for (i
= 0; i
< opp
->max_irq
; i
++) {
919 qemu_put_be32s(f
, &opp
->src
[i
].ipvp
);
920 qemu_put_be32s(f
, &opp
->src
[i
].ide
);
921 qemu_put_sbe32s(f
, &opp
->src
[i
].type
);
922 qemu_put_sbe32s(f
, &opp
->src
[i
].last_cpu
);
923 qemu_put_sbe32s(f
, &opp
->src
[i
].pending
);
926 qemu_put_sbe32s(f
, &opp
->nb_cpus
);
928 for (i
= 0; i
< opp
->nb_cpus
; i
++) {
929 qemu_put_be32s(f
, &opp
->dst
[i
].tfrr
);
930 qemu_put_be32s(f
, &opp
->dst
[i
].pctp
);
931 qemu_put_be32s(f
, &opp
->dst
[i
].pcsr
);
932 openpic_save_IRQ_queue(f
, &opp
->dst
[i
].raised
);
933 openpic_save_IRQ_queue(f
, &opp
->dst
[i
].servicing
);
936 for (i
= 0; i
< MAX_TMR
; i
++) {
937 qemu_put_be32s(f
, &opp
->timers
[i
].ticc
);
938 qemu_put_be32s(f
, &opp
->timers
[i
].tibc
);
941 pci_device_save(&opp
->pci_dev
, f
);
944 static void openpic_load_IRQ_queue(QEMUFile
* f
, IRQ_queue_t
*q
)
948 for (i
= 0; i
< BF_WIDTH(MAX_IRQ
); i
++)
949 qemu_get_be32s(f
, &q
->queue
[i
]);
951 qemu_get_sbe32s(f
, &q
->next
);
952 qemu_get_sbe32s(f
, &q
->priority
);
955 static int openpic_load(QEMUFile
* f
, void *opaque
, int version_id
)
957 openpic_t
*opp
= (openpic_t
*)opaque
;
963 qemu_get_be32s(f
, &opp
->frep
);
964 qemu_get_be32s(f
, &opp
->glbc
);
965 qemu_get_be32s(f
, &opp
->micr
);
966 qemu_get_be32s(f
, &opp
->veni
);
967 qemu_get_be32s(f
, &opp
->pint
);
968 qemu_get_be32s(f
, &opp
->spve
);
969 qemu_get_be32s(f
, &opp
->tifr
);
971 for (i
= 0; i
< opp
->max_irq
; i
++) {
972 qemu_get_be32s(f
, &opp
->src
[i
].ipvp
);
973 qemu_get_be32s(f
, &opp
->src
[i
].ide
);
974 qemu_get_sbe32s(f
, &opp
->src
[i
].type
);
975 qemu_get_sbe32s(f
, &opp
->src
[i
].last_cpu
);
976 qemu_get_sbe32s(f
, &opp
->src
[i
].pending
);
979 qemu_get_sbe32s(f
, &opp
->nb_cpus
);
981 for (i
= 0; i
< opp
->nb_cpus
; i
++) {
982 qemu_get_be32s(f
, &opp
->dst
[i
].tfrr
);
983 qemu_get_be32s(f
, &opp
->dst
[i
].pctp
);
984 qemu_get_be32s(f
, &opp
->dst
[i
].pcsr
);
985 openpic_load_IRQ_queue(f
, &opp
->dst
[i
].raised
);
986 openpic_load_IRQ_queue(f
, &opp
->dst
[i
].servicing
);
989 for (i
= 0; i
< MAX_TMR
; i
++) {
990 qemu_get_be32s(f
, &opp
->timers
[i
].ticc
);
991 qemu_get_be32s(f
, &opp
->timers
[i
].tibc
);
994 return pci_device_load(&opp
->pci_dev
, f
);
997 static void openpic_irq_raise(openpic_t
*opp
, int n_CPU
, IRQ_src_t
*src
)
999 qemu_irq_raise(opp
->dst
[n_CPU
].irqs
[OPENPIC_OUTPUT_INT
]);
1002 qemu_irq
*openpic_init (MemoryRegion
**pmem
, int nb_cpus
,
1003 qemu_irq
**irqs
, qemu_irq irq_out
)
1009 MemoryRegionOps
const *ops
;
1013 {"glb", &openpic_glb_ops
, OPENPIC_GLB_REG_START
, OPENPIC_GLB_REG_SIZE
},
1014 {"tmr", &openpic_tmr_ops
, OPENPIC_TMR_REG_START
, OPENPIC_TMR_REG_SIZE
},
1015 {"src", &openpic_src_ops
, OPENPIC_SRC_REG_START
, OPENPIC_SRC_REG_SIZE
},
1016 {"cpu", &openpic_cpu_ops
, OPENPIC_CPU_REG_START
, OPENPIC_CPU_REG_SIZE
},
1019 /* XXX: for now, only one CPU is supported */
1022 opp
= g_malloc0(sizeof(openpic_t
));
1024 memory_region_init(&opp
->mem
, "openpic", 0x40000);
1026 for (i
= 0; i
< ARRAY_SIZE(list
); i
++) {
1028 memory_region_init_io(&opp
->sub_io_mem
[i
], list
[i
].ops
, opp
,
1029 list
[i
].name
, list
[i
].size
);
1031 memory_region_add_subregion(&opp
->mem
, list
[i
].start_addr
,
1032 &opp
->sub_io_mem
[i
]);
1035 // isu_base &= 0xFFFC0000;
1036 opp
->nb_cpus
= nb_cpus
;
1037 opp
->max_irq
= OPENPIC_MAX_IRQ
;
1038 opp
->irq_ipi0
= OPENPIC_IRQ_IPI0
;
1039 opp
->irq_tim0
= OPENPIC_IRQ_TIM0
;
1041 for (i
= 0; i
< OPENPIC_EXT_IRQ
; i
++) {
1042 opp
->src
[i
].type
= IRQ_EXTERNAL
;
1044 for (; i
< OPENPIC_IRQ_TIM0
; i
++) {
1045 opp
->src
[i
].type
= IRQ_SPECIAL
;
1047 m
= OPENPIC_IRQ_IPI0
;
1048 for (; i
< m
; i
++) {
1049 opp
->src
[i
].type
= IRQ_TIMER
;
1051 for (; i
< OPENPIC_MAX_IRQ
; i
++) {
1052 opp
->src
[i
].type
= IRQ_INTERNAL
;
1054 for (i
= 0; i
< nb_cpus
; i
++)
1055 opp
->dst
[i
].irqs
= irqs
[i
];
1056 opp
->irq_out
= irq_out
;
1058 register_savevm(&opp
->pci_dev
.qdev
, "openpic", 0, 2,
1059 openpic_save
, openpic_load
, opp
);
1060 qemu_register_reset(openpic_reset
, opp
);
1062 opp
->irq_raise
= openpic_irq_raise
;
1063 opp
->reset
= openpic_reset
;
1068 return qemu_allocate_irqs(openpic_set_irq
, opp
, opp
->max_irq
);
1071 static void mpic_irq_raise(openpic_t
*mpp
, int n_CPU
, IRQ_src_t
*src
)
1073 int n_ci
= IDR_CI0
- n_CPU
;
1075 if(test_bit(&src
->ide
, n_ci
)) {
1076 qemu_irq_raise(mpp
->dst
[n_CPU
].irqs
[OPENPIC_OUTPUT_CINT
]);
1079 qemu_irq_raise(mpp
->dst
[n_CPU
].irqs
[OPENPIC_OUTPUT_INT
]);
1083 static void mpic_reset (void *opaque
)
1085 openpic_t
*mpp
= (openpic_t
*)opaque
;
1088 mpp
->glbc
= 0x80000000;
1089 /* Initialise controller registers */
1090 mpp
->frep
= 0x004f0002 | ((mpp
->nb_cpus
- 1) << 8);
1092 mpp
->pint
= 0x00000000;
1093 mpp
->spve
= 0x0000FFFF;
1094 /* Initialise IRQ sources */
1095 for (i
= 0; i
< mpp
->max_irq
; i
++) {
1096 mpp
->src
[i
].ipvp
= 0x80800000;
1097 mpp
->src
[i
].ide
= 0x00000001;
1099 /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1100 for (i
= mpp
->irq_ipi0
; i
< (mpp
->irq_ipi0
+ MAX_IPI
); i
++) {
1101 mpp
->src
[i
].ide
= 0;
1103 /* Initialise IRQ destinations */
1104 for (i
= 0; i
< MAX_CPU
; i
++) {
1105 mpp
->dst
[i
].pctp
= 0x0000000F;
1106 mpp
->dst
[i
].tfrr
= 0x00000000;
1107 memset(&mpp
->dst
[i
].raised
, 0, sizeof(IRQ_queue_t
));
1108 mpp
->dst
[i
].raised
.next
= -1;
1109 memset(&mpp
->dst
[i
].servicing
, 0, sizeof(IRQ_queue_t
));
1110 mpp
->dst
[i
].servicing
.next
= -1;
1112 /* Initialise timers */
1113 for (i
= 0; i
< MAX_TMR
; i
++) {
1114 mpp
->timers
[i
].ticc
= 0x00000000;
1115 mpp
->timers
[i
].tibc
= 0x80000000;
1117 /* Go out of RESET state */
1118 mpp
->glbc
= 0x00000000;
1121 static void mpic_timer_write(void *opaque
, hwaddr addr
, uint64_t val
,
1124 openpic_t
*mpp
= opaque
;
1127 DPRINTF("%s: addr " TARGET_FMT_plx
" <= %08x\n", __func__
, addr
, val
);
1131 idx
= (addr
>> 6) & 0x3;
1132 switch (addr
& 0x30) {
1133 case 0x00: /* gtccr */
1135 case 0x10: /* gtbcr */
1136 if ((mpp
->timers
[idx
].ticc
& 0x80000000) != 0 &&
1137 (val
& 0x80000000) == 0 &&
1138 (mpp
->timers
[idx
].tibc
& 0x80000000) != 0)
1139 mpp
->timers
[idx
].ticc
&= ~0x80000000;
1140 mpp
->timers
[idx
].tibc
= val
;
1142 case 0x20: /* GTIVPR */
1143 write_IRQreg_ipvp(mpp
, MPIC_TMR_IRQ
+ idx
, val
);
1145 case 0x30: /* GTIDR & TFRR */
1146 if ((addr
& 0xF0) == 0xF0)
1147 mpp
->dst
[cpu
].tfrr
= val
;
1149 write_IRQreg_ide(mpp
, MPIC_TMR_IRQ
+ idx
, val
);
1154 static uint64_t mpic_timer_read(void *opaque
, hwaddr addr
, unsigned len
)
1156 openpic_t
*mpp
= opaque
;
1160 DPRINTF("%s: addr " TARGET_FMT_plx
"\n", __func__
, addr
);
1161 retval
= 0xFFFFFFFF;
1165 idx
= (addr
>> 6) & 0x3;
1166 switch (addr
& 0x30) {
1167 case 0x00: /* gtccr */
1168 retval
= mpp
->timers
[idx
].ticc
;
1170 case 0x10: /* gtbcr */
1171 retval
= mpp
->timers
[idx
].tibc
;
1173 case 0x20: /* TIPV */
1174 retval
= read_IRQreg_ipvp(mpp
, MPIC_TMR_IRQ
+ idx
);
1176 case 0x30: /* TIDR */
1177 if ((addr
&0xF0) == 0XF0)
1178 retval
= mpp
->dst
[cpu
].tfrr
;
1180 retval
= read_IRQreg_ide(mpp
, MPIC_TMR_IRQ
+ idx
);
1183 DPRINTF("%s: => %08x\n", __func__
, retval
);
1188 static const MemoryRegionOps mpic_glb_ops
= {
1189 .write
= openpic_gbl_write
,
1190 .read
= openpic_gbl_read
,
1191 .endianness
= DEVICE_BIG_ENDIAN
,
1193 .min_access_size
= 4,
1194 .max_access_size
= 4,
1198 static const MemoryRegionOps mpic_tmr_ops
= {
1199 .write
= mpic_timer_write
,
1200 .read
= mpic_timer_read
,
1201 .endianness
= DEVICE_BIG_ENDIAN
,
1203 .min_access_size
= 4,
1204 .max_access_size
= 4,
1208 static const MemoryRegionOps mpic_cpu_ops
= {
1209 .write
= openpic_cpu_write
,
1210 .read
= openpic_cpu_read
,
1211 .endianness
= DEVICE_BIG_ENDIAN
,
1213 .min_access_size
= 4,
1214 .max_access_size
= 4,
1218 static const MemoryRegionOps mpic_irq_ops
= {
1219 .write
= openpic_src_write
,
1220 .read
= openpic_src_read
,
1221 .endianness
= DEVICE_BIG_ENDIAN
,
1223 .min_access_size
= 4,
1224 .max_access_size
= 4,
1228 qemu_irq
*mpic_init (MemoryRegion
*address_space
, hwaddr base
,
1229 int nb_cpus
, qemu_irq
**irqs
, qemu_irq irq_out
)
1235 MemoryRegionOps
const *ops
;
1239 {"glb", &mpic_glb_ops
, MPIC_GLB_REG_START
, MPIC_GLB_REG_SIZE
},
1240 {"tmr", &mpic_tmr_ops
, MPIC_TMR_REG_START
, MPIC_TMR_REG_SIZE
},
1241 {"src", &mpic_irq_ops
, MPIC_SRC_REG_START
, MPIC_SRC_REG_SIZE
},
1242 {"cpu", &mpic_cpu_ops
, MPIC_CPU_REG_START
, MPIC_CPU_REG_SIZE
},
1245 mpp
= g_malloc0(sizeof(openpic_t
));
1247 memory_region_init(&mpp
->mem
, "mpic", 0x40000);
1248 memory_region_add_subregion(address_space
, base
, &mpp
->mem
);
1250 for (i
= 0; i
< sizeof(list
)/sizeof(list
[0]); i
++) {
1252 memory_region_init_io(&mpp
->sub_io_mem
[i
], list
[i
].ops
, mpp
,
1253 list
[i
].name
, list
[i
].size
);
1255 memory_region_add_subregion(&mpp
->mem
, list
[i
].start_addr
,
1256 &mpp
->sub_io_mem
[i
]);
1259 mpp
->nb_cpus
= nb_cpus
;
1260 mpp
->max_irq
= MPIC_MAX_IRQ
;
1261 mpp
->irq_ipi0
= MPIC_IPI_IRQ
;
1262 mpp
->irq_tim0
= MPIC_TMR_IRQ
;
1264 for (i
= 0; i
< nb_cpus
; i
++)
1265 mpp
->dst
[i
].irqs
= irqs
[i
];
1266 mpp
->irq_out
= irq_out
;
1268 mpp
->irq_raise
= mpic_irq_raise
;
1269 mpp
->reset
= mpic_reset
;
1271 register_savevm(NULL
, "mpic", 0, 2, openpic_save
, openpic_load
, mpp
);
1272 qemu_register_reset(mpic_reset
, mpp
);
1274 return qemu_allocate_irqs(openpic_set_irq
, mpp
, mpp
->max_irq
);