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