Statistics
| Branch: | Revision:

root / hw / openpic.c @ a26a7b38

History | View | Annotate | Download (36.2 kB)

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

    
43
//#define DEBUG_OPENPIC
44

    
45
#ifdef DEBUG_OPENPIC
46
#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
47
#else
48
#define DPRINTF(fmt, ...) do { } while (0)
49
#endif
50

    
51
#define MAX_CPU     15
52
#define MAX_SRC     256
53
#define MAX_TMR     4
54
#define MAX_IPI     4
55
#define MAX_MSI     8
56
#define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
57
#define VID         0x03 /* MPIC version ID */
58

    
59
/* OpenPIC capability flags */
60
#define OPENPIC_FLAG_IDE_CRIT     (1 << 0)
61

    
62
/* OpenPIC address map */
63
#define OPENPIC_GLB_REG_START        0x0
64
#define OPENPIC_GLB_REG_SIZE         0x10F0
65
#define OPENPIC_TMR_REG_START        0x10F0
66
#define OPENPIC_TMR_REG_SIZE         0x220
67
#define OPENPIC_MSI_REG_START        0x1600
68
#define OPENPIC_MSI_REG_SIZE         0x200
69
#define OPENPIC_SRC_REG_START        0x10000
70
#define OPENPIC_SRC_REG_SIZE         (MAX_SRC * 0x20)
71
#define OPENPIC_CPU_REG_START        0x20000
72
#define OPENPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
73

    
74
/* Raven */
75
#define RAVEN_MAX_CPU      2
76
#define RAVEN_MAX_EXT     48
77
#define RAVEN_MAX_IRQ     64
78
#define RAVEN_MAX_TMR      MAX_TMR
79
#define RAVEN_MAX_IPI      MAX_IPI
80

    
81
/* Interrupt definitions */
82
#define RAVEN_FE_IRQ     (RAVEN_MAX_EXT)     /* Internal functional IRQ */
83
#define RAVEN_ERR_IRQ    (RAVEN_MAX_EXT + 1) /* Error IRQ */
84
#define RAVEN_TMR_IRQ    (RAVEN_MAX_EXT + 2) /* First timer IRQ */
85
#define RAVEN_IPI_IRQ    (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */
86
/* First doorbell IRQ */
87
#define RAVEN_DBL_IRQ    (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
88

    
89
/* FSL_MPIC_20 */
90
#define FSL_MPIC_20_MAX_CPU      1
91
#define FSL_MPIC_20_MAX_EXT     12
92
#define FSL_MPIC_20_MAX_INT     64
93
#define FSL_MPIC_20_MAX_IRQ     MAX_IRQ
94

    
95
/* Interrupt definitions */
96
/* IRQs, accessible through the IRQ region */
97
#define FSL_MPIC_20_EXT_IRQ      0x00
98
#define FSL_MPIC_20_INT_IRQ      0x10
99
#define FSL_MPIC_20_MSG_IRQ      0xb0
100
#define FSL_MPIC_20_MSI_IRQ      0xe0
101
/* These are available through separate regions, but
102
   for simplicity's sake mapped into the same number space */
103
#define FSL_MPIC_20_TMR_IRQ      0x100
104
#define FSL_MPIC_20_IPI_IRQ      0x104
105

    
106
/*
107
 * Block Revision Register1 (BRR1): QEMU does not fully emulate
108
 * any version on MPIC. So to start with, set the IP version to 0.
109
 *
110
 * NOTE: This is Freescale MPIC specific register. Keep it here till
111
 * this code is refactored for different variants of OPENPIC and MPIC.
112
 */
113
#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
114
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
115
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
116

    
117
#define FREP_NIRQ_SHIFT   16
118
#define FREP_NCPU_SHIFT    8
119
#define FREP_VID_SHIFT     0
120

    
121
#define VID_REVISION_1_2   2
122
#define VID_REVISION_1_3   3
123

    
124
#define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
125

    
126
#define GLBC_RESET        0x80000000
127

    
128
#define TIBC_CI           0x80000000 /* count inhibit */
129
#define TICC_TOG          0x80000000 /* toggles when decrement to zero */
130

    
131
#define IDR_EP_SHIFT      31
132
#define IDR_EP_MASK       (1 << IDR_EP_SHIFT)
133
#define IDR_CI0_SHIFT     30
134
#define IDR_CI1_SHIFT     29
135
#define IDR_P1_SHIFT      1
136
#define IDR_P0_SHIFT      0
137

    
138
#define MSIIR_OFFSET       0x140
139
#define MSIIR_SRS_SHIFT    29
140
#define MSIIR_SRS_MASK     (0x7 << MSIIR_SRS_SHIFT)
141
#define MSIIR_IBS_SHIFT    24
142
#define MSIIR_IBS_MASK     (0x1f << MSIIR_IBS_SHIFT)
143

    
144
#define BF_WIDTH(_bits_) \
145
(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
146

    
147
static inline void set_bit(uint32_t *field, int bit)
148
{
149
    field[bit >> 5] |= 1 << (bit & 0x1F);
150
}
151

    
152
static inline void reset_bit(uint32_t *field, int bit)
153
{
154
    field[bit >> 5] &= ~(1 << (bit & 0x1F));
155
}
156

    
157
static inline int test_bit(uint32_t *field, int bit)
158
{
159
    return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
160
}
161

    
162
static int get_current_cpu(void)
163
{
164
  return cpu_single_env->cpu_index;
165
}
166

    
167
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
168
                                          int idx);
