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