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