169
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
170
                                       uint32_t val, int idx);
171

    
172
typedef struct IRQ_queue_t {
173
    uint32_t queue[BF_WIDTH(MAX_IRQ)];
174
    int next;
175
    int priority;
176
    int pending;    /* nr of pending bits in queue */
177
} IRQ_queue_t;
178

    
179
typedef struct IRQ_src_t {
180
    uint32_t ipvp;  /* IRQ vector/priority register */
181
    uint32_t ide;   /* IRQ destination register */
182
    int last_cpu;
183
    int pending;    /* TRUE if IRQ is pending */
184
} IRQ_src_t;
185

    
186
#define IPVP_MASK_SHIFT       31
187
#define IPVP_MASK_MASK        (1 << IPVP_MASK_SHIFT)
188
#define IPVP_ACTIVITY_SHIFT   30
189
#define IPVP_ACTIVITY_MASK    (1 << IPVP_ACTIVITY_SHIFT)
190
#define IPVP_MODE_SHIFT       29
191
#define IPVP_MODE_MASK        (1 << IPVP_MODE_SHIFT)
192
#define IPVP_POLARITY_SHIFT   23
193
#define IPVP_POLARITY_MASK    (1 << IPVP_POLARITY_SHIFT)
194
#define IPVP_SENSE_SHIFT      22
195
#define IPVP_SENSE_MASK       (1 << IPVP_SENSE_SHIFT)
196

    
197
#define IPVP_PRIORITY_MASK     (0xF << 16)
198
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
199
#define IPVP_VECTOR(opp, _ipvpr_) ((_ipvpr_) & (opp)->vector_mask)
200

    
201
/* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
202
#define IDE_EP      0x80000000  /* external pin */
203
#define IDE_CI      0x40000000  /* critical interrupt */
204

    
205
typedef struct IRQ_dst_t {
206
    uint32_t pctp; /* CPU current task priority */
207
    IRQ_queue_t raised;
208
    IRQ_queue_t servicing;
209
    qemu_irq *irqs;
210
} IRQ_dst_t;
211

    
212
typedef struct OpenPICState {
213
    SysBusDevice busdev;
214
    MemoryRegion mem;
215

    
216
    /* Behavior control */
217
    uint32_t model;
218
    uint32_t flags;
219
    uint32_t nb_irqs;
220
    uint32_t vid;
221
    uint32_t veni; /* Vendor identification register */
222
    uint32_t vector_mask;
223
    uint32_t tifr_reset;
224
    uint32_t ipvp_reset;
225
    uint32_t ide_reset;
226
    uint32_t brr1;
227

    
228
    /* Sub-regions */
229
    MemoryRegion sub_io_mem[5];
230

    
231
    /* Global registers */
232
    uint32_t frep; /* Feature reporting register */
233
    uint32_t glbc; /* Global configuration register  */
234
    uint32_t pint; /* Processor initialization register */
235
    uint32_t spve; /* Spurious vector register */
236
    uint32_t tifr; /* Timer frequency reporting register */
237
    /* Source registers */
238
    IRQ_src_t src[MAX_IRQ];
239
    /* Local registers per output pin */
240
    IRQ_dst_t dst[MAX_CPU];
241
    uint32_t nb_cpus;
242
    /* Timer registers */
243
    struct {
244
        uint32_t ticc;  /* Global timer current count register */
245
        uint32_t tibc;  /* Global timer base count register */
246
    } timers[MAX_TMR];
247
    /* Shared MSI registers */
248
    struct {
249
        uint32_t msir;   /* Shared Message Signaled Interrupt Register */
250
    } msi[MAX_MSI];
251
    uint32_t max_irq;
252
    uint32_t irq_ipi0;
253
    uint32_t irq_tim0;
254
    uint32_t irq_msi;
255
} OpenPICState;
256

    
257
static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
258

    
259
static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ)
260
{
261
    q->pending++;
262
    set_bit(q->queue, n_IRQ);
263
}
264

    
265
static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ)
266
{
267
    q->pending--;
268
    reset_bit(q->queue, n_IRQ);
269
}
270

    
271
static inline int IRQ_testbit(IRQ_queue_t *q, int n_IRQ)
272
{
273
    return test_bit(q->queue, n_IRQ);
274
}
275

    
276
static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q)
277
{
278
    int next, i;
279
    int priority;
280

    
281
    next = -1;
282
    priority = -1;
283

    
284
    if (!q->pending) {
285
        /* IRQ bitmap is empty */
286
        goto out;
287
    }
288

    
289
    for (i = 0; i < opp->max_irq; i++) {
290
        if (IRQ_testbit(q, i)) {
291
            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
292
                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
293
            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
294
                next = i;
295
                priority = IPVP_PRIORITY(opp->src[i].ipvp);
296
            }
297
        }
298
    }
299

    
300
out:
301
    q->next = next;
302
    q->priority = priority;
