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