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