303
}
304

    
305
static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
306
{
307
    if (q->next == -1) {
308
        /* XXX: optimize */
309
        IRQ_check(opp, q);
310
    }
311

    
312
    return q->next;
313
}
314

    
315
static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
316
{
317
    IRQ_dst_t *dst;
318
    IRQ_src_t *src;
319
    int priority;
320

    
321
    dst = &opp->dst[n_CPU];
322
    src = &opp->src[n_IRQ];
323
    priority = IPVP_PRIORITY(src->ipvp);
324
    if (priority <= dst->pctp) {
325
        /* Too low priority */
326
        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
327
                __func__, n_IRQ, n_CPU);
328
        return;
329
    }
330
    if (IRQ_testbit(&dst->raised, n_IRQ)) {
331
        /* Interrupt miss */
332
        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
333
                __func__, n_IRQ, n_CPU);
334
        return;
335
    }
336
    src->ipvp |= IPVP_ACTIVITY_MASK;
337
    IRQ_setbit(&dst->raised, n_IRQ);
338
    if (priority < dst->raised.priority) {
339
        /* An higher priority IRQ is already raised */
340
        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
341
                __func__, n_IRQ, dst->raised.next, n_CPU);
342
        return;
343
    }
344
    IRQ_get_next(opp, &dst->raised);
345
    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
346
        priority <= dst->servicing.priority) {
347
        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
348
                __func__, n_IRQ, dst->servicing.next, n_CPU);
349
        /* Already servicing a higher priority IRQ */
350
        return;
351
    }
352
    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
353
    openpic_irq_raise(opp, n_CPU, src);
354
}
355

    
356
/* update pic state because registers for n_IRQ have changed value */
357
static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
358
{
359
    IRQ_src_t *src;
360
    int i;
361

    
362
    src = &opp->src[n_IRQ];
363

    
364
    if (!src->pending) {
365
        /* no irq pending */
366
        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
367
        return;
368
    }
369
    if (src->ipvp & IPVP_MASK_MASK) {
370
        /* Interrupt source is disabled */
371
        DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
372
        return;
373
    }
374
    if (IPVP_PRIORITY(src->ipvp) == 0) {
375
        /* Priority set to zero */
376
        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
377
        return;
378
    }
379
    if (src->ipvp & IPVP_ACTIVITY_MASK) {
380
        /* IRQ already active */
381
        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
382
        return;
383
    }
384
    if (src->ide == 0) {
385
        /* No target */
386
        DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
387
        return;
388
    }
389

    
390
    if (src->ide == (1 << src->last_cpu)) {
391
        /* Only one CPU is allowed to receive this IRQ */
392
        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
393
    } else if (!(src->ipvp & IPVP_MODE_MASK)) {
394
        /* Directed delivery mode */
395
        for (i = 0; i < opp->nb_cpus; i++) {
396
            if (src->ide & (1 << i)) {
397
                IRQ_local_pipe(opp, i, n_IRQ);
398
            }
399
        }
400
    } else {
401
        /* Distributed delivery mode */
402
        for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
403
            if (i == opp->nb_cpus)
404
                i = 0;
405
            if (src->ide & (1 << i)) {
406
                IRQ_local_pipe(opp, i, n_IRQ);
407
                src->last_cpu = i;
408
                break;
409
            }
410
        }
411
    }
412
}
413

    
414
static void openpic_set_irq(void *opaque, int n_IRQ, int level)
415
{
416
    OpenPICState *opp = opaque;
417
    IRQ_src_t *src;
418

    
419
    src = &opp->src[n_IRQ];
420
    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
421
            n_IRQ, level, src->ipvp);
422
    if (src->ipvp & IPVP_SENSE_MASK) {
423
        /* level-sensitive irq */
424
        src->pending = level;
425
        if (!level) {
426
            src->ipvp &= ~IPVP_ACTIVITY_MASK;
427
        }
428
    } else {
429
        /* edge-sensitive irq */
430
        if (level)
431
            src->pending = 1;
432
    }
433
    openpic_update_irq(opp, n_IRQ);
434
}
435

    
436
static void openpic_reset(DeviceState *d)
437
{
438
    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
439
    int i;
440

    
441
    opp->glbc = GLBC_RESET;
442
    /* Initialise controller registers */
443
    opp->frep = ((opp->nb_irqs - 1) << FREP_NIRQ_SHIFT) |
444
                ((opp->nb_cpus - 1) << FREP_NCPU_SHIFT) |
445
                (opp->vid << FREP_VID_SHIFT);
446

    
447
    opp->pint = 0;
448
    opp->spve = -1 & opp->vector_mask;
449
    opp->tifr = opp->tifr_reset;
450
    /* Initialise IRQ sources */
451
    for (i = 0; i < opp->max_irq; i++) {
452
        opp->src[i].ipvp = opp->ipvp_reset;
453
        opp->src[i].ide  = opp->ide_reset;
454
    }
455
    /* Initialise IRQ destinations */
456
    for (i = 0; i < MAX_CPU; i++) {
457
        opp->dst[i].pctp      = 15;
458
        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
459
        opp->dst[i].raised.next = -1;
460
        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
461
        opp->dst[i].servicing.next = -1;
462
    }
463
    /* Initialise timers */
464
    for (i = 0; i < MAX_TMR; i++) {
465
        opp->timers[i].ticc = 0;
466
        opp->timers[i].tibc = TIBC_CI;
467
    }
468
    /* Go out of RESET state */
469
    opp->glbc = 0;
470
}
471

    
472
static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
473
{
474
    return opp->src[n_IRQ].ide;
475
}
476

    
477
static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
478
{
479
    return opp->src[n_IRQ].ipvp;
480
}
481

    
482
static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
483
{
484
    uint32_t tmp;
485

    
486
    tmp = val & (IDE_EP | IDE_CI);
487
    tmp |= val & ((1ULL << MAX_CPU) - 1);
488
    opp->src[n_IRQ].ide = tmp;
489
    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
490
}
491

    
492
static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
493
{
494
    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
495
    /* ACTIVITY bit is read-only */
496
    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
497
        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | opp->vector_mask));
