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