blob: d6d70a473d7f2e9ec75236465096c56b8ab13d84 [file] [log] [blame]
Scott Woodb823f982013-04-12 14:08:43 +00001/*
2 * OpenPIC emulation
3 *
4 * Copyright (c) 2004 Jocelyn Mayer
5 * 2011 Alexander Graf
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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
23 * THE SOFTWARE.
24 */
Scott Woodb823f982013-04-12 14:08:43 +000025
26#define MAX_CPU 32
27#define MAX_SRC 256
28#define MAX_TMR 4
29#define MAX_IPI 4
30#define MAX_MSI 8
31#define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR)
32#define VID 0x03 /* MPIC version ID */
33
34/* OpenPIC capability flags */
35#define OPENPIC_FLAG_IDR_CRIT (1 << 0)
36#define OPENPIC_FLAG_ILR (2 << 0)
37
38/* OpenPIC address map */
39#define OPENPIC_GLB_REG_START 0x0
40#define OPENPIC_GLB_REG_SIZE 0x10F0
41#define OPENPIC_TMR_REG_START 0x10F0
42#define OPENPIC_TMR_REG_SIZE 0x220
43#define OPENPIC_MSI_REG_START 0x1600
44#define OPENPIC_MSI_REG_SIZE 0x200
45#define OPENPIC_SUMMARY_REG_START 0x3800
46#define OPENPIC_SUMMARY_REG_SIZE 0x800
47#define OPENPIC_SRC_REG_START 0x10000
48#define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
49#define OPENPIC_CPU_REG_START 0x20000
50#define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
51
Scott Woodb823f982013-04-12 14:08:43 +000052typedef struct FslMpicInfo {
53 int max_ext;
54} FslMpicInfo;
55
56static FslMpicInfo fsl_mpic_20 = {
57 .max_ext = 12,
58};
59
60static FslMpicInfo fsl_mpic_42 = {
61 .max_ext = 12,
62};
63
64#define FRR_NIRQ_SHIFT 16
65#define FRR_NCPU_SHIFT 8
66#define FRR_VID_SHIFT 0
67
68#define VID_REVISION_1_2 2
69#define VID_REVISION_1_3 3
70
71#define VIR_GENERIC 0x00000000 /* Generic Vendor ID */
72
73#define GCR_RESET 0x80000000
74#define GCR_MODE_PASS 0x00000000
75#define GCR_MODE_MIXED 0x20000000
76#define GCR_MODE_PROXY 0x60000000
77
78#define TBCR_CI 0x80000000 /* count inhibit */
79#define TCCR_TOG 0x80000000 /* toggles when decrement to zero */
80
81#define IDR_EP_SHIFT 31
82#define IDR_EP_MASK (1 << IDR_EP_SHIFT)
83#define IDR_CI0_SHIFT 30
84#define IDR_CI1_SHIFT 29
85#define IDR_P1_SHIFT 1
86#define IDR_P0_SHIFT 0
87
88#define ILR_INTTGT_MASK 0x000000ff
89#define ILR_INTTGT_INT 0x00
90#define ILR_INTTGT_CINT 0x01 /* critical */
91#define ILR_INTTGT_MCP 0x02 /* machine check */
92
Scott Woodb823f982013-04-12 14:08:43 +000093#define MSIIR_OFFSET 0x140
94#define MSIIR_SRS_SHIFT 29
95#define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT)
96#define MSIIR_IBS_SHIFT 24
97#define MSIIR_IBS_MASK (0x1f << MSIIR_IBS_SHIFT)
98
99static int get_current_cpu(void)
100{
101 CPUState *cpu_single_cpu;
102
103 if (!cpu_single_env) {
104 return -1;
105 }
106
107 cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
108 return cpu_single_cpu->cpu_index;
109}
110
111static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, int idx);
112static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
113 uint32_t val, int idx);
114
115typedef enum IRQType {
116 IRQ_TYPE_NORMAL = 0,
117 IRQ_TYPE_FSLINT, /* FSL internal interrupt -- level only */
118 IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */
119} IRQType;
120
121typedef struct IRQQueue {
122 /* Round up to the nearest 64 IRQs so that the queue length
123 * won't change when moving between 32 and 64 bit hosts.
124 */
125 unsigned long queue[BITS_TO_LONGS((MAX_IRQ + 63) & ~63)];
126 int next;
127 int priority;
128} IRQQueue;
129
130typedef struct IRQSource {
131 uint32_t ivpr; /* IRQ vector/priority register */
132 uint32_t idr; /* IRQ destination register */
133 uint32_t destmask; /* bitmap of CPU destinations */
134 int last_cpu;
135 int output; /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
136 int pending; /* TRUE if IRQ is pending */
137 IRQType type;
138 bool level:1; /* level-triggered */
139 bool nomask:1; /* critical interrupts ignore mask on some FSL MPICs */
140} IRQSource;
141
142#define IVPR_MASK_SHIFT 31
143#define IVPR_MASK_MASK (1 << IVPR_MASK_SHIFT)
144#define IVPR_ACTIVITY_SHIFT 30
145#define IVPR_ACTIVITY_MASK (1 << IVPR_ACTIVITY_SHIFT)
146#define IVPR_MODE_SHIFT 29
147#define IVPR_MODE_MASK (1 << IVPR_MODE_SHIFT)
148#define IVPR_POLARITY_SHIFT 23
149#define IVPR_POLARITY_MASK (1 << IVPR_POLARITY_SHIFT)
150#define IVPR_SENSE_SHIFT 22
151#define IVPR_SENSE_MASK (1 << IVPR_SENSE_SHIFT)
152
153#define IVPR_PRIORITY_MASK (0xF << 16)
154#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
155#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
156
157/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
158#define IDR_EP 0x80000000 /* external pin */
159#define IDR_CI 0x40000000 /* critical interrupt */
160
161typedef struct IRQDest {
162 int32_t ctpr; /* CPU current task priority */
163 IRQQueue raised;
164 IRQQueue servicing;
165 qemu_irq *irqs;
166
167 /* Count of IRQ sources asserting on non-INT outputs */
168 uint32_t outputs_active[OPENPIC_OUTPUT_NB];
169} IRQDest;
170
171typedef struct OpenPICState {
172 SysBusDevice busdev;
173 MemoryRegion mem;
174
175 /* Behavior control */
176 FslMpicInfo *fsl;
177 uint32_t model;
178 uint32_t flags;
179 uint32_t nb_irqs;
180 uint32_t vid;
181 uint32_t vir; /* Vendor identification register */
182 uint32_t vector_mask;
183 uint32_t tfrr_reset;
184 uint32_t ivpr_reset;
185 uint32_t idr_reset;
186 uint32_t brr1;
187 uint32_t mpic_mode_mask;
188
189 /* Sub-regions */
190 MemoryRegion sub_io_mem[6];
191
192 /* Global registers */
193 uint32_t frr; /* Feature reporting register */
194 uint32_t gcr; /* Global configuration register */
195 uint32_t pir; /* Processor initialization register */
196 uint32_t spve; /* Spurious vector register */
197 uint32_t tfrr; /* Timer frequency reporting register */
198 /* Source registers */
199 IRQSource src[MAX_IRQ];
200 /* Local registers per output pin */
201 IRQDest dst[MAX_CPU];
202 uint32_t nb_cpus;
203 /* Timer registers */
204 struct {
205 uint32_t tccr; /* Global timer current count register */
206 uint32_t tbcr; /* Global timer base count register */
207 } timers[MAX_TMR];
208 /* Shared MSI registers */
209 struct {
210 uint32_t msir; /* Shared Message Signaled Interrupt Register */
211 } msi[MAX_MSI];
212 uint32_t max_irq;
213 uint32_t irq_ipi0;
214 uint32_t irq_tim0;
215 uint32_t irq_msi;
216} OpenPICState;
217
218static inline void IRQ_setbit(IRQQueue * q, int n_IRQ)
219{
220 set_bit(n_IRQ, q->queue);
221}
222
223static inline void IRQ_resetbit(IRQQueue * q, int n_IRQ)
224{
225 clear_bit(n_IRQ, q->queue);
226}
227
228static inline int IRQ_testbit(IRQQueue * q, int n_IRQ)
229{
230 return test_bit(n_IRQ, q->queue);
231}
232
233static void IRQ_check(OpenPICState * opp, IRQQueue * q)
234{
235 int irq = -1;
236 int next = -1;
237 int priority = -1;
238
239 for (;;) {
240 irq = find_next_bit(q->queue, opp->max_irq, irq + 1);
241 if (irq == opp->max_irq) {
242 break;
243 }
244
245 DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
246 irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
247
248 if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
249 next = irq;
250 priority = IVPR_PRIORITY(opp->src[irq].ivpr);
251 }
252 }
253
254 q->next = next;
255 q->priority = priority;
256}
257
258static int IRQ_get_next(OpenPICState * opp, IRQQueue * q)
259{
260 /* XXX: optimize */
261 IRQ_check(opp, q);
262
263 return q->next;
264}
265
266static void IRQ_local_pipe(OpenPICState * opp, int n_CPU, int n_IRQ,
267 bool active, bool was_active)
268{
269 IRQDest *dst;
270 IRQSource *src;
271 int priority;
272
273 dst = &opp->dst[n_CPU];
274 src = &opp->src[n_IRQ];
275
276 DPRINTF("%s: IRQ %d active %d was %d\n",
277 __func__, n_IRQ, active, was_active);
278
279 if (src->output != OPENPIC_OUTPUT_INT) {
280 DPRINTF("%s: output %d irq %d active %d was %d count %d\n",
281 __func__, src->output, n_IRQ, active, was_active,
282 dst->outputs_active[src->output]);
283
284 /* On Freescale MPIC, critical interrupts ignore priority,
285 * IACK, EOI, etc. Before MPIC v4.1 they also ignore
286 * masking.
287 */
288 if (active) {
289 if (!was_active
290 && dst->outputs_active[src->output]++ == 0) {
291 DPRINTF
292 ("%s: Raise OpenPIC output %d cpu %d irq %d\n",
293 __func__, src->output, n_CPU, n_IRQ);
294 qemu_irq_raise(dst->irqs[src->output]);
295 }
296 } else {
297 if (was_active
298 && --dst->outputs_active[src->output] == 0) {
299 DPRINTF
300 ("%s: Lower OpenPIC output %d cpu %d irq %d\n",
301 __func__, src->output, n_CPU, n_IRQ);
302 qemu_irq_lower(dst->irqs[src->output]);
303 }
304 }
305
306 return;
307 }
308
309 priority = IVPR_PRIORITY(src->ivpr);
310
311 /* Even if the interrupt doesn't have enough priority,
312 * it is still raised, in case ctpr is lowered later.
313 */
314 if (active) {
315 IRQ_setbit(&dst->raised, n_IRQ);
316 } else {
317 IRQ_resetbit(&dst->raised, n_IRQ);
318 }
319
320 IRQ_check(opp, &dst->raised);
321
322 if (active && priority <= dst->ctpr) {
323 DPRINTF
324 ("%s: IRQ %d priority %d too low for ctpr %d on CPU %d\n",
325 __func__, n_IRQ, priority, dst->ctpr, n_CPU);
326 active = 0;
327 }
328
329 if (active) {
330 if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
331 priority <= dst->servicing.priority) {
332 DPRINTF
333 ("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
334 __func__, n_IRQ, dst->servicing.next, n_CPU);
335 } else {
336 DPRINTF
337 ("%s: Raise OpenPIC INT output cpu %d irq %d/%d\n",
338 __func__, n_CPU, n_IRQ, dst->raised.next);
339 qemu_irq_raise(opp->dst[n_CPU].
340 irqs[OPENPIC_OUTPUT_INT]);
341 }
342 } else {
343 IRQ_get_next(opp, &dst->servicing);
344 if (dst->raised.priority > dst->ctpr &&
345 dst->raised.priority > dst->servicing.priority) {
346 DPRINTF
347 ("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU %d\n",
348 __func__, n_IRQ, dst->raised.next,
349 dst->raised.priority, dst->ctpr,
350 dst->servicing.priority, n_CPU);
351 /* IRQ line stays asserted */
352 } else {
353 DPRINTF
354 ("%s: IRQ %d inactive, current prio %d/%d, CPU %d\n",
355 __func__, n_IRQ, dst->ctpr,
356 dst->servicing.priority, n_CPU);
357 qemu_irq_lower(opp->dst[n_CPU].
358 irqs[OPENPIC_OUTPUT_INT]);
359 }
360 }
361}
362
363/* update pic state because registers for n_IRQ have changed value */
364static void openpic_update_irq(OpenPICState * opp, int n_IRQ)
365{
366 IRQSource *src;
367 bool active, was_active;
368 int i;
369
370 src = &opp->src[n_IRQ];
371 active = src->pending;
372
373 if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
374 /* Interrupt source is disabled */
375 DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
376 active = false;
377 }
378
379 was_active = ! !(src->ivpr & IVPR_ACTIVITY_MASK);
380
381 /*
382 * We don't have a similar check for already-active because
383 * ctpr may have changed and we need to withdraw the interrupt.
384 */
385 if (!active && !was_active) {
386 DPRINTF("%s: IRQ %d is already inactive\n", __func__, n_IRQ);
387 return;
388 }
389
390 if (active) {
391 src->ivpr |= IVPR_ACTIVITY_MASK;
392 } else {
393 src->ivpr &= ~IVPR_ACTIVITY_MASK;
394 }
395
396 if (src->destmask == 0) {
397 /* No target */
398 DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
399 return;
400 }
401
402 if (src->destmask == (1 << src->last_cpu)) {
403 /* Only one CPU is allowed to receive this IRQ */
404 IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active);
405 } else if (!(src->ivpr & IVPR_MODE_MASK)) {
406 /* Directed delivery mode */
407 for (i = 0; i < opp->nb_cpus; i++) {
408 if (src->destmask & (1 << i)) {
409 IRQ_local_pipe(opp, i, n_IRQ, active,
410 was_active);
411 }
412 }
413 } else {
414 /* Distributed delivery mode */
415 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
416 if (i == opp->nb_cpus) {
417 i = 0;
418 }
419 if (src->destmask & (1 << i)) {
420 IRQ_local_pipe(opp, i, n_IRQ, active,
421 was_active);
422 src->last_cpu = i;
423 break;
424 }
425 }
426 }
427}
428
429static void openpic_set_irq(void *opaque, int n_IRQ, int level)
430{
431 OpenPICState *opp = opaque;
432 IRQSource *src;
433
434 if (n_IRQ >= MAX_IRQ) {
435 fprintf(stderr, "%s: IRQ %d out of range\n", __func__, n_IRQ);
436 abort();
437 }
438
439 src = &opp->src[n_IRQ];
440 DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
441 n_IRQ, level, src->ivpr);
442 if (src->level) {
443 /* level-sensitive irq */
444 src->pending = level;
445 openpic_update_irq(opp, n_IRQ);
446 } else {
447 /* edge-sensitive irq */
448 if (level) {
449 src->pending = 1;
450 openpic_update_irq(opp, n_IRQ);
451 }
452
453 if (src->output != OPENPIC_OUTPUT_INT) {
454 /* Edge-triggered interrupts shouldn't be used
455 * with non-INT delivery, but just in case,
456 * try to make it do something sane rather than
457 * cause an interrupt storm. This is close to
458 * what you'd probably see happen in real hardware.
459 */
460 src->pending = 0;
461 openpic_update_irq(opp, n_IRQ);
462 }
463 }
464}
465
466static void openpic_reset(DeviceState * d)
467{
468 OpenPICState *opp = FROM_SYSBUS(typeof(*opp), SYS_BUS_DEVICE(d));
469 int i;
470
471 opp->gcr = GCR_RESET;
472 /* Initialise controller registers */
473 opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
474 ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
475 (opp->vid << FRR_VID_SHIFT);
476
477 opp->pir = 0;
478 opp->spve = -1 & opp->vector_mask;
479 opp->tfrr = opp->tfrr_reset;
480 /* Initialise IRQ sources */
481 for (i = 0; i < opp->max_irq; i++) {
482 opp->src[i].ivpr = opp->ivpr_reset;
483 opp->src[i].idr = opp->idr_reset;
484
485 switch (opp->src[i].type) {
486 case IRQ_TYPE_NORMAL:
487 opp->src[i].level =
488 ! !(opp->ivpr_reset & IVPR_SENSE_MASK);
489 break;
490
491 case IRQ_TYPE_FSLINT:
492 opp->src[i].ivpr |= IVPR_POLARITY_MASK;
493 break;
494
495 case IRQ_TYPE_FSLSPECIAL:
496 break;
497 }
498 }
499 /* Initialise IRQ destinations */
500 for (i = 0; i < MAX_CPU; i++) {
501 opp->dst[i].ctpr = 15;
502 memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
503 opp->dst[i].raised.next = -1;
504 memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
505 opp->dst[i].servicing.next = -1;
506 }
507 /* Initialise timers */
508 for (i = 0; i < MAX_TMR; i++) {
509 opp->timers[i].tccr = 0;
510 opp->timers[i].tbcr = TBCR_CI;
511 }
512 /* Go out of RESET state */
513 opp->gcr = 0;
514}
515
516static inline uint32_t read_IRQreg_idr(OpenPICState * opp, int n_IRQ)
517{
518 return opp->src[n_IRQ].idr;
519}
520
521static inline uint32_t read_IRQreg_ilr(OpenPICState * opp, int n_IRQ)
522{
523 if (opp->flags & OPENPIC_FLAG_ILR) {
524 return output_to_inttgt(opp->src[n_IRQ].output);
525 }
526
527 return 0xffffffff;
528}
529
530static inline uint32_t read_IRQreg_ivpr(OpenPICState * opp, int n_IRQ)
531{
532 return opp->src[n_IRQ].ivpr;
533}
534
535static inline void write_IRQreg_idr(OpenPICState * opp, int n_IRQ, uint32_t val)
536{
537 IRQSource *src = &opp->src[n_IRQ];
538 uint32_t normal_mask = (1UL << opp->nb_cpus) - 1;
539 uint32_t crit_mask = 0;
540 uint32_t mask = normal_mask;
541 int crit_shift = IDR_EP_SHIFT - opp->nb_cpus;
542 int i;
543
544 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
545 crit_mask = mask << crit_shift;
546 mask |= crit_mask | IDR_EP;
547 }
548
549 src->idr = val & mask;
550 DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, src->idr);
551
552 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
553 if (src->idr & crit_mask) {
554 if (src->idr & normal_mask) {
555 DPRINTF
556 ("%s: IRQ configured for multiple output types, using "
557 "critical\n", __func__);
558 }
559
560 src->output = OPENPIC_OUTPUT_CINT;
561 src->nomask = true;
562 src->destmask = 0;
563
564 for (i = 0; i < opp->nb_cpus; i++) {
565 int n_ci = IDR_CI0_SHIFT - i;
566
567 if (src->idr & (1UL << n_ci)) {
568 src->destmask |= 1UL << i;
569 }
570 }
571 } else {
572 src->output = OPENPIC_OUTPUT_INT;
573 src->nomask = false;
574 src->destmask = src->idr & normal_mask;
575 }
576 } else {
577 src->destmask = src->idr;
578 }
579}
580
581static inline void write_IRQreg_ilr(OpenPICState * opp, int n_IRQ, uint32_t val)
582{
583 if (opp->flags & OPENPIC_FLAG_ILR) {
584 IRQSource *src = &opp->src[n_IRQ];
585
586 src->output = inttgt_to_output(val & ILR_INTTGT_MASK);
587 DPRINTF("Set ILR %d to 0x%08x, output %d\n", n_IRQ, src->idr,
588 src->output);
589
590 /* TODO: on MPIC v4.0 only, set nomask for non-INT */
591 }
592}
593
594static inline void write_IRQreg_ivpr(OpenPICState * opp, int n_IRQ,
595 uint32_t val)
596{
597 uint32_t mask;
598
599 /* NOTE when implementing newer FSL MPIC models: starting with v4.0,
600 * the polarity bit is read-only on internal interrupts.
601 */
602 mask = IVPR_MASK_MASK | IVPR_PRIORITY_MASK | IVPR_SENSE_MASK |
603 IVPR_POLARITY_MASK | opp->vector_mask;
604
605 /* ACTIVITY bit is read-only */
606 opp->src[n_IRQ].ivpr =
607 (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) | (val & mask);
608
609 /* For FSL internal interrupts, The sense bit is reserved and zero,
610 * and the interrupt is always level-triggered. Timers and IPIs
611 * have no sense or polarity bits, and are edge-triggered.
612 */
613 switch (opp->src[n_IRQ].type) {
614 case IRQ_TYPE_NORMAL:
615 opp->src[n_IRQ].level =
616 ! !(opp->src[n_IRQ].ivpr & IVPR_SENSE_MASK);
617 break;
618
619 case IRQ_TYPE_FSLINT:
620 opp->src[n_IRQ].ivpr &= ~IVPR_SENSE_MASK;
621 break;
622
623 case IRQ_TYPE_FSLSPECIAL:
624 opp->src[n_IRQ].ivpr &= ~(IVPR_POLARITY_MASK | IVPR_SENSE_MASK);
625 break;
626 }
627
628 openpic_update_irq(opp, n_IRQ);
629 DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
630 opp->src[n_IRQ].ivpr);
631}
632
633static void openpic_gcr_write(OpenPICState * opp, uint64_t val)
634{
635 bool mpic_proxy = false;
636
637 if (val & GCR_RESET) {
638 openpic_reset(&opp->busdev.qdev);
639 return;
640 }
641
642 opp->gcr &= ~opp->mpic_mode_mask;
643 opp->gcr |= val & opp->mpic_mode_mask;
644
645 /* Set external proxy mode */
646 if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
647 mpic_proxy = true;
648 }
649
650 ppce500_set_mpic_proxy(mpic_proxy);
651}
652
653static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
654 unsigned len)
655{
656 OpenPICState *opp = opaque;
657 IRQDest *dst;
658 int idx;
659
660 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
661 __func__, addr, val);
662 if (addr & 0xF) {
663 return;
664 }
665 switch (addr) {
666 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
667 break;
668 case 0x40:
669 case 0x50:
670 case 0x60:
671 case 0x70:
672 case 0x80:
673 case 0x90:
674 case 0xA0:
675 case 0xB0:
676 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
677 break;
678 case 0x1000: /* FRR */
679 break;
680 case 0x1020: /* GCR */
681 openpic_gcr_write(opp, val);
682 break;
683 case 0x1080: /* VIR */
684 break;
685 case 0x1090: /* PIR */
686 for (idx = 0; idx < opp->nb_cpus; idx++) {
687 if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) {
688 DPRINTF
689 ("Raise OpenPIC RESET output for CPU %d\n",
690 idx);
691 dst = &opp->dst[idx];
692 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
693 } else if (!(val & (1 << idx))
694 && (opp->pir & (1 << idx))) {
695 DPRINTF
696 ("Lower OpenPIC RESET output for CPU %d\n",
697 idx);
698 dst = &opp->dst[idx];
699 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
700 }
701 }
702 opp->pir = val;
703 break;
704 case 0x10A0: /* IPI_IVPR */
705 case 0x10B0:
706 case 0x10C0:
707 case 0x10D0:
708 {
709 int idx;
710 idx = (addr - 0x10A0) >> 4;
711 write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val);
712 }
713 break;
714 case 0x10E0: /* SPVE */
715 opp->spve = val & opp->vector_mask;
716 break;
717 default:
718 break;
719 }
720}
721
722static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
723{
724 OpenPICState *opp = opaque;
725 uint32_t retval;
726
727 DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
728 retval = 0xFFFFFFFF;
729 if (addr & 0xF) {
730 return retval;
731 }
732 switch (addr) {
733 case 0x1000: /* FRR */
734 retval = opp->frr;
735 break;
736 case 0x1020: /* GCR */
737 retval = opp->gcr;
738 break;
739 case 0x1080: /* VIR */
740 retval = opp->vir;
741 break;
742 case 0x1090: /* PIR */
743 retval = 0x00000000;
744 break;
745 case 0x00: /* Block Revision Register1 (BRR1) */
746 retval = opp->brr1;
747 break;
748 case 0x40:
749 case 0x50:
750 case 0x60:
751 case 0x70:
752 case 0x80:
753 case 0x90:
754 case 0xA0:
755 case 0xB0:
756 retval =
757 openpic_cpu_read_internal(opp, addr, get_current_cpu());
758 break;
759 case 0x10A0: /* IPI_IVPR */
760 case 0x10B0:
761 case 0x10C0:
762 case 0x10D0:
763 {
764 int idx;
765 idx = (addr - 0x10A0) >> 4;
766 retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx);
767 }
768 break;
769 case 0x10E0: /* SPVE */
770 retval = opp->spve;
771 break;
772 default:
773 break;
774 }
775 DPRINTF("%s: => 0x%08x\n", __func__, retval);
776
777 return retval;
778}
779
780static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
781 unsigned len)
782{
783 OpenPICState *opp = opaque;
784 int idx;
785
786 addr += 0x10f0;
787
788 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
789 __func__, addr, val);
790 if (addr & 0xF) {
791 return;
792 }
793
794 if (addr == 0x10f0) {
795 /* TFRR */
796 opp->tfrr = val;
797 return;
798 }
799
800 idx = (addr >> 6) & 0x3;
801 addr = addr & 0x30;
802
803 switch (addr & 0x30) {
804 case 0x00: /* TCCR */
805 break;
806 case 0x10: /* TBCR */
807 if ((opp->timers[idx].tccr & TCCR_TOG) != 0 &&
808 (val & TBCR_CI) == 0 &&
809 (opp->timers[idx].tbcr & TBCR_CI) != 0) {
810 opp->timers[idx].tccr &= ~TCCR_TOG;
811 }
812 opp->timers[idx].tbcr = val;
813 break;
814 case 0x20: /* TVPR */
815 write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val);
816 break;
817 case 0x30: /* TDR */
818 write_IRQreg_idr(opp, opp->irq_tim0 + idx, val);
819 break;
820 }
821}
822
823static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
824{
825 OpenPICState *opp = opaque;
826 uint32_t retval = -1;
827 int idx;
828
829 DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
830 if (addr & 0xF) {
831 goto out;
832 }
833 idx = (addr >> 6) & 0x3;
834 if (addr == 0x0) {
835 /* TFRR */
836 retval = opp->tfrr;
837 goto out;
838 }
839 switch (addr & 0x30) {
840 case 0x00: /* TCCR */
841 retval = opp->timers[idx].tccr;
842 break;
843 case 0x10: /* TBCR */
844 retval = opp->timers[idx].tbcr;
845 break;
846 case 0x20: /* TIPV */
847 retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
848 break;
849 case 0x30: /* TIDE (TIDR) */
850 retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
851 break;
852 }
853
854out:
855 DPRINTF("%s: => 0x%08x\n", __func__, retval);
856
857 return retval;
858}
859
860static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
861 unsigned len)
862{
863 OpenPICState *opp = opaque;
864 int idx;
865
866 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
867 __func__, addr, val);
868
869 addr = addr & 0xffff;
870 idx = addr >> 5;
871
872 switch (addr & 0x1f) {
873 case 0x00:
874 write_IRQreg_ivpr(opp, idx, val);
875 break;
876 case 0x10:
877 write_IRQreg_idr(opp, idx, val);
878 break;
879 case 0x18:
880 write_IRQreg_ilr(opp, idx, val);
881 break;
882 }
883}
884
885static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
886{
887 OpenPICState *opp = opaque;
888 uint32_t retval;
889 int idx;
890
891 DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
892 retval = 0xFFFFFFFF;
893
894 addr = addr & 0xffff;
895 idx = addr >> 5;
896
897 switch (addr & 0x1f) {
898 case 0x00:
899 retval = read_IRQreg_ivpr(opp, idx);
900 break;
901 case 0x10:
902 retval = read_IRQreg_idr(opp, idx);
903 break;
904 case 0x18:
905 retval = read_IRQreg_ilr(opp, idx);
906 break;
907 }
908
909 DPRINTF("%s: => 0x%08x\n", __func__, retval);
910 return retval;
911}
912
913static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
914 unsigned size)
915{
916 OpenPICState *opp = opaque;
917 int idx = opp->irq_msi;
918 int srs, ibs;
919
920 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n",
921 __func__, addr, val);
922 if (addr & 0xF) {
923 return;
924 }
925
926 switch (addr) {
927 case MSIIR_OFFSET:
928 srs = val >> MSIIR_SRS_SHIFT;
929 idx += srs;
930 ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT;
931 opp->msi[srs].msir |= 1 << ibs;
932 openpic_set_irq(opp, idx, 1);
933 break;
934 default:
935 /* most registers are read-only, thus ignored */
936 break;
937 }
938}
939
940static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
941{
942 OpenPICState *opp = opaque;
943 uint64_t r = 0;
944 int i, srs;
945
946 DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
947 if (addr & 0xF) {
948 return -1;
949 }
950
951 srs = addr >> 4;
952
953 switch (addr) {
954 case 0x00:
955 case 0x10:
956 case 0x20:
957 case 0x30:
958 case 0x40:
959 case 0x50:
960 case 0x60:
961 case 0x70: /* MSIRs */
962 r = opp->msi[srs].msir;
963 /* Clear on read */
964 opp->msi[srs].msir = 0;
965 openpic_set_irq(opp, opp->irq_msi + srs, 0);
966 break;
967 case 0x120: /* MSISR */
968 for (i = 0; i < MAX_MSI; i++) {
969 r |= (opp->msi[i].msir ? 1 : 0) << i;
970 }
971 break;
972 }
973
974 return r;
975}
976
977static uint64_t openpic_summary_read(void *opaque, hwaddr addr, unsigned size)
978{
979 uint64_t r = 0;
980
981 DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
982
983 /* TODO: EISR/EIMR */
984
985 return r;
986}
987
988static void openpic_summary_write(void *opaque, hwaddr addr, uint64_t val,
989 unsigned size)
990{
991 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n",
992 __func__, addr, val);
993
994 /* TODO: EISR/EIMR */
995}
996
997static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
998 uint32_t val, int idx)
999{
1000 OpenPICState *opp = opaque;
1001 IRQSource *src;
1002 IRQDest *dst;
1003 int s_IRQ, n_IRQ;
1004
1005 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x\n", __func__, idx,
1006 addr, val);
1007
1008 if (idx < 0) {
1009 return;
1010 }
1011
1012 if (addr & 0xF) {
1013 return;
1014 }
1015 dst = &opp->dst[idx];
1016 addr &= 0xFF0;
1017 switch (addr) {
1018 case 0x40: /* IPIDR */
1019 case 0x50:
1020 case 0x60:
1021 case 0x70:
1022 idx = (addr - 0x40) >> 4;
1023 /* we use IDE as mask which CPUs to deliver the IPI to still. */
1024 opp->src[opp->irq_ipi0 + idx].destmask |= val;
1025 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
1026 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
1027 break;
1028 case 0x80: /* CTPR */
1029 dst->ctpr = val & 0x0000000F;
1030
1031 DPRINTF("%s: set CPU %d ctpr to %d, raised %d servicing %d\n",
1032 __func__, idx, dst->ctpr, dst->raised.priority,
1033 dst->servicing.priority);
1034
1035 if (dst->raised.priority <= dst->ctpr) {
1036 DPRINTF
1037 ("%s: Lower OpenPIC INT output cpu %d due to ctpr\n",
1038 __func__, idx);
1039 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
1040 } else if (dst->raised.priority > dst->servicing.priority) {
1041 DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d\n",
1042 __func__, idx, dst->raised.next);
1043 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
1044 }
1045
1046 break;
1047 case 0x90: /* WHOAMI */
1048 /* Read-only register */
1049 break;
1050 case 0xA0: /* IACK */
1051 /* Read-only register */
1052 break;
1053 case 0xB0: /* EOI */
1054 DPRINTF("EOI\n");
1055 s_IRQ = IRQ_get_next(opp, &dst->servicing);
1056
1057 if (s_IRQ < 0) {
1058 DPRINTF("%s: EOI with no interrupt in service\n",
1059 __func__);
1060 break;
1061 }
1062
1063 IRQ_resetbit(&dst->servicing, s_IRQ);
1064 /* Set up next servicing IRQ */
1065 s_IRQ = IRQ_get_next(opp, &dst->servicing);
1066 /* Check queued interrupts. */
1067 n_IRQ = IRQ_get_next(opp, &dst->raised);
1068 src = &opp->src[n_IRQ];
1069 if (n_IRQ != -1 &&
1070 (s_IRQ == -1 ||
1071 IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
1072 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
1073 idx, n_IRQ);
1074 qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
1075 }
1076 break;
1077 default:
1078 break;
1079 }
1080}
1081
1082static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
1083 unsigned len)
1084{
1085 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
1086}
1087
1088static uint32_t openpic_iack(OpenPICState * opp, IRQDest * dst, int cpu)
1089{
1090 IRQSource *src;
1091 int retval, irq;
1092
1093 DPRINTF("Lower OpenPIC INT output\n");
1094 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
1095
1096 irq = IRQ_get_next(opp, &dst->raised);
1097 DPRINTF("IACK: irq=%d\n", irq);
1098
1099 if (irq == -1) {
1100 /* No more interrupt pending */
1101 return opp->spve;
1102 }
1103
1104 src = &opp->src[irq];
1105 if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
1106 !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
1107 fprintf(stderr, "%s: bad raised IRQ %d ctpr %d ivpr 0x%08x\n",
1108 __func__, irq, dst->ctpr, src->ivpr);
1109 openpic_update_irq(opp, irq);
1110 retval = opp->spve;
1111 } else {
1112 /* IRQ enter servicing state */
1113 IRQ_setbit(&dst->servicing, irq);
1114 retval = IVPR_VECTOR(opp, src->ivpr);
1115 }
1116
1117 if (!src->level) {
1118 /* edge-sensitive IRQ */
1119 src->ivpr &= ~IVPR_ACTIVITY_MASK;
1120 src->pending = 0;
1121 IRQ_resetbit(&dst->raised, irq);
1122 }
1123
1124 if ((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + MAX_IPI))) {
1125 src->destmask &= ~(1 << cpu);
1126 if (src->destmask && !src->level) {
1127 /* trigger on CPUs that didn't know about it yet */
1128 openpic_set_irq(opp, irq, 1);
1129 openpic_set_irq(opp, irq, 0);
1130 /* if all CPUs knew about it, set active bit again */
1131 src->ivpr |= IVPR_ACTIVITY_MASK;
1132 }
1133 }
1134
1135 return retval;
1136}
1137
1138static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, int idx)
1139{
1140 OpenPICState *opp = opaque;
1141 IRQDest *dst;
1142 uint32_t retval;
1143
1144 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
1145 retval = 0xFFFFFFFF;
1146
1147 if (idx < 0) {
1148 return retval;
1149 }
1150
1151 if (addr & 0xF) {
1152 return retval;
1153 }
1154 dst = &opp->dst[idx];
1155 addr &= 0xFF0;
1156 switch (addr) {
1157 case 0x80: /* CTPR */
1158 retval = dst->ctpr;
1159 break;
1160 case 0x90: /* WHOAMI */
1161 retval = idx;
1162 break;
1163 case 0xA0: /* IACK */
1164 retval = openpic_iack(opp, dst, idx);
1165 break;
1166 case 0xB0: /* EOI */
1167 retval = 0;
1168 break;
1169 default:
1170 break;
1171 }
1172 DPRINTF("%s: => 0x%08x\n", __func__, retval);
1173
1174 return retval;
1175}
1176
1177static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
1178{
1179 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
1180}
1181
Scott Woodb823f982013-04-12 14:08:43 +00001182static const MemoryRegionOps openpic_glb_ops_be = {
1183 .write = openpic_gbl_write,
1184 .read = openpic_gbl_read,
Scott Woodb823f982013-04-12 14:08:43 +00001185};
1186
1187static const MemoryRegionOps openpic_tmr_ops_be = {
1188 .write = openpic_tmr_write,
1189 .read = openpic_tmr_read,
Scott Woodb823f982013-04-12 14:08:43 +00001190};
1191
1192static const MemoryRegionOps openpic_cpu_ops_be = {
1193 .write = openpic_cpu_write,
1194 .read = openpic_cpu_read,
Scott Woodb823f982013-04-12 14:08:43 +00001195};
1196
1197static const MemoryRegionOps openpic_src_ops_be = {
1198 .write = openpic_src_write,
1199 .read = openpic_src_read,
Scott Woodb823f982013-04-12 14:08:43 +00001200};
1201
1202static const MemoryRegionOps openpic_msi_ops_be = {
1203 .read = openpic_msi_read,
1204 .write = openpic_msi_write,
Scott Woodb823f982013-04-12 14:08:43 +00001205};
1206
1207static const MemoryRegionOps openpic_summary_ops_be = {
1208 .read = openpic_summary_read,
1209 .write = openpic_summary_write,
Scott Woodb823f982013-04-12 14:08:43 +00001210};
1211
Scott Woodb823f982013-04-12 14:08:43 +00001212typedef struct MemReg {
1213 const char *name;
1214 MemoryRegionOps const *ops;
1215 hwaddr start_addr;
1216 ram_addr_t size;
1217} MemReg;
1218
1219static void fsl_common_init(OpenPICState * opp)
1220{
1221 int i;
1222 int virq = MAX_SRC;
1223
1224 opp->vid = VID_REVISION_1_2;
1225 opp->vir = VIR_GENERIC;
1226 opp->vector_mask = 0xFFFF;
1227 opp->tfrr_reset = 0;
1228 opp->ivpr_reset = IVPR_MASK_MASK;
1229 opp->idr_reset = 1 << 0;
1230 opp->max_irq = MAX_IRQ;
1231
1232 opp->irq_ipi0 = virq;
1233 virq += MAX_IPI;
1234 opp->irq_tim0 = virq;
1235 virq += MAX_TMR;
1236
1237 assert(virq <= MAX_IRQ);
1238
1239 opp->irq_msi = 224;
1240
1241 msi_supported = true;
1242 for (i = 0; i < opp->fsl->max_ext; i++) {
1243 opp->src[i].level = false;
1244 }
1245
1246 /* Internal interrupts, including message and MSI */
1247 for (i = 16; i < MAX_SRC; i++) {
1248 opp->src[i].type = IRQ_TYPE_FSLINT;
1249 opp->src[i].level = true;
1250 }
1251
1252 /* timers and IPIs */
1253 for (i = MAX_SRC; i < virq; i++) {
1254 opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
1255 opp->src[i].level = false;
1256 }
1257}
1258
1259static void map_list(OpenPICState * opp, const MemReg * list, int *count)
1260{
1261 while (list->name) {
1262 assert(*count < ARRAY_SIZE(opp->sub_io_mem));
1263
1264 memory_region_init_io(&opp->sub_io_mem[*count], list->ops, opp,
1265 list->name, list->size);
1266
1267 memory_region_add_subregion(&opp->mem, list->start_addr,
1268 &opp->sub_io_mem[*count]);
1269
1270 (*count)++;
1271 list++;
1272 }
1273}
1274
1275static int openpic_init(SysBusDevice * dev)
1276{
1277 OpenPICState *opp = FROM_SYSBUS(typeof(*opp), dev);
1278 int i, j;
1279 int list_count = 0;
1280 static const MemReg list_le[] = {
1281 {"glb", &openpic_glb_ops_le,
1282 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1283 {"tmr", &openpic_tmr_ops_le,
1284 OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1285 {"src", &openpic_src_ops_le,
1286 OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1287 {"cpu", &openpic_cpu_ops_le,
1288 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1289 {NULL}
1290 };
1291 static const MemReg list_be[] = {
1292 {"glb", &openpic_glb_ops_be,
1293 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1294 {"tmr", &openpic_tmr_ops_be,
1295 OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1296 {"src", &openpic_src_ops_be,
1297 OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1298 {"cpu", &openpic_cpu_ops_be,
1299 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1300 {NULL}
1301 };
1302 static const MemReg list_fsl[] = {
1303 {"msi", &openpic_msi_ops_be,
1304 OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1305 {"summary", &openpic_summary_ops_be,
1306 OPENPIC_SUMMARY_REG_START, OPENPIC_SUMMARY_REG_SIZE},
1307 {NULL}
1308 };
1309
1310 memory_region_init(&opp->mem, "openpic", 0x40000);
1311
1312 switch (opp->model) {
1313 case OPENPIC_MODEL_FSL_MPIC_20:
1314 default:
1315 opp->fsl = &fsl_mpic_20;
1316 opp->brr1 = 0x00400200;
1317 opp->flags |= OPENPIC_FLAG_IDR_CRIT;
1318 opp->nb_irqs = 80;
1319 opp->mpic_mode_mask = GCR_MODE_MIXED;
1320
1321 fsl_common_init(opp);
1322 map_list(opp, list_be, &list_count);
1323 map_list(opp, list_fsl, &list_count);
1324
1325 break;
1326
1327 case OPENPIC_MODEL_FSL_MPIC_42:
1328 opp->fsl = &fsl_mpic_42;
1329 opp->brr1 = 0x00400402;
1330 opp->flags |= OPENPIC_FLAG_ILR;
1331 opp->nb_irqs = 196;
1332 opp->mpic_mode_mask = GCR_MODE_PROXY;
1333
1334 fsl_common_init(opp);
1335 map_list(opp, list_be, &list_count);
1336 map_list(opp, list_fsl, &list_count);
1337
1338 break;
Scott Woodb823f982013-04-12 14:08:43 +00001339 }
1340
Scott Woodb823f982013-04-12 14:08:43 +00001341 return 0;
1342}