498
    openpic_update_irq(opp, n_IRQ);
499
    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
500
            opp->src[n_IRQ].ipvp);
501
}
502

    
503
static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
504
                              unsigned len)
505
{
506
    OpenPICState *opp = opaque;
507
    IRQ_dst_t *dst;
508
    int idx;
509

    
510
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
511
    if (addr & 0xF)
512
        return;
513
    switch (addr) {
514
    case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
515
        break;
516
    case 0x40:
517
    case 0x50:
518
    case 0x60:
519
    case 0x70:
520
    case 0x80:
521
    case 0x90:
522
    case 0xA0:
523
    case 0xB0:
524
        openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
525
        break;
526
    case 0x1000: /* FREP */
527
        break;
528
    case 0x1020: /* GLBC */
529
        if (val & GLBC_RESET) {
530
            openpic_reset(&opp->busdev.qdev);
531
        }
532
        break;
533
    case 0x1080: /* VENI */
534
        break;
535
    case 0x1090: /* PINT */
536
        for (idx = 0; idx < opp->nb_cpus; idx++) {
537
            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
538
                DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
539
                dst = &opp->dst[idx];
540
                qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
541
            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
542
                DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
543
                dst = &opp->dst[idx];
544
                qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
545
            }
546
        }
547
        opp->pint = val;
548
        break;
549
    case 0x10A0: /* IPI_IPVP */
550
    case 0x10B0:
551
    case 0x10C0:
552
    case 0x10D0:
553
        {
554
            int idx;
555
            idx = (addr - 0x10A0) >> 4;
556
            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
557
        }
558
        break;
559
    case 0x10E0: /* SPVE */
560
        opp->spve = val & opp->vector_mask;
561
        break;
562
    default:
563
        break;
564
    }
565
}
566

    
567
static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
568
{
569
    OpenPICState *opp = opaque;
570
    uint32_t retval;
571

    
572
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
573
    retval = 0xFFFFFFFF;
574
    if (addr & 0xF)
575
        return retval;
576
    switch (addr) {
577
    case 0x1000: /* FREP */
578
        retval = opp->frep;
579
        break;
580
    case 0x1020: /* GLBC */
581
        retval = opp->glbc;
582
        break;
583
    case 0x1080: /* VENI */
584
        retval = opp->veni;
585
        break;
586
    case 0x1090: /* PINT */
587
        retval = 0x00000000;
588
        break;
589
    case 0x00: /* Block Revision Register1 (BRR1) */
590
        retval = opp->brr1;
591
        break;
592
    case 0x40:
593
    case 0x50:
594
    case 0x60:
595
    case 0x70:
596
    case 0x80:
597
    case 0x90:
598
    case 0xA0:
599
    case 0xB0:
600
        retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
601
        break;
602
    case 0x10A0: /* IPI_IPVP */
603
    case 0x10B0:
604
    case 0x10C0:
605
    case 0x10D0:
606
        {
607
            int idx;
608
            idx = (addr - 0x10A0) >> 4;
609
            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
610
        }
611
        break;
612
    case 0x10E0: /* SPVE */
613
        retval = opp->spve;
614
        break;
615
    default:
616
        break;
617
    }
618
    DPRINTF("%s: => %08x\n", __func__, retval);
619

    
620
    return retval;
621
}
622

    
623
static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
624
                                unsigned len)
625
{
626
    OpenPICState *opp = opaque;
627
    int idx;
628

    
629
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
630
    if (addr & 0xF)
631
        return;
632
    idx = (addr >> 6) & 0x3;
633
    addr = addr & 0x30;
634

    
635
    if (addr == 0x0) {
636
        /* TIFR (TFRR) */
637
        opp->tifr = val;
638
        return;
639
    }
640
    switch (addr & 0x30) {
641
    case 0x00: /* TICC (GTCCR) */
642
        break;
643
    case 0x10: /* TIBC (GTBCR) */
644
        if ((opp->timers[idx].ticc & TICC_TOG) != 0 &&
645
            (val & TIBC_CI) == 0 &&
646
            (opp->timers[idx].tibc & TIBC_CI) != 0) {
647
            opp->timers[idx].ticc &= ~TICC_TOG;
648
        }
649
        opp->timers[idx].tibc = val;
650
        break;
651
    case 0x20: /* TIVP (GTIVPR) */
652
        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
653
        break;
654
    case 0x30: /* TIDE (GTIDR) */
655
        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
656
        break;
657
    }
658
}
659

    
660
static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
661
{
662
    OpenPICState *opp = opaque;
663
    uint32_t retval = -1;
664
    int idx;
665

    
666
    DPRINTF("%s: addr %08x\n", __func__, addr);
667
    if (addr & 0xF) {
668
        goto out;
669
    }
670
    idx = (addr >> 6) & 0x3;
671
    if (addr == 0x0) {
672
        /* TIFR (TFRR) */
673
        retval = opp->tifr;
674
        goto out;
675
    }
676
    switch (addr & 0x30) {
677
    case 0x00: /* TICC (GTCCR) */
678
        retval = opp->timers[idx].ticc;
679
        break;
680
    case 0x10: /* TIBC (GTBCR) */
681
        retval = opp->timers[idx].tibc;
682
        break;
683
    case 0x20: /* TIPV (TIPV) */
684
        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
685
        break;
686
    case 0x30: /* TIDE (TIDR) */
687
        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
688
        break;
689
    }
690

    
691
out:
692
    DPRINTF("%s: => %08x\n", __func__, retval);
693

    
694
    return retval;
695
}
696

    
697
static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
698
                              unsigned len)
