1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include "qemu/osdep.h"
38#include "hw/irq.h"
39#include "hw/ppc/mac.h"
40#include "hw/pci/pci.h"
41#include "hw/ppc/openpic.h"
42#include "hw/ppc/ppc_e500.h"
43#include "hw/qdev-properties.h"
44#include "hw/sysbus.h"
45#include "migration/vmstate.h"
46#include "hw/pci/msi.h"
47#include "qapi/error.h"
48#include "qemu/bitops.h"
49#include "qapi/qmp/qerror.h"
50#include "qemu/module.h"
51#include "qemu/timer.h"
52#include "qemu/error-report.h"
53
54
55
56#ifdef DEBUG_OPENPIC
57static const int debug_openpic = 1;
58#else
59static const int debug_openpic = 0;
60#endif
61
62static int get_current_cpu(void);
63#define DPRINTF(fmt, ...) do { \
64 if (debug_openpic) { \
65 info_report("Core%d: " fmt, get_current_cpu(), ## __VA_ARGS__); \
66 } \
67 } while (0)
68
69
70#define OPENPIC_FLAG_IDR_CRIT (1 << 0)
71#define OPENPIC_FLAG_ILR (2 << 0)
72
73
74#define OPENPIC_GLB_REG_START 0x0
75#define OPENPIC_GLB_REG_SIZE 0x10F0
76#define OPENPIC_TMR_REG_START 0x10F0
77#define OPENPIC_TMR_REG_SIZE 0x220
78#define OPENPIC_MSI_REG_START 0x1600
79#define OPENPIC_MSI_REG_SIZE 0x200
80#define OPENPIC_SUMMARY_REG_START 0x3800
81#define OPENPIC_SUMMARY_REG_SIZE 0x800
82#define OPENPIC_SRC_REG_START 0x10000
83#define OPENPIC_SRC_REG_SIZE (OPENPIC_MAX_SRC * 0x20)
84#define OPENPIC_CPU_REG_START 0x20000
85#define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
86
87static FslMpicInfo fsl_mpic_20 = {
88 .max_ext = 12,
89};
90
91static FslMpicInfo fsl_mpic_42 = {
92 .max_ext = 12,
93};
94
95#define FRR_NIRQ_SHIFT 16
96#define FRR_NCPU_SHIFT 8
97#define FRR_VID_SHIFT 0
98
99#define VID_REVISION_1_2 2
100#define VID_REVISION_1_3 3
101
102#define VIR_GENERIC 0x00000000
103#define VIR_MPIC2A 0x00004614
104
105#define GCR_RESET 0x80000000
106#define GCR_MODE_PASS 0x00000000
107#define GCR_MODE_MIXED 0x20000000
108#define GCR_MODE_PROXY 0x60000000
109
110#define TBCR_CI 0x80000000
111#define TCCR_TOG 0x80000000
112
113#define IDR_EP_SHIFT 31
114#define IDR_EP_MASK (1U << IDR_EP_SHIFT)
115#define IDR_CI0_SHIFT 30
116#define IDR_CI1_SHIFT 29
117#define IDR_P1_SHIFT 1
118#define IDR_P0_SHIFT 0
119
120#define ILR_INTTGT_MASK 0x000000ff
121#define ILR_INTTGT_INT 0x00
122#define ILR_INTTGT_CINT 0x01
123#define ILR_INTTGT_MCP 0x02
124
125
126
127
128
129
130static const int inttgt_output[][2] = {
131 { ILR_INTTGT_INT, OPENPIC_OUTPUT_INT },
132 { ILR_INTTGT_CINT, OPENPIC_OUTPUT_CINT },
133 { ILR_INTTGT_MCP, OPENPIC_OUTPUT_MCK },
134};
135
136static int inttgt_to_output(int inttgt)
137{
138 int i;
139
140 for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
141 if (inttgt_output[i][0] == inttgt) {
142 return inttgt_output[i][1];
143 }
144 }
145
146 error_report("%s: unsupported inttgt %d", __func__, inttgt);
147 return OPENPIC_OUTPUT_INT;
148}
149
150static int output_to_inttgt(int output)
151{
152 int i;
153
154 for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
155 if (inttgt_output[i][1] == output) {
156 return inttgt_output[i][0];
157 }
158 }
159
160 abort();
161}
162
163#define MSIIR_OFFSET 0x140
164#define MSIIR_SRS_SHIFT 29
165#define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT)
166#define MSIIR_IBS_SHIFT 24
167#define MSIIR_IBS_MASK (0x1f << MSIIR_IBS_SHIFT)
168
169static int get_current_cpu(void)
170{
171 if (!current_cpu) {
172 return -1;
173 }
174
175 return current_cpu->cpu_index;
176}
177
178static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
179 int idx);
180static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
181 uint32_t val, int idx);
182static void openpic_reset(DeviceState *d);
183
184
185
186
187
188#define OPENPIC_TIMER_FREQ_MHZ 25
189#define OPENPIC_TIMER_NS_PER_TICK (1000 / OPENPIC_TIMER_FREQ_MHZ)
190static inline uint64_t ns_to_ticks(uint64_t ns)
191{
192 return ns / OPENPIC_TIMER_NS_PER_TICK;
193}
194static inline uint64_t ticks_to_ns(uint64_t ticks)
195{
196 return ticks * OPENPIC_TIMER_NS_PER_TICK;
197}
198
199static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
200{
201 set_bit(n_IRQ, q->queue);
202}
203
204static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
205{
206 clear_bit(n_IRQ, q->queue);
207}
208
209static void IRQ_check(OpenPICState *opp, IRQQueue *q)
210{
211 int irq = -1;
212 int next = -1;
213 int priority = -1;
214
215 for (;;) {
216 irq = find_next_bit(q->queue, opp->max_irq, irq + 1);
217 if (irq == opp->max_irq) {
218 break;
219 }
220
221 DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d",
222 irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
223
224 if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
225 next = irq;
226 priority = IVPR_PRIORITY(opp->src[irq].ivpr);
227 }
228 }
229
230 q->next = next;
231 q->priority = priority;
232}
233
234static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
235{
236
237 IRQ_check(opp, q);
238
239 return q->next;
240}
241
242static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ,
243 bool active, bool was_active)
244{
245 IRQDest *dst;
246 IRQSource *src;
247 int priority;
248
249 dst = &opp->dst[n_CPU];
250 src = &opp->src[n_IRQ];
251
252 DPRINTF("%s: IRQ %d active %d was %d",
253 __func__, n_IRQ, active, was_active);
254
255 if (src->output != OPENPIC_OUTPUT_INT) {
256 DPRINTF("%s: output %d irq %d active %d was %d count %d",
257 __func__, src->output, n_IRQ, active, was_active,
258 dst->outputs_active[src->output]);
259
260
261
262
263
264 if (active) {
265 if (!was_active && dst->outputs_active[src->output]++ == 0) {
266 DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d",
267 __func__, src->output, n_CPU, n_IRQ);
268 qemu_irq_raise(dst->irqs[src->output]);
269 }
270 } else {
271 if (was_active && --dst->outputs_active[src->output] == 0) {
272 DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d",
273 __func__, src->output, n_CPU, n_IRQ);
274 qemu_irq_lower(dst->irqs[src->output]);
275 }
276 }
277
278 return;
279 }
280
281 priority = IVPR_PRIORITY(src->ivpr);
282
283
284
285
286 if (active) {
287 IRQ_setbit(&dst->raised, n_IRQ);
288 } else {
289 IRQ_resetbit(&dst->raised, n_IRQ);
290 }
291
292 IRQ_check(opp, &dst->raised);
293
294 if (active && priority <= dst->ctpr) {
295 DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d",
296 __func__, n_IRQ, priority, dst->ctpr, n_CPU);
297 active = 0;
298 }
299
300 if (active) {
301 if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
302 priority <= dst->servicing.priority) {
303 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d",
304 __func__, n_IRQ, dst->servicing.next, n_CPU);
305 } else {
306 DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d",
307 __func__, n_CPU, n_IRQ, dst->raised.next);
308 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
309 }
310 } else {
311 IRQ_get_next(opp, &dst->servicing);
312 if (dst->raised.priority > dst->ctpr &&
313 dst->raised.priority > dst->servicing.priority) {
314 DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU %d",
315 __func__, n_IRQ, dst->raised.next, dst->raised.priority,
316 dst->ctpr, dst->servicing.priority, n_CPU);
317
318 } else {
319 DPRINTF("%s: IRQ %d inactive, current prio %d/%d, CPU %d",
320 __func__, n_IRQ, dst->ctpr, dst->servicing.priority, n_CPU);
321 qemu_irq_lower(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
322 }
323 }
324}
325
326
327static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
328{
329 IRQSource *src;
330 bool active, was_active;
331 int i;
332
333 src = &opp->src[n_IRQ];
334 active = src->pending;
335
336 if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
337
338 DPRINTF("%s: IRQ %d is disabled", __func__, n_IRQ);
339 active = false;
340 }
341
342 was_active = !!(src->ivpr & IVPR_ACTIVITY_MASK);
343
344
345
346
347
348 if (!active && !was_active) {
349 DPRINTF("%s: IRQ %d is already inactive", __func__, n_IRQ);
350 return;
351 }
352
353 if (active) {
354 src->ivpr |= IVPR_ACTIVITY_MASK;
355 } else {
356 src->ivpr &= ~IVPR_ACTIVITY_MASK;
357 }
358
359 if (src->destmask == 0) {
360
361 DPRINTF("%s: IRQ %d has no target", __func__, n_IRQ);
362 return;
363 }
364
365 if (src->destmask == (1 << src->last_cpu)) {
366
367 IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active);
368 } else if (!(src->ivpr & IVPR_MODE_MASK)) {
369
370 for (i = 0; i < opp->nb_cpus; i++) {
371 if (src->destmask & (1 << i)) {
372 IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
373 }
374 }
375 } else {
376
377 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
378 if (i == opp->nb_cpus) {
379 i = 0;
380 }
381 if (src->destmask & (1 << i)) {
382 IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
383 src->last_cpu = i;
384 break;
385 }
386 }
387 }
388}
389
390static void openpic_set_irq(void *opaque, int n_IRQ, int level)
391{
392 OpenPICState *opp = opaque;
393 IRQSource *src;
394
395 if (n_IRQ >= OPENPIC_MAX_IRQ) {
396 error_report("%s: IRQ %d out of range", __func__, n_IRQ);
397 abort();
398 }
399
400 src = &opp->src[n_IRQ];
401 DPRINTF("openpic: set irq %d = %d ivpr=0x%08x",
402 n_IRQ, level, src->ivpr);
403 if (src->level) {
404
405 src->pending = level;
406 openpic_update_irq(opp, n_IRQ);
407 } else {
408
409 if (level) {
410 src->pending = 1;
411 openpic_update_irq(opp, n_IRQ);
412 }
413
414 if (src->output != OPENPIC_OUTPUT_INT) {
415
416
417
418
419
420
421 src->pending = 0;
422 openpic_update_irq(opp, n_IRQ);
423 }
424 }
425}
426
427static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ)
428{
429 return opp->src[n_IRQ].idr;
430}
431
432static inline uint32_t read_IRQreg_ilr(OpenPICState *opp, int n_IRQ)
433{
434 if (opp->flags & OPENPIC_FLAG_ILR) {
435 return output_to_inttgt(opp->src[n_IRQ].output);
436 }
437
438 return 0xffffffff;
439}
440
441static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
442{
443 return opp->src[n_IRQ].ivpr;
444}
445
446static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
447{
448 IRQSource *src = &opp->src[n_IRQ];
449 uint32_t normal_mask = (1UL << opp->nb_cpus) - 1;
450 uint32_t crit_mask = 0;
451 uint32_t mask = normal_mask;
452 int crit_shift = IDR_EP_SHIFT - opp->nb_cpus;
453 int i;
454
455 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
456 crit_mask = mask << crit_shift;
457 mask |= crit_mask | IDR_EP;
458 }
459
460 src->idr = val & mask;
461 DPRINTF("Set IDR %d to 0x%08x", n_IRQ, src->idr);
462
463 if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
464 if (src->idr & crit_mask) {
465 if (src->idr & normal_mask) {
466 DPRINTF("%s: IRQ configured for multiple output types, using "
467 "critical", __func__);
468 }
469
470 src->output = OPENPIC_OUTPUT_CINT;
471 src->nomask = true;
472 src->destmask = 0;
473
474 for (i = 0; i < opp->nb_cpus; i++) {
475 int n_ci = IDR_CI0_SHIFT - i;
476
477 if (src->idr & (1UL << n_ci)) {
478 src->destmask |= 1UL << i;
479 }
480 }
481 } else {
482 src->output = OPENPIC_OUTPUT_INT;
483 src->nomask = false;
484 src->destmask = src->idr & normal_mask;
485 }
486 } else {
487 src->destmask = src->idr;
488 }
489}
490
491static inline void write_IRQreg_ilr(OpenPICState *opp, int n_IRQ, uint32_t val)
492{
493 if (opp->flags & OPENPIC_FLAG_ILR) {
494 IRQSource *src = &opp->src[n_IRQ];
495
496 src->output = inttgt_to_output(val & ILR_INTTGT_MASK);
497 DPRINTF("Set ILR %d to 0x%08x, output %d", n_IRQ, src->idr,
498 src->output);
499
500
501 }
502}
503
504static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
505{
506 uint32_t mask;
507
508
509
510
511 mask = IVPR_MASK_MASK | IVPR_PRIORITY_MASK | IVPR_SENSE_MASK |
512 IVPR_POLARITY_MASK | opp->vector_mask;
513
514
515 opp->src[n_IRQ].ivpr =
516 (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) | (val & mask);
517
518
519
520
521
522 switch (opp->src[n_IRQ].type) {
523 case IRQ_TYPE_NORMAL:
524 opp->src[n_IRQ].level = !!(opp->src[n_IRQ].ivpr & IVPR_SENSE_MASK);
525 break;
526
527 case IRQ_TYPE_FSLINT:
528 opp->src[n_IRQ].ivpr &= ~IVPR_SENSE_MASK;
529 break;
530
531 case IRQ_TYPE_FSLSPECIAL:
532 opp->src[n_IRQ].ivpr &= ~(IVPR_POLARITY_MASK | IVPR_SENSE_MASK);
533 break;
534 }
535
536 openpic_update_irq(opp, n_IRQ);
537 DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x", n_IRQ, val,
538 opp->src[n_IRQ].ivpr);
539}
540
541static void openpic_gcr_write(OpenPICState *opp, uint64_t val)
542{
543 bool mpic_proxy = false;
544
545 if (val & GCR_RESET) {
546 openpic_reset(DEVICE(opp));
547 return;
548 }
549
550 opp->gcr &= ~opp->mpic_mode_mask;
551 opp->gcr |= val & opp->mpic_mode_mask;
552
553
554 if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
555 mpic_proxy = true;
556 }
557
558 ppce500_set_mpic_proxy(mpic_proxy);
559}
560
561static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
562 unsigned len)
563{
564 OpenPICState *opp = opaque;
565 IRQDest *dst;
566 int idx;
567
568 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64,
569 __func__, addr, val);
570 if (addr & 0xF) {
571 return;
572 }
573 switch (addr) {
574 case 0x00:
575 break;
576 case 0x40:
577 case 0x50:
578 case 0x60:
579 case 0x70:
580 case 0x80:
581 case 0x90:
582 case 0xA0:
583 case 0xB0:
584 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
585 break;
586 case 0x1000:
587 break;
588 case 0x1020:
589 openpic_gcr_write(opp, val);
590 break;
591 case 0x1080:
592 break;
593 case 0x1090:
594 for (idx = 0; idx < opp->nb_cpus; idx++) {
595 if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) {
596 DPRINTF("Raise OpenPIC RESET output for CPU %d", idx);
597 dst = &opp->dst[idx];
598 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
599 } else if (!(val & (1 << idx)) && (opp->pir & (1 << idx))) {
600 DPRINTF("Lower OpenPIC RESET output for CPU %d", idx);
601 dst = &opp->dst[idx];
602 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
603 }
604 }
605 opp->pir = val;
606 break;
607 case 0x10A0:
608 case 0x10B0:
609 case 0x10C0:
610 case 0x10D0:
611 {
612 int idx;
613 idx = (addr - 0x10A0) >> 4;
614 write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val);
615 }
616 break;
617 case 0x10E0:
618 opp->spve = val & opp->vector_mask;
619 break;
620 default:
621 break;
622 }
623}
624
625static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
626{
627 OpenPICState *opp = opaque;
628 uint32_t retval;
629
630 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
631 retval = 0xFFFFFFFF;
632 if (addr & 0xF) {
633 return retval;
634 }
635 switch (addr) {
636 case 0x1000:
637 retval = opp->frr;
638 break;
639 case 0x1020:
640 retval = opp->gcr;
641 break;
642 case 0x1080:
643 retval = opp->vir;
644 break;
645 case 0x1090:
646 retval = 0x00000000;
647 break;
648 case 0x00:
649 retval = opp->brr1;
650 break;
651 case 0x40:
652 case 0x50:
653 case 0x60:
654 case 0x70:
655 case 0x80:
656 case 0x90:
657 case 0xA0:
658 case 0xB0:
659 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
660 break;
661 case 0x10A0:
662 case 0x10B0:
663 case 0x10C0:
664 case 0x10D0:
665 {
666 int idx;
667 idx = (addr - 0x10A0) >> 4;
668 retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx);
669 }
670 break;
671 case 0x10E0:
672 retval = opp->spve;
673 break;
674 default:
675 break;
676 }
677 DPRINTF("%s: => 0x%08x", __func__, retval);
678
679 return retval;
680}
681
682static void openpic_tmr_set_tmr(OpenPICTimer *tmr, uint32_t val, bool enabled);
683
684static void qemu_timer_cb(void *opaque)
685{
686 OpenPICTimer *tmr = opaque;
687 OpenPICState *opp = tmr->opp;
688 uint32_t n_IRQ = tmr->n_IRQ;
689 uint32_t val = tmr->tbcr & ~TBCR_CI;
690 uint32_t tog = ((tmr->tccr & TCCR_TOG) ^ TCCR_TOG);
691
692 DPRINTF("%s n_IRQ=%d", __func__, n_IRQ);
693
694 tmr->tccr = val | tog;
695 openpic_tmr_set_tmr(tmr, val, true);
696
697 opp->src[n_IRQ].destmask = read_IRQreg_idr(opp, n_IRQ);
698 openpic_set_irq(opp, n_IRQ, 1);
699 openpic_set_irq(opp, n_IRQ, 0);
700}
701
702
703
704static void openpic_tmr_set_tmr(OpenPICTimer *tmr, uint32_t val, bool enabled)
705{
706 uint64_t ns = ticks_to_ns(val & ~TCCR_TOG);
707
708
709
710
711
712 if ((ns == 0) || !enabled) {
713 tmr->qemu_timer_active = false;
714 tmr->tccr = tmr->tccr & TCCR_TOG;
715 timer_del(tmr->qemu_timer);
716 } else {
717 tmr->qemu_timer_active = true;
718 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
719 tmr->origin_time = now;
720 timer_mod(tmr->qemu_timer, now + ns);
721 }
722}
723
724
725
726static uint64_t openpic_tmr_get_timer(OpenPICTimer *tmr)
727{
728 uint64_t retval;
729 if (!tmr->qemu_timer_active) {
730 retval = tmr->tccr;
731 } else {
732 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
733 uint64_t used = now - tmr->origin_time;
734 uint32_t used_ticks = (uint32_t)ns_to_ticks(used);
735 uint32_t count = (tmr->tccr & ~TCCR_TOG) - used_ticks;
736 retval = (uint32_t)((tmr->tccr & TCCR_TOG) | (count & ~TCCR_TOG));
737 }
738 return retval;
739}
740
741static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
742 unsigned len)
743{
744 OpenPICState *opp = opaque;
745 int idx;
746
747 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64,
748 __func__, (addr + 0x10f0), val);
749 if (addr & 0xF) {
750 return;
751 }
752
753 if (addr == 0) {
754
755 opp->tfrr = val;
756 return;
757 }
758 addr -= 0x10;
759 idx = (addr >> 6) & 0x3;
760
761 switch (addr & 0x30) {
762 case 0x00:
763 break;
764 case 0x10:
765
766 if ((opp->timers[idx].tbcr & TBCR_CI) != (val & TBCR_CI)) {
767
768 if ((val & TBCR_CI) == 0) {
769 opp->timers[idx].tccr = val & ~TCCR_TOG;
770 }
771 openpic_tmr_set_tmr(&opp->timers[idx],
772 (val & ~TBCR_CI),
773 ((val & TBCR_CI) == 0));
774 }
775 opp->timers[idx].tbcr = val;
776 break;
777 case 0x20:
778 write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val);
779 break;
780 case 0x30:
781 write_IRQreg_idr(opp, opp->irq_tim0 + idx, val);
782 break;
783 }
784}
785
786static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
787{
788 OpenPICState *opp = opaque;
789 uint32_t retval = -1;
790 int idx;
791
792 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr + 0x10f0);
793 if (addr & 0xF) {
794 goto out;
795 }
796 if (addr == 0) {
797
798 retval = opp->tfrr;
799 goto out;
800 }
801 addr -= 0x10;
802 idx = (addr >> 6) & 0x3;
803 switch (addr & 0x30) {
804 case 0x00:
805 retval = openpic_tmr_get_timer(&opp->timers[idx]);
806 break;
807 case 0x10:
808 retval = opp->timers[idx].tbcr;
809 break;
810 case 0x20:
811 retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
812 break;
813 case 0x30:
814 retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
815 break;
816 }
817
818out:
819 DPRINTF("%s: => 0x%08x", __func__, retval);
820
821 return retval;
822}
823
824static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
825 unsigned len)
826{
827 OpenPICState *opp = opaque;
828 int idx;
829
830 DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64,
831 __func__, addr, val);
832
833 addr = addr & 0xffff;
834 idx = addr >> 5;
835
836 switch (addr & 0x1f) {
837 case 0x00:
838 write_IRQreg_ivpr(opp, idx, val);
839 break;
840 case 0x10:
841 write_IRQreg_idr(opp, idx, val);
842 break;
843 case 0x18:
844 write_IRQreg_ilr(opp, idx, val);
845 break;
846 }
847}
848
849static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
850{
851 OpenPICState *opp = opaque;
852 uint32_t retval;
853 int idx;
854
855 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
856 retval = 0xFFFFFFFF;
857
858 addr = addr & 0xffff;
859 idx = addr >> 5;
860
861 switch (addr & 0x1f) {
862 case 0x00:
863 retval = read_IRQreg_ivpr(opp, idx);
864 break;
865 case 0x10:
866 retval = read_IRQreg_idr(opp, idx);
867 break;
868 case 0x18:
869 retval = read_IRQreg_ilr(opp, idx);
870 break;
871 }
872
873 DPRINTF("%s: => 0x%08x", __func__, retval);
874 return retval;
875}
876
877static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
878 unsigned size)
879{
880 OpenPICState *opp = opaque;
881 int idx = opp->irq_msi;
882 int srs, ibs;
883
884 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64,
885 __func__, addr, val);
886 if (addr & 0xF) {
887 return;
888 }
889
890 switch (addr) {
891 case MSIIR_OFFSET:
892 srs = val >> MSIIR_SRS_SHIFT;
893 idx += srs;
894 ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT;
895 opp->msi[srs].msir |= 1 << ibs;
896 openpic_set_irq(opp, idx, 1);
897 break;
898 default:
899
900 break;
901 }
902}
903
904static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
905{
906 OpenPICState *opp = opaque;
907 uint64_t r = 0;
908 int i, srs;
909
910 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
911 if (addr & 0xF) {
912 return -1;
913 }
914
915 srs = addr >> 4;
916
917 switch (addr) {
918 case 0x00:
919 case 0x10:
920 case 0x20:
921 case 0x30:
922 case 0x40:
923 case 0x50:
924 case 0x60:
925 case 0x70:
926 r = opp->msi[srs].msir;
927
928 opp->msi[srs].msir = 0;
929 openpic_set_irq(opp, opp->irq_msi + srs, 0);
930 break;
931 case 0x120:
932 for (i = 0; i < MAX_MSI; i++) {
933 r |= (opp->msi[i].msir ? 1 : 0) << i;
934 }
935 break;
936 }
937
938 return r;
939}
940
941static uint64_t openpic_summary_read(void *opaque, hwaddr addr, unsigned size)
942{
943 uint64_t r = 0;
944
945 DPRINTF("%s: addr %#" HWADDR_PRIx, __func__, addr);
946
947
948
949 return r;
950}
951
952static void openpic_summary_write(void *opaque, hwaddr addr, uint64_t val,
953 unsigned size)
954{
955 DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64,
956 __func__, addr, val);
957
958
959}
960
961static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
962 uint32_t val, int idx)
963{
964 OpenPICState *opp = opaque;
965 IRQSource *src;
966 IRQDest *dst;
967 int s_IRQ, n_IRQ;
968
969 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x", __func__, idx,
970 addr, val);
971
972 if (idx < 0 || idx >= opp->nb_cpus) {
973 return;
974 }
975
976 if (addr & 0xF) {
977 return;
978 }
979 dst = &opp->dst[idx];
980 addr &= 0xFF0;
981 switch (addr) {
982 case 0x40:
983 case 0x50:
984 case 0x60:
985 case 0x70:
986 idx = (addr - 0x40) >> 4;
987
988 opp->src[opp->irq_ipi0 + idx].destmask |= val;
989 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
990 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
991 break;
992 case 0x80:
993 dst->ctpr = val & 0x0000000F;
994
995 DPRINTF("%s: set CPU %d ctpr to %d, raised %d servicing %d",
996 __func__, idx, dst->ctpr, dst->raised.priority,
997 dst->servicing.priority);
998
999 if (dst->raised.priority <= dst->ctpr) {
1000 DPRINTF("%s: Lower OpenPIC INT output cpu %d due to ctpr",
1001 __func__, idx);
1002 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
1003 } else if (dst->raised.priority > dst->servicing.priority) {
1004 DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d",
1005 __func__, idx, dst->raised.next);
1006 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
1007 }
1008
1009 break;
1010 case 0x90:
1011
1012 break;
1013 case 0xA0:
1014
1015 break;
1016 case 0xB0:
1017 DPRINTF("EOI");
1018 s_IRQ = IRQ_get_next(opp, &dst->servicing);
1019
1020 if (s_IRQ < 0) {
1021 DPRINTF("%s: EOI with no interrupt in service", __func__);
1022 break;
1023 }
1024
1025 IRQ_resetbit(&dst->servicing, s_IRQ);
1026
1027 s_IRQ = IRQ_get_next(opp, &dst->servicing);
1028
1029 n_IRQ = IRQ_get_next(opp, &dst->raised);
1030 src = &opp->src[n_IRQ];
1031 if (n_IRQ != -1 &&
1032 (s_IRQ == -1 ||
1033 IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
1034 DPRINTF("Raise OpenPIC INT output cpu %d irq %d",
1035 idx, n_IRQ);
1036 qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
1037 }
1038 break;
1039 default:
1040 break;
1041 }
1042}
1043
1044static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
1045 unsigned len)
1046{
1047 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
1048}
1049
1050
1051static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
1052{
1053 IRQSource *src;
1054 int retval, irq;
1055
1056 DPRINTF("Lower OpenPIC INT output");
1057 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
1058
1059 irq = IRQ_get_next(opp, &dst->raised);
1060 DPRINTF("IACK: irq=%d", irq);
1061
1062 if (irq == -1) {
1063
1064 return opp->spve;
1065 }
1066
1067 src = &opp->src[irq];
1068 if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
1069 !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
1070 error_report("%s: bad raised IRQ %d ctpr %d ivpr 0x%08x",
1071 __func__, irq, dst->ctpr, src->ivpr);
1072 openpic_update_irq(opp, irq);
1073 retval = opp->spve;
1074 } else {
1075
1076 IRQ_setbit(&dst->servicing, irq);
1077 retval = IVPR_VECTOR(opp, src->ivpr);
1078 }
1079
1080 if (!src->level) {
1081
1082 src->ivpr &= ~IVPR_ACTIVITY_MASK;
1083 src->pending = 0;
1084 IRQ_resetbit(&dst->raised, irq);
1085 }
1086
1087
1088 if (((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + OPENPIC_MAX_IPI))) ||
1089 ((irq >= opp->irq_tim0) && (irq < (opp->irq_tim0 + OPENPIC_MAX_TMR)))) {
1090 DPRINTF("irq is IPI or TMR");
1091 src->destmask &= ~(1 << cpu);
1092 if (src->destmask && !src->level) {
1093
1094 openpic_set_irq(opp, irq, 1);
1095 openpic_set_irq(opp, irq, 0);
1096
1097 src->ivpr |= IVPR_ACTIVITY_MASK;
1098 }
1099 }
1100
1101 return retval;
1102}
1103
1104static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
1105 int idx)
1106{
1107 OpenPICState *opp = opaque;
1108 IRQDest *dst;
1109 uint32_t retval;
1110
1111 DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx, __func__, idx, addr);
1112 retval = 0xFFFFFFFF;
1113
1114 if (idx < 0 || idx >= opp->nb_cpus) {
1115 return retval;
1116 }
1117
1118 if (addr & 0xF) {
1119 return retval;
1120 }
1121 dst = &opp->dst[idx];
1122 addr &= 0xFF0;
1123 switch (addr) {
1124 case 0x80:
1125 retval = dst->ctpr;
1126 break;
1127 case 0x90:
1128 retval = idx;
1129 break;
1130 case 0xA0:
1131 retval = openpic_iack(opp, dst, idx);
1132 break;
1133 case 0xB0:
1134 retval = 0;
1135 break;
1136 default:
1137 break;
1138 }
1139 DPRINTF("%s: => 0x%08x", __func__, retval);
1140
1141 return retval;
1142}
1143
1144static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
1145{
1146 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
1147}
1148
1149static const MemoryRegionOps openpic_glb_ops_le = {
1150 .write = openpic_gbl_write,
1151 .read = openpic_gbl_read,
1152 .endianness = DEVICE_LITTLE_ENDIAN,
1153 .impl = {
1154 .min_access_size = 4,
1155 .max_access_size = 4,
1156 },
1157};
1158
1159static const MemoryRegionOps openpic_glb_ops_be = {
1160 .write = openpic_gbl_write,
1161 .read = openpic_gbl_read,
1162 .endianness = DEVICE_BIG_ENDIAN,
1163 .impl = {
1164 .min_access_size = 4,
1165 .max_access_size = 4,
1166 },
1167};
1168
1169static const MemoryRegionOps openpic_tmr_ops_le = {
1170 .write = openpic_tmr_write,
1171 .read = openpic_tmr_read,
1172 .endianness = DEVICE_LITTLE_ENDIAN,
1173 .impl = {
1174 .min_access_size = 4,
1175 .max_access_size = 4,
1176 },
1177};
1178
1179static const MemoryRegionOps openpic_tmr_ops_be = {
1180 .write = openpic_tmr_write,
1181 .read = openpic_tmr_read,
1182 .endianness = DEVICE_BIG_ENDIAN,
1183 .impl = {
1184 .min_access_size = 4,
1185 .max_access_size = 4,
1186 },
1187};
1188
1189static const MemoryRegionOps openpic_cpu_ops_le = {
1190 .write = openpic_cpu_write,
1191 .read = openpic_cpu_read,
1192 .endianness = DEVICE_LITTLE_ENDIAN,
1193 .impl = {
1194 .min_access_size = 4,
1195 .max_access_size = 4,
1196 },
1197};
1198
1199static const MemoryRegionOps openpic_cpu_ops_be = {
1200 .write = openpic_cpu_write,
1201 .read = openpic_cpu_read,
1202 .endianness = DEVICE_BIG_ENDIAN,
1203 .impl = {
1204 .min_access_size = 4,
1205 .max_access_size = 4,
1206 },
1207};
1208
1209static const MemoryRegionOps openpic_src_ops_le = {
1210 .write = openpic_src_write,
1211 .read = openpic_src_read,
1212 .endianness = DEVICE_LITTLE_ENDIAN,
1213 .impl = {
1214 .min_access_size = 4,
1215 .max_access_size = 4,
1216 },
1217};
1218
1219static const MemoryRegionOps openpic_src_ops_be = {
1220 .write = openpic_src_write,
1221 .read = openpic_src_read,
1222 .endianness = DEVICE_BIG_ENDIAN,
1223 .impl = {
1224 .min_access_size = 4,
1225 .max_access_size = 4,
1226 },
1227};
1228
1229static const MemoryRegionOps openpic_msi_ops_be = {
1230 .read = openpic_msi_read,
1231 .write = openpic_msi_write,
1232 .endianness = DEVICE_BIG_ENDIAN,
1233 .impl = {
1234 .min_access_size = 4,
1235 .max_access_size = 4,
1236 },
1237};
1238
1239static const MemoryRegionOps openpic_summary_ops_be = {
1240 .read = openpic_summary_read,
1241 .write = openpic_summary_write,
1242 .endianness = DEVICE_BIG_ENDIAN,
1243 .impl = {
1244 .min_access_size = 4,
1245 .max_access_size = 4,
1246 },
1247};
1248
1249static void openpic_reset(DeviceState *d)
1250{
1251 OpenPICState *opp = OPENPIC(d);
1252 int i;
1253
1254 opp->gcr = GCR_RESET;
1255
1256 opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
1257 ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
1258 (opp->vid << FRR_VID_SHIFT);
1259
1260 opp->pir = 0;
1261 opp->spve = -1 & opp->vector_mask;
1262 opp->tfrr = opp->tfrr_reset;
1263
1264 for (i = 0; i < opp->max_irq; i++) {
1265 opp->src[i].ivpr = opp->ivpr_reset;
1266 switch (opp->src[i].type) {
1267 case IRQ_TYPE_NORMAL:
1268 opp->src[i].level = !!(opp->ivpr_reset & IVPR_SENSE_MASK);
1269 break;
1270
1271 case IRQ_TYPE_FSLINT:
1272 opp->src[i].ivpr |= IVPR_POLARITY_MASK;
1273 break;
1274
1275 case IRQ_TYPE_FSLSPECIAL:
1276 break;
1277 }
1278
1279 write_IRQreg_idr(opp, i, opp->idr_reset);
1280 }
1281
1282 for (i = 0; i < opp->nb_cpus; i++) {
1283 opp->dst[i].ctpr = 15;
1284 opp->dst[i].raised.next = -1;
1285 opp->dst[i].raised.priority = 0;
1286 bitmap_clear(opp->dst[i].raised.queue, 0, IRQQUEUE_SIZE_BITS);
1287 opp->dst[i].servicing.next = -1;
1288 opp->dst[i].servicing.priority = 0;
1289 bitmap_clear(opp->dst[i].servicing.queue, 0, IRQQUEUE_SIZE_BITS);
1290 }
1291
1292 for (i = 0; i < OPENPIC_MAX_TMR; i++) {
1293 opp->timers[i].tccr = 0;
1294 opp->timers[i].tbcr = TBCR_CI;
1295 if (opp->timers[i].qemu_timer_active) {
1296 timer_del(opp->timers[i].qemu_timer);
1297 opp->timers[i].qemu_timer_active = false;
1298 }
1299 }
1300
1301 opp->gcr = 0;
1302}
1303
1304typedef struct MemReg {
1305 const char *name;
1306 MemoryRegionOps const *ops;
1307 hwaddr start_addr;
1308 ram_addr_t size;
1309} MemReg;
1310
1311static void fsl_common_init(OpenPICState *opp)
1312{
1313 int i;
1314 int virq = OPENPIC_MAX_SRC;
1315
1316 opp->vid = VID_REVISION_1_2;
1317 opp->vir = VIR_GENERIC;
1318 opp->vector_mask = 0xFFFF;
1319 opp->tfrr_reset = 0;
1320 opp->ivpr_reset = IVPR_MASK_MASK;
1321 opp->idr_reset = 1 << 0;
1322 opp->max_irq = OPENPIC_MAX_IRQ;
1323
1324 opp->irq_ipi0 = virq;
1325 virq += OPENPIC_MAX_IPI;
1326 opp->irq_tim0 = virq;
1327 virq += OPENPIC_MAX_TMR;
1328
1329 assert(virq <= OPENPIC_MAX_IRQ);
1330
1331 opp->irq_msi = 224;
1332
1333 msi_nonbroken = true;
1334 for (i = 0; i < opp->fsl->max_ext; i++) {
1335 opp->src[i].level = false;
1336 }
1337
1338
1339 for (i = 16; i < OPENPIC_MAX_SRC; i++) {
1340 opp->src[i].type = IRQ_TYPE_FSLINT;
1341 opp->src[i].level = true;
1342 }
1343
1344
1345 for (i = OPENPIC_MAX_SRC; i < virq; i++) {
1346 opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
1347 opp->src[i].level = false;
1348 }
1349
1350 for (i = 0; i < OPENPIC_MAX_TMR; i++) {
1351 opp->timers[i].n_IRQ = opp->irq_tim0 + i;
1352 opp->timers[i].qemu_timer_active = false;
1353 opp->timers[i].qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1354 &qemu_timer_cb,
1355 &opp->timers[i]);
1356 opp->timers[i].opp = opp;
1357 }
1358}
1359
1360static void map_list(OpenPICState *opp, const MemReg *list, int *count)
1361{
1362 while (list->name) {
1363 assert(*count < ARRAY_SIZE(opp->sub_io_mem));
1364
1365 memory_region_init_io(&opp->sub_io_mem[*count], OBJECT(opp), list->ops,
1366 opp, list->name, list->size);
1367
1368 memory_region_add_subregion(&opp->mem, list->start_addr,
1369 &opp->sub_io_mem[*count]);
1370
1371 (*count)++;
1372 list++;
1373 }
1374}
1375
1376static const VMStateDescription vmstate_openpic_irq_queue = {
1377 .name = "openpic_irq_queue",
1378 .version_id = 0,
1379 .minimum_version_id = 0,
1380 .fields = (VMStateField[]) {
1381 VMSTATE_BITMAP(queue, IRQQueue, 0, queue_size),
1382 VMSTATE_INT32(next, IRQQueue),
1383 VMSTATE_INT32(priority, IRQQueue),
1384 VMSTATE_END_OF_LIST()
1385 }
1386};
1387
1388static const VMStateDescription vmstate_openpic_irqdest = {
1389 .name = "openpic_irqdest",
1390 .version_id = 0,
1391 .minimum_version_id = 0,
1392 .fields = (VMStateField[]) {
1393 VMSTATE_INT32(ctpr, IRQDest),
1394 VMSTATE_STRUCT(raised, IRQDest, 0, vmstate_openpic_irq_queue,
1395 IRQQueue),
1396 VMSTATE_STRUCT(servicing, IRQDest, 0, vmstate_openpic_irq_queue,
1397 IRQQueue),
1398 VMSTATE_UINT32_ARRAY(outputs_active, IRQDest, OPENPIC_OUTPUT_NB),
1399 VMSTATE_END_OF_LIST()
1400 }
1401};
1402
1403static const VMStateDescription vmstate_openpic_irqsource = {
1404 .name = "openpic_irqsource",
1405 .version_id = 0,
1406 .minimum_version_id = 0,
1407 .fields = (VMStateField[]) {
1408 VMSTATE_UINT32(ivpr, IRQSource),
1409 VMSTATE_UINT32(idr, IRQSource),
1410 VMSTATE_UINT32(destmask, IRQSource),
1411 VMSTATE_INT32(last_cpu, IRQSource),
1412 VMSTATE_INT32(pending, IRQSource),
1413 VMSTATE_END_OF_LIST()
1414 }
1415};
1416
1417static const VMStateDescription vmstate_openpic_timer = {
1418 .name = "openpic_timer",
1419 .version_id = 0,
1420 .minimum_version_id = 0,
1421 .fields = (VMStateField[]) {
1422 VMSTATE_UINT32(tccr, OpenPICTimer),
1423 VMSTATE_UINT32(tbcr, OpenPICTimer),
1424 VMSTATE_END_OF_LIST()
1425 }
1426};
1427
1428static const VMStateDescription vmstate_openpic_msi = {
1429 .name = "openpic_msi",
1430 .version_id = 0,
1431 .minimum_version_id = 0,
1432 .fields = (VMStateField[]) {
1433 VMSTATE_UINT32(msir, OpenPICMSI),
1434 VMSTATE_END_OF_LIST()
1435 }
1436};
1437
1438static int openpic_post_load(void *opaque, int version_id)
1439{
1440 OpenPICState *opp = (OpenPICState *)opaque;
1441 int i;
1442
1443
1444 for (i = 0; i < opp->max_irq; i++) {
1445 write_IRQreg_idr(opp, i, opp->src[i].idr);
1446 write_IRQreg_ivpr(opp, i, opp->src[i].ivpr);
1447 }
1448
1449 return 0;
1450}
1451
1452static const VMStateDescription vmstate_openpic = {
1453 .name = "openpic",
1454 .version_id = 3,
1455 .minimum_version_id = 3,
1456 .post_load = openpic_post_load,
1457 .fields = (VMStateField[]) {
1458 VMSTATE_UINT32(gcr, OpenPICState),
1459 VMSTATE_UINT32(vir, OpenPICState),
1460 VMSTATE_UINT32(pir, OpenPICState),
1461 VMSTATE_UINT32(spve, OpenPICState),
1462 VMSTATE_UINT32(tfrr, OpenPICState),
1463 VMSTATE_UINT32(max_irq, OpenPICState),
1464 VMSTATE_STRUCT_VARRAY_UINT32(src, OpenPICState, max_irq, 0,
1465 vmstate_openpic_irqsource, IRQSource),
1466 VMSTATE_UINT32_EQUAL(nb_cpus, OpenPICState, NULL),
1467 VMSTATE_STRUCT_VARRAY_UINT32(dst, OpenPICState, nb_cpus, 0,
1468 vmstate_openpic_irqdest, IRQDest),
1469 VMSTATE_STRUCT_ARRAY(timers, OpenPICState, OPENPIC_MAX_TMR, 0,
1470 vmstate_openpic_timer, OpenPICTimer),
1471 VMSTATE_STRUCT_ARRAY(msi, OpenPICState, MAX_MSI, 0,
1472 vmstate_openpic_msi, OpenPICMSI),
1473 VMSTATE_UINT32(irq_ipi0, OpenPICState),
1474 VMSTATE_UINT32(irq_tim0, OpenPICState),
1475 VMSTATE_UINT32(irq_msi, OpenPICState),
1476 VMSTATE_END_OF_LIST()
1477 }
1478};
1479
1480static void openpic_init(Object *obj)
1481{
1482 OpenPICState *opp = OPENPIC(obj);
1483
1484 memory_region_init(&opp->mem, obj, "openpic", 0x40000);
1485}
1486
1487static void openpic_realize(DeviceState *dev, Error **errp)
1488{
1489 SysBusDevice *d = SYS_BUS_DEVICE(dev);
1490 OpenPICState *opp = OPENPIC(dev);
1491 int i, j;
1492 int list_count = 0;
1493 static const MemReg list_le[] = {
1494 {"glb", &openpic_glb_ops_le,
1495 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1496 {"tmr", &openpic_tmr_ops_le,
1497 OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1498 {"src", &openpic_src_ops_le,
1499 OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1500 {"cpu", &openpic_cpu_ops_le,
1501 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1502 {NULL}
1503 };
1504 static const MemReg list_be[] = {
1505 {"glb", &openpic_glb_ops_be,
1506 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1507 {"tmr", &openpic_tmr_ops_be,
1508 OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1509 {"src", &openpic_src_ops_be,
1510 OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1511 {"cpu", &openpic_cpu_ops_be,
1512 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1513 {NULL}
1514 };
1515 static const MemReg list_fsl[] = {
1516 {"msi", &openpic_msi_ops_be,
1517 OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1518 {"summary", &openpic_summary_ops_be,
1519 OPENPIC_SUMMARY_REG_START, OPENPIC_SUMMARY_REG_SIZE},
1520 {NULL}
1521 };
1522
1523 if (opp->nb_cpus > MAX_CPU) {
1524 error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
1525 TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
1526 (uint64_t)0, (uint64_t)MAX_CPU);
1527 return;
1528 }
1529
1530 switch (opp->model) {
1531 case OPENPIC_MODEL_FSL_MPIC_20:
1532 default:
1533 opp->fsl = &fsl_mpic_20;
1534 opp->brr1 = 0x00400200;
1535 opp->flags |= OPENPIC_FLAG_IDR_CRIT;
1536 opp->nb_irqs = 80;
1537 opp->mpic_mode_mask = GCR_MODE_MIXED;
1538
1539 fsl_common_init(opp);
1540 map_list(opp, list_be, &list_count);
1541 map_list(opp, list_fsl, &list_count);
1542
1543 break;
1544
1545 case OPENPIC_MODEL_FSL_MPIC_42:
1546 opp->fsl = &fsl_mpic_42;
1547 opp->brr1 = 0x00400402;
1548 opp->flags |= OPENPIC_FLAG_ILR;
1549 opp->nb_irqs = 196;
1550 opp->mpic_mode_mask = GCR_MODE_PROXY;
1551
1552 fsl_common_init(opp);
1553 map_list(opp, list_be, &list_count);
1554 map_list(opp, list_fsl, &list_count);
1555
1556 break;
1557
1558 case OPENPIC_MODEL_RAVEN:
1559 opp->nb_irqs = RAVEN_MAX_EXT;
1560 opp->vid = VID_REVISION_1_3;
1561 opp->vir = VIR_GENERIC;
1562 opp->vector_mask = 0xFF;
1563 opp->tfrr_reset = 4160000;
1564 opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
1565 opp->idr_reset = 0;
1566 opp->max_irq = RAVEN_MAX_IRQ;
1567 opp->irq_ipi0 = RAVEN_IPI_IRQ;
1568 opp->irq_tim0 = RAVEN_TMR_IRQ;
1569 opp->brr1 = -1;
1570 opp->mpic_mode_mask = GCR_MODE_MIXED;
1571
1572 if (opp->nb_cpus != 1) {
1573 error_setg(errp, "Only UP supported today");
1574 return;
1575 }
1576
1577 map_list(opp, list_le, &list_count);
1578 break;
1579
1580 case OPENPIC_MODEL_KEYLARGO:
1581 opp->nb_irqs = KEYLARGO_MAX_EXT;
1582 opp->vid = VID_REVISION_1_2;
1583 opp->vir = VIR_GENERIC;
1584 opp->vector_mask = 0xFF;
1585 opp->tfrr_reset = 4160000;
1586 opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
1587 opp->idr_reset = 0;
1588 opp->max_irq = KEYLARGO_MAX_IRQ;
1589 opp->irq_ipi0 = KEYLARGO_IPI_IRQ;
1590 opp->irq_tim0 = KEYLARGO_TMR_IRQ;
1591 opp->brr1 = -1;
1592 opp->mpic_mode_mask = GCR_MODE_MIXED;
1593
1594 if (opp->nb_cpus != 1) {
1595 error_setg(errp, "Only UP supported today");
1596 return;
1597 }
1598
1599 map_list(opp, list_le, &list_count);
1600 break;
1601 }
1602
1603 for (i = 0; i < opp->nb_cpus; i++) {
1604 opp->dst[i].irqs = g_new0(qemu_irq, OPENPIC_OUTPUT_NB);
1605 for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
1606 sysbus_init_irq(d, &opp->dst[i].irqs[j]);
1607 }
1608
1609 opp->dst[i].raised.queue_size = IRQQUEUE_SIZE_BITS;
1610 opp->dst[i].raised.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
1611 opp->dst[i].servicing.queue_size = IRQQUEUE_SIZE_BITS;
1612 opp->dst[i].servicing.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
1613 }
1614
1615 sysbus_init_mmio(d, &opp->mem);
1616 qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq);
1617}
1618
1619static Property openpic_properties[] = {
1620 DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_FSL_MPIC_20),
1621 DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1),
1622 DEFINE_PROP_END_OF_LIST(),
1623};
1624
1625static void openpic_class_init(ObjectClass *oc, void *data)
1626{
1627 DeviceClass *dc = DEVICE_CLASS(oc);
1628
1629 dc->realize = openpic_realize;
1630 device_class_set_props(dc, openpic_properties);
1631 dc->reset = openpic_reset;
1632 dc->vmsd = &vmstate_openpic;
1633 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
1634}
1635
1636static const TypeInfo openpic_info = {
1637 .name = TYPE_OPENPIC,
1638 .parent = TYPE_SYS_BUS_DEVICE,
1639 .instance_size = sizeof(OpenPICState),
1640 .instance_init = openpic_init,
1641 .class_init = openpic_class_init,
1642};
1643
1644static void openpic_register_types(void)
1645{
1646 type_register_static(&openpic_info);
1647}
1648
1649type_init(openpic_register_types)
1650