699
{
700
    OpenPICState *opp = opaque;
701
    int idx;
702

    
703
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
704
    if (addr & 0xF)
705
        return;
706
    addr = addr & 0xFFF0;
707
    idx = addr >> 5;
708
    if (addr & 0x10) {
709
        /* EXDE / IFEDE / IEEDE */
710
        write_IRQreg_ide(opp, idx, val);
711
    } else {
712
        /* EXVP / IFEVP / IEEVP */
713
        write_IRQreg_ipvp(opp, idx, val);
714
    }
715
}
716

    
717
static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
718
{
719
    OpenPICState *opp = opaque;
720
    uint32_t retval;
721
    int idx;
722

    
723
    DPRINTF("%s: addr %08x\n", __func__, addr);
724
    retval = 0xFFFFFFFF;
725
    if (addr & 0xF)
726
        return retval;
727
    addr = addr & 0xFFF0;
728
    idx = addr >> 5;
729
    if (addr & 0x10) {
730
        /* EXDE / IFEDE / IEEDE */
731
        retval = read_IRQreg_ide(opp, idx);
732
    } else {
733
        /* EXVP / IFEVP / IEEVP */
734
        retval = read_IRQreg_ipvp(opp, idx);
735
    }
736
    DPRINTF("%s: => %08x\n", __func__, retval);
737

    
738
    return retval;
739
}
740

    
741
static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
742
                              unsigned size)
743
{
744
    OpenPICState *opp = opaque;
745
    int idx = opp->irq_msi;
746
    int srs, ibs;
747

    
748
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
749
    if (addr & 0xF) {
750
        return;
751
    }
752

    
753
    switch (addr) {
754
    case MSIIR_OFFSET:
755
        srs = val >> MSIIR_SRS_SHIFT;
756
        idx += srs;
757
        ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT;
758
        opp->msi[srs].msir |= 1 << ibs;
759
        openpic_set_irq(opp, idx, 1);
760
        break;
761
    default:
762
        /* most registers are read-only, thus ignored */
763
        break;
764
    }
765
}
766

    
767
static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
768
{
769
    OpenPICState *opp = opaque;
770
    uint64_t r = 0;
771
    int i, srs;
772

    
773
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
774
    if (addr & 0xF) {
775
        return -1;
776
    }
777

    
778
    srs = addr >> 4;
779

    
780
    switch (addr) {
781
    case 0x00:
782
    case 0x10:
783
    case 0x20:
784
    case 0x30:
785
    case 0x40:
786
    case 0x50:
787
    case 0x60:
788
    case 0x70: /* MSIRs */
789
        r = opp->msi[srs].msir;
790
        /* Clear on read */
791
        opp->msi[srs].msir = 0;
792
        break;
793
    case 0x120: /* MSISR */
794
        for (i = 0; i < MAX_MSI; i++) {
795
            r |= (opp->msi[i].msir ? 1 : 0) << i;
796
        }
797
        break;
798
    }
799

    
800
    return r;
801
}
802

    
803
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
804
                                       uint32_t val, int idx)
805
{
806
    OpenPICState *opp = opaque;
807
    IRQ_src_t *src;
808
    IRQ_dst_t *dst;
809
    int s_IRQ, n_IRQ;
810

    
811
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
812
            addr, val);
813
    if (addr & 0xF)
814
        return;
815
    dst = &opp->dst[idx];
816
    addr &= 0xFF0;
817
    switch (addr) {
818
    case 0x40: /* IPIDR */
819
    case 0x50:
820
    case 0x60:
821
    case 0x70:
822
        idx = (addr - 0x40) >> 4;
823
        /* we use IDE as mask which CPUs to deliver the IPI to still. */
824
        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
825
                         opp->src[opp->irq_ipi0 + idx].ide | val);
826
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
827
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
828
        break;
829
    case 0x80: /* PCTP */
830
        dst->pctp = val & 0x0000000F;
831
        break;
832
    case 0x90: /* WHOAMI */
833
        /* Read-only register */
834
        break;
835
    case 0xA0: /* PIAC */
836
        /* Read-only register */
837
        break;
838
    case 0xB0: /* PEOI */
839
        DPRINTF("PEOI\n");
840
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
841
        IRQ_resetbit(&dst->servicing, s_IRQ);
842
        dst->servicing.next = -1;
843
        /* Set up next servicing IRQ */
844
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
845
        /* Check queued interrupts. */
846
        n_IRQ = IRQ_get_next(opp, &dst->raised);
847
        src = &opp->src[n_IRQ];
848
        if (n_IRQ != -1 &&
849
            (s_IRQ == -1 ||
850
             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
851
            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
852
                    idx, n_IRQ);
853
            openpic_irq_raise(opp, idx, src);
854
        }
855
        break;
856
    default:
857
        break;
858
    }
859
}
860

    
861
static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
862
                              unsigned len)
863
{
864
    openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
865
}
866

    
867
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
868
                                          int idx)
869
{
870
    OpenPICState *opp = opaque;
871
    IRQ_src_t *src;
872
    IRQ_dst_t *dst;
873
    uint32_t retval;
874
    int n_IRQ;
875

    
876
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
877
    retval = 0xFFFFFFFF;
878
    if (addr & 0xF)
879
        return retval;
880
    dst = &opp->dst[idx];
881
    addr &= 0xFF0;
882
    switch (addr) {
883
    case 0x80: /* PCTP */
884
        retval = dst->pctp;
885
        break;
886
    case 0x90: /* WHOAMI */
887
        retval = idx;
888
        break;
889
    case 0xA0: /* PIAC */
890
        DPRINTF("Lower OpenPIC INT output\n");
891
        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
892
        n_IRQ = IRQ_get_next(opp, &dst->raised);
893
        DPRINTF("PIAC: irq=%d\n", n_IRQ);
894
        if (n_IRQ == -1) {
895
            /* No more interrupt pending */
896
            retval = opp->spve;
897
        } else {
898
            src = &opp->src[n_IRQ];
899
            if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
900
                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
901
                /* - Spurious level-sensitive IRQ
902
                 * - Priorities has been changed
903
                 *   and the pending IRQ isn't allowed anymore
904
                 */
905
                src->ipvp &= ~IPVP_ACTIVITY_MASK;
906
                retval = opp->spve;
907
            } else {
908
                /* IRQ enter servicing state */
909
                IRQ_setbit(&dst->servicing, n_IRQ);
910
                retval = IPVP_VECTOR(opp, src->ipvp);
911
            }
912
            IRQ_resetbit(&dst->raised, n_IRQ);
913
            dst->raised.next = -1;
914
            if (!(src->ipvp & IPVP_SENSE_MASK)) {
915
                /* edge-sensitive IRQ */
916
                src->ipvp &= ~IPVP_ACTIVITY_MASK;
917
                src->pending = 0;
918
            }
919

    
920
            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
921
                src->ide &= ~(1 << idx);
922
                if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
923
                    /* trigger on CPUs that didn't know about it yet */
924
                    openpic_set_irq(opp, n_IRQ, 1);
925
                    openpic_set_irq(opp, n_IRQ, 0);
926
                    /* if all CPUs knew about it, set active bit again */
927
                    src->ipvp |= IPVP_ACTIVITY_MASK;
928
                }
929
            }
930
        }
931
        break;
932
    case 0xB0: /* PEOI */
933
        retval = 0;
934
        break;
935
    default:
936
        break;
937
    }
938
    DPRINTF("%s: => %08x\n", __func__, retval);
939

    
940
    return retval;
941
}
942

    
943
static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
944
{
945
    return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
946
}
947

    
948
static const MemoryRegionOps openpic_glb_ops_le = {
949
    .write = openpic_gbl_write,
950
    .read  = openpic_gbl_read,
951
    .endianness = DEVICE_LITTLE_ENDIAN,
952
    .impl = {
953
        .min_access_size = 4,
954
        .max_access_size = 4,
955
    },
956
};
957

    
958
static const MemoryRegionOps openpic_glb_ops_be = {
959
    .write = openpic_gbl_write,
960
    .read  = openpic_gbl_read,
961
    .endianness = DEVICE_BIG_ENDIAN,
962
    .impl = {
963
        .min_access_size = 4,
964
        .max_access_size = 4,
965
    },
966
};
967

    
968
static const MemoryRegionOps openpic_tmr_ops_le = {
969
    .write = openpic_tmr_write,
970
    .read  = openpic_tmr_read,
971
    .endianness = DEVICE_LITTLE_ENDIAN,
972
    .impl = {
973
        .min_access_size = 4,
974
        .max_access_size = 4,
975
    },
976
};
977

    
978
static const MemoryRegionOps openpic_tmr_ops_be = {
979
    .write = openpic_tmr_write,
980
    .read  = openpic_tmr_read,
981
    .endianness = DEVICE_BIG_ENDIAN,
982
    .impl = {
983
        .min_access_size = 4,
984
        .max_access_size = 4,
985
    },
986
};
987

    
988
static const MemoryRegionOps openpic_cpu_ops_le = {
989
    .write = openpic_cpu_write,
990
    .read  = openpic_cpu_read,
991
    .endianness = DEVICE_LITTLE_ENDIAN,
992
    .impl = {
993
        .min_access_size = 4,
994
        .max_access_size = 4,
995
    },
996
};
997

    
998
static const MemoryRegionOps openpic_cpu_ops_be = {
999
    .write = openpic_cpu_write,
1000
    .read  = openpic_cpu_read,
1001
    .endianness = DEVICE_BIG_ENDIAN,
1002
    .impl = {
1003
        .min_access_size = 4,
1004
        .max_access_size = 4,
1005
    },
1006
};
1007

    
1008
static const MemoryRegionOps openpic_src_ops_le = {
1009
    .write = openpic_src_write,
1010
    .read  = openpic_src_read,
1011
    .endianness = DEVICE_LITTLE_ENDIAN,
1012
    .impl = {
1013
        .min_access_size = 4,
1014
        .max_access_size = 4,
1015
    },
1016
};
1017

    
1018
static const MemoryRegionOps openpic_src_ops_be = {
1019
    .write = openpic_src_write,
1020
    .read  = openpic_src_read,
1021
    .endianness = DEVICE_BIG_ENDIAN,
1022
    .impl = {
1023
        .min_access_size = 4,
1024
        .max_access_size = 4,
1025
    },
1026
};
1027

    
1028
static const MemoryRegionOps openpic_msi_ops_le = {
1029
    .read = openpic_msi_read,
1030
    .write = openpic_msi_write,
1031
    .endianness = DEVICE_LITTLE_ENDIAN,
1032
    .impl = {
1033
        .min_access_size = 4,
1034
        .max_access_size = 4,
1035
    },
1036
};
1037

    
1038
static const MemoryRegionOps openpic_msi_ops_be = {
1039
    .read = openpic_msi_read,
1040
    .write = openpic_msi_write,
1041
    .endianness = DEVICE_BIG_ENDIAN,
1042
    .impl = {
1043
        .min_access_size = 4,
1044
        .max_access_size = 4,
1045
    },
1046
};
1047

    
1048
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1049
{
1050
    unsigned int i;
1051

    
1052
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1053
        qemu_put_be32s(f, &q->queue[i]);
1054

    
1055
    qemu_put_sbe32s(f, &q->next);
1056
    qemu_put_sbe32s(f, &q->priority);
1057
}
1058

    
1059
static void openpic_save(QEMUFile* f, void *opaque)
1060
{
1061
    OpenPICState *opp = (OpenPICState *)opaque;
1062
    unsigned int i;
1063

    
1064
    qemu_put_be32s(f, &opp->glbc);
1065
    qemu_put_be32s(f, &opp->veni);
1066
    qemu_put_be32s(f, &opp->pint);
1067
    qemu_put_be32s(f, &opp->spve);
1068
    qemu_put_be32s(f, &opp->tifr);
1069

    
1070
    for (i = 0; i < opp->max_irq; i++) {
1071
        qemu_put_be32s(f, &opp->src[i].ipvp);
1072
        qemu_put_be32s(f, &opp->src[i].ide);
1073
        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1074
        qemu_put_sbe32s(f, &opp->src[i].pending);
1075
    }
1076

    
1077
    qemu_put_be32s(f, &opp->nb_cpus);
1078

    
1079
    for (i = 0; i < opp->nb_cpus; i++) {
1080
        qemu_put_be32s(f, &opp->dst[i].pctp);
1081
        openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1082
        openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1083
    }
1084

    
1085
    for (i = 0; i < MAX_TMR; i++) {
1086
        qemu_put_be32s(f, &opp->timers[i].ticc);
1087
        qemu_put_be32s(f, &opp->timers[i].tibc);
1088
    }
1089
}
1090

    
1091
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1092
{
1093
    unsigned int i;
1094

    
1095
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1096
        qemu_get_be32s(f, &q->queue[i]);
1097

    
1098
    qemu_get_sbe32s(f, &q->next);
1099
    qemu_get_sbe32s(f, &q->priority);
1100
}
1101

    
1102
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1103
{
1104
    OpenPICState *opp = (OpenPICState *)opaque;
1105
    unsigned int i;
1106

    
1107
    if (version_id != 1)
1108
        return -EINVAL;
1109

    
1110
    qemu_get_be32s(f, &opp->glbc);
1111
    qemu_get_be32s(f, &opp->veni);
1112
    qemu_get_be32s(f, &opp->pint);
1113
    qemu_get_be32s(f, &opp->spve);
1114
    qemu_get_be32s(f, &opp->tifr);
1115

    
1116
    for (i = 0; i < opp->max_irq; i++) {
1117
        qemu_get_be32s(f, &opp->src[i].ipvp);
1118
        qemu_get_be32s(f, &opp->src[i].ide);
1119
        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1120
        qemu_get_sbe32s(f, &opp->src[i].pending);
1121
    }
1122

    
1123
    qemu_get_be32s(f, &opp->nb_cpus);
1124

    
1125
    for (i = 0; i < opp->nb_cpus; i++) {
1126
        qemu_get_be32s(f, &opp->dst[i].pctp);
1127
        openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1128
        openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1129
    }
1130

    
1131
    for (i = 0; i < MAX_TMR; i++) {
1132
        qemu_get_be32s(f, &opp->timers[i].ticc);
1133
        qemu_get_be32s(f, &opp->timers[i].tibc);
1134
    }
1135

    
1136
    return 0;
1137
}
1138

    
1139
static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
1140
{
1141
    int n_ci = IDR_CI0_SHIFT - n_CPU;
1142

    
1143
    if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
1144
        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1145
    } else {
1146
        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1147
    }
1148
}
1149

    
1150
struct memreg {
1151
    const char             *name;
1152
    MemoryRegionOps const  *ops;
1153
    bool                   map;
1154
    hwaddr      start_addr;
1155
    ram_addr_t              size;
1156
};
1157

    
1158
static int openpic_init(SysBusDevice *dev)
1159
{
1160
    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
1161
    int i, j;
1162
    struct memreg list_le[] = {
1163
        {"glb", &openpic_glb_ops_le, true,
1164
                OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1165
        {"tmr", &openpic_tmr_ops_le, true,
1166
                OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1167
        {"msi", &openpic_msi_ops_le, true,
1168
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1169
        {"src", &openpic_src_ops_le, true,
1170
                OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1171
        {"cpu", &openpic_cpu_ops_le, true,
1172
                OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1173
    };
1174
    struct memreg list_be[] = {
1175
        {"glb", &openpic_glb_ops_be, true,
1176
                OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1177
        {"tmr", &openpic_tmr_ops_be, true,
1178
                OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1179
        {"msi", &openpic_msi_ops_be, true,
1180
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1181
        {"src", &openpic_src_ops_be, true,
1182
                OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1183
        {"cpu", &openpic_cpu_ops_be, true,
1184
                OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1185
    };
1186
    struct memreg *list;
1187

    
1188
    switch (opp->model) {
1189
    case OPENPIC_MODEL_FSL_MPIC_20:
1190
    default:
1191
        opp->flags |= OPENPIC_FLAG_IDE_CRIT;
1192
        opp->nb_irqs = 80;
1193
        opp->vid = VID_REVISION_1_2;
1194
        opp->veni = VENI_GENERIC;
1195
        opp->vector_mask = 0xFFFF;
1196
        opp->tifr_reset = 0;
1197
        opp->ipvp_reset = IPVP_MASK_MASK;
1198
        opp->ide_reset = 1 << 0;
1199
        opp->max_irq = FSL_MPIC_20_MAX_IRQ;
1200
        opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
1201
        opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
1202
        opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
1203
        opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
1204
        msi_supported = true;
1205
        list = list_be;
1206
        break;
1207
    case OPENPIC_MODEL_RAVEN:
1208
        opp->nb_irqs = RAVEN_MAX_EXT;
1209
        opp->vid = VID_REVISION_1_3;
1210
        opp->veni = VENI_GENERIC;
1211
        opp->vector_mask = 0xFF;
1212
        opp->tifr_reset = 4160000;
1213
        opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
1214
        opp->ide_reset = 0;
1215
        opp->max_irq = RAVEN_MAX_IRQ;
1216
        opp->irq_ipi0 = RAVEN_IPI_IRQ;
1217
        opp->irq_tim0 = RAVEN_TMR_IRQ;
1218
        opp->brr1 = -1;
1219
        list = list_le;
1220
        /* Don't map MSI region */
1221
        list[2].map = false;
1222

    
1223
        /* Only UP supported today */
1224
        if (opp->nb_cpus != 1) {
1225
            return -EINVAL;
1226
        }
1227
        break;
1228
    }
1229

    
1230
    memory_region_init(&opp->mem, "openpic", 0x40000);
1231

    
1232
    for (i = 0; i < ARRAY_SIZE(list_le); i++) {
1233
        if (!list[i].map) {
1234
            continue;
1235
        }
1236

    
1237
        memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1238
                              list[i].name, list[i].size);
1239

    
1240
        memory_region_add_subregion(&opp->mem, list[i].start_addr,
1241
                                    &opp->sub_io_mem[i]);
1242
    }
1243

    
1244
    for (i = 0; i < opp->nb_cpus; i++) {
1245
        opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB);
1246
        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
1247
            sysbus_init_irq(dev, &opp->dst[i].irqs[j]);
1248
        }
1249
    }
1250

    
1251
    register_savevm(&opp->busdev.qdev, "openpic", 0, 2,
1252
                    openpic_save, openpic_load, opp);
1253

    
1254
    sysbus_init_mmio(dev, &opp->mem);
1255
    qdev_init_gpio_in(&dev->qdev, openpic_set_irq, opp->max_irq);
1256

    
1257
    return 0;
1258
}
1259

    
1260
static Property openpic_properties[] = {
1261
    DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_FSL_MPIC_20),
1262
    DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1),
1263
    DEFINE_PROP_END_OF_LIST(),
1264
};
1265

    
1266
static void openpic_class_init(ObjectClass *klass, void *data)
1267
{
1268
    DeviceClass *dc = DEVICE_CLASS(klass);
1269
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1270

    
1271
    k->init = openpic_init;
1272
    dc->props = openpic_properties;
1273
    dc->reset = openpic_reset;
1274
}
1275

    
1276
static TypeInfo openpic_info = {
1277
    .name          = "openpic",
1278
    .parent        = TYPE_SYS_BUS_DEVICE,
1279
    .instance_size = sizeof(OpenPICState),
1280
    .class_init    = openpic_class_init,
1281
};
1282

    
1283
static void openpic_register_types(void)
1284
{
1285
    type_register_static(&openpic_info);
1286
}
1287

    
1288
type_init(openpic_register_types)