qemu/hw/timer/aspeed_timer.c
<<
>>
Prefs
   1/*
   2 * ASPEED AST2400 Timer
   3 *
   4 * Andrew Jeffery <andrew@aj.id.au>
   5 *
   6 * Copyright (C) 2016 IBM Corp.
   7 *
   8 * This code is licensed under the GPL version 2 or later.  See
   9 * the COPYING file in the top-level directory.
  10 */
  11
  12#include "qemu/osdep.h"
  13#include "qapi/error.h"
  14#include "hw/irq.h"
  15#include "hw/sysbus.h"
  16#include "hw/timer/aspeed_timer.h"
  17#include "migration/vmstate.h"
  18#include "qemu/bitops.h"
  19#include "qemu/timer.h"
  20#include "qemu/log.h"
  21#include "qemu/module.h"
  22#include "trace.h"
  23
  24#define TIMER_NR_REGS 4
  25
  26#define TIMER_CTRL_BITS 4
  27#define TIMER_CTRL_MASK ((1 << TIMER_CTRL_BITS) - 1)
  28
  29#define TIMER_CLOCK_USE_EXT true
  30#define TIMER_CLOCK_EXT_HZ 1000000
  31#define TIMER_CLOCK_USE_APB false
  32
  33#define TIMER_REG_STATUS 0
  34#define TIMER_REG_RELOAD 1
  35#define TIMER_REG_MATCH_FIRST 2
  36#define TIMER_REG_MATCH_SECOND 3
  37
  38#define TIMER_FIRST_CAP_PULSE 4
  39
  40enum timer_ctrl_op {
  41    op_enable = 0,
  42    op_external_clock,
  43    op_overflow_interrupt,
  44    op_pulse_enable
  45};
  46
  47/*
  48 * Minimum value of the reload register to filter out short period
  49 * timers which have a noticeable impact in emulation. 5us should be
  50 * enough, use 20us for "safety".
  51 */
  52#define TIMER_MIN_NS (20 * SCALE_US)
  53
  54/**
  55 * Avoid mutual references between AspeedTimerCtrlState and AspeedTimer
  56 * structs, as it's a waste of memory. The ptimer BH callback needs to know
  57 * whether a specific AspeedTimer is enabled, but this information is held in
  58 * AspeedTimerCtrlState. So, provide a helper to hoist ourselves from an
  59 * arbitrary AspeedTimer to AspeedTimerCtrlState.
  60 */
  61static inline AspeedTimerCtrlState *timer_to_ctrl(AspeedTimer *t)
  62{
  63    const AspeedTimer (*timers)[] = (void *)t - (t->id * sizeof(*t));
  64    return container_of(timers, AspeedTimerCtrlState, timers);
  65}
  66
  67static inline bool timer_ctrl_status(AspeedTimer *t, enum timer_ctrl_op op)
  68{
  69    return !!(timer_to_ctrl(t)->ctrl & BIT(t->id * TIMER_CTRL_BITS + op));
  70}
  71
  72static inline bool timer_enabled(AspeedTimer *t)
  73{
  74    return timer_ctrl_status(t, op_enable);
  75}
  76
  77static inline bool timer_overflow_interrupt(AspeedTimer *t)
  78{
  79    return timer_ctrl_status(t, op_overflow_interrupt);
  80}
  81
  82static inline bool timer_can_pulse(AspeedTimer *t)
  83{
  84    return t->id >= TIMER_FIRST_CAP_PULSE;
  85}
  86
  87static inline bool timer_external_clock(AspeedTimer *t)
  88{
  89    return timer_ctrl_status(t, op_external_clock);
  90}
  91
  92static inline uint32_t calculate_rate(struct AspeedTimer *t)
  93{
  94    AspeedTimerCtrlState *s = timer_to_ctrl(t);
  95
  96    return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ :
  97        aspeed_scu_get_apb_freq(s->scu);
  98}
  99
 100static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
 101{
 102    uint64_t delta_ns = now_ns - MIN(now_ns, t->start);
 103    uint32_t rate = calculate_rate(t);
 104    uint64_t ticks = muldiv64(delta_ns, rate, NANOSECONDS_PER_SECOND);
 105
 106    return t->reload - MIN(t->reload, ticks);
 107}
 108
 109static uint32_t calculate_min_ticks(AspeedTimer *t, uint32_t value)
 110{
 111    uint32_t rate = calculate_rate(t);
 112    uint32_t min_ticks = muldiv64(TIMER_MIN_NS, rate, NANOSECONDS_PER_SECOND);
 113
 114    return  value < min_ticks ? min_ticks : value;
 115}
 116
 117static inline uint64_t calculate_time(struct AspeedTimer *t, uint32_t ticks)
 118{
 119    uint64_t delta_ns;
 120    uint64_t delta_ticks;
 121
 122    delta_ticks = t->reload - MIN(t->reload, ticks);
 123    delta_ns = muldiv64(delta_ticks, NANOSECONDS_PER_SECOND, calculate_rate(t));
 124
 125    return t->start + delta_ns;
 126}
 127
 128static inline uint32_t calculate_match(struct AspeedTimer *t, int i)
 129{
 130    return t->match[i] < t->reload ? t->match[i] : 0;
 131}
 132
 133static uint64_t calculate_next(struct AspeedTimer *t)
 134{
 135    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 136    uint64_t next;
 137
 138    /*
 139     * We don't know the relationship between the values in the match
 140     * registers, so sort using MAX/MIN/zero. We sort in that order as
 141     * the timer counts down to zero.
 142     */
 143
 144    next = calculate_time(t, MAX(calculate_match(t, 0), calculate_match(t, 1)));
 145    if (now < next) {
 146        return next;
 147    }
 148
 149    next = calculate_time(t, MIN(calculate_match(t, 0), calculate_match(t, 1)));
 150    if (now < next) {
 151        return next;
 152    }
 153
 154    next = calculate_time(t, 0);
 155    if (now < next) {
 156        return next;
 157    }
 158
 159    /* We've missed all deadlines, fire interrupt and try again */
 160    timer_del(&t->timer);
 161
 162    if (timer_overflow_interrupt(t)) {
 163        AspeedTimerCtrlState *s = timer_to_ctrl(t);
 164        t->level = !t->level;
 165        s->irq_sts |= BIT(t->id);
 166        qemu_set_irq(t->irq, t->level);
 167    }
 168
 169    next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0);
 170    t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 171
 172    return calculate_time(t, next);
 173}
 174
 175static void aspeed_timer_mod(AspeedTimer *t)
 176{
 177    uint64_t next = calculate_next(t);
 178    if (next) {
 179        timer_mod(&t->timer, next);
 180    }
 181}
 182
 183static void aspeed_timer_expire(void *opaque)
 184{
 185    AspeedTimer *t = opaque;
 186    bool interrupt = false;
 187    uint32_t ticks;
 188
 189    if (!timer_enabled(t)) {
 190        return;
 191    }
 192
 193    ticks = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 194
 195    if (!ticks) {
 196        interrupt = timer_overflow_interrupt(t) || !t->match[0] || !t->match[1];
 197    } else if (ticks <= MIN(t->match[0], t->match[1])) {
 198        interrupt = true;
 199    } else if (ticks <= MAX(t->match[0], t->match[1])) {
 200        interrupt = true;
 201    }
 202
 203    if (interrupt) {
 204        AspeedTimerCtrlState *s = timer_to_ctrl(t);
 205        t->level = !t->level;
 206        s->irq_sts |= BIT(t->id);
 207        qemu_set_irq(t->irq, t->level);
 208    }
 209
 210    aspeed_timer_mod(t);
 211}
 212
 213static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
 214{
 215    uint64_t value;
 216
 217    switch (reg) {
 218    case TIMER_REG_STATUS:
 219        if (timer_enabled(t)) {
 220            value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 221        } else {
 222            value = t->reload;
 223        }
 224        break;
 225    case TIMER_REG_RELOAD:
 226        value = t->reload;
 227        break;
 228    case TIMER_REG_MATCH_FIRST:
 229    case TIMER_REG_MATCH_SECOND:
 230        value = t->match[reg - 2];
 231        break;
 232    default:
 233        qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
 234                      __func__, reg);
 235        value = 0;
 236        break;
 237    }
 238    return value;
 239}
 240
 241static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
 242{
 243    AspeedTimerCtrlState *s = opaque;
 244    const int reg = (offset & 0xf) / 4;
 245    uint64_t value;
 246
 247    switch (offset) {
 248    case 0x30: /* Control Register */
 249        value = s->ctrl;
 250        break;
 251    case 0x00 ... 0x2c: /* Timers 1 - 4 */
 252        value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
 253        break;
 254    case 0x40 ... 0x8c: /* Timers 5 - 8 */
 255        value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
 256        break;
 257    default:
 258        value = ASPEED_TIMER_GET_CLASS(s)->read(s, offset);
 259        break;
 260    }
 261    trace_aspeed_timer_read(offset, size, value);
 262    return value;
 263}
 264
 265static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
 266                                   uint32_t value)
 267{
 268    AspeedTimer *t;
 269    uint32_t old_reload;
 270
 271    trace_aspeed_timer_set_value(timer, reg, value);
 272    t = &s->timers[timer];
 273    switch (reg) {
 274    case TIMER_REG_RELOAD:
 275        old_reload = t->reload;
 276        t->reload = calculate_min_ticks(t, value);
 277
 278        /* If the reload value was not previously set, or zero, and
 279         * the current value is valid, try to start the timer if it is
 280         * enabled.
 281         */
 282        if (old_reload || !t->reload) {
 283            break;
 284        }
 285
 286    case TIMER_REG_STATUS:
 287        if (timer_enabled(t)) {
 288            uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 289            int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now);
 290            uint32_t rate = calculate_rate(t);
 291
 292            if (delta >= 0) {
 293                t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
 294            } else {
 295                t->start -= muldiv64(-delta, NANOSECONDS_PER_SECOND, rate);
 296            }
 297            aspeed_timer_mod(t);
 298        }
 299        break;
 300    case TIMER_REG_MATCH_FIRST:
 301    case TIMER_REG_MATCH_SECOND:
 302        t->match[reg - 2] = value;
 303        if (timer_enabled(t)) {
 304            aspeed_timer_mod(t);
 305        }
 306        break;
 307    default:
 308        qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
 309                      __func__, reg);
 310        break;
 311    }
 312}
 313
 314/* Control register operations are broken out into helpers that can be
 315 * explicitly called on aspeed_timer_reset(), but also from
 316 * aspeed_timer_ctrl_op().
 317 */
 318
 319static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
 320{
 321    trace_aspeed_timer_ctrl_enable(t->id, enable);
 322    if (enable) {
 323        t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 324        aspeed_timer_mod(t);
 325    } else {
 326        timer_del(&t->timer);
 327    }
 328}
 329
 330static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable)
 331{
 332    trace_aspeed_timer_ctrl_external_clock(t->id, enable);
 333}
 334
 335static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)
 336{
 337    trace_aspeed_timer_ctrl_overflow_interrupt(t->id, enable);
 338}
 339
 340static void aspeed_timer_ctrl_pulse_enable(AspeedTimer *t, bool enable)
 341{
 342    if (timer_can_pulse(t)) {
 343        trace_aspeed_timer_ctrl_pulse_enable(t->id, enable);
 344    } else {
 345        qemu_log_mask(LOG_GUEST_ERROR,
 346                "%s: Timer does not support pulse mode\n", __func__);
 347    }
 348}
 349
 350/**
 351 * Given the actions are fixed in number and completely described in helper
 352 * functions, dispatch with a lookup table rather than manage control flow with
 353 * a switch statement.
 354 */
 355static void (*const ctrl_ops[])(AspeedTimer *, bool) = {
 356    [op_enable] = aspeed_timer_ctrl_enable,
 357    [op_external_clock] = aspeed_timer_ctrl_external_clock,
 358    [op_overflow_interrupt] = aspeed_timer_ctrl_overflow_interrupt,
 359    [op_pulse_enable] = aspeed_timer_ctrl_pulse_enable,
 360};
 361
 362/**
 363 * Conditionally affect changes chosen by a timer's control bit.
 364 *
 365 * The aspeed_timer_ctrl_op() interface is convenient for the
 366 * aspeed_timer_set_ctrl() function as the "no change" early exit can be
 367 * calculated for all operations, which cleans up the caller code. However the
 368 * interface isn't convenient for the reset function where we want to enter a
 369 * specific state without artificially constructing old and new values that
 370 * will fall through the change guard (and motivates extracting the actions
 371 * out to helper functions).
 372 *
 373 * @t: The timer to manipulate
 374 * @op: The type of operation to be performed
 375 * @old: The old state of the timer's control bits
 376 * @new: The incoming state for the timer's control bits
 377 */
 378static void aspeed_timer_ctrl_op(AspeedTimer *t, enum timer_ctrl_op op,
 379                                 uint8_t old, uint8_t new)
 380{
 381    const uint8_t mask = BIT(op);
 382    const bool enable = !!(new & mask);
 383    const bool changed = ((old ^ new) & mask);
 384    if (!changed) {
 385        return;
 386    }
 387    ctrl_ops[op](t, enable);
 388}
 389
 390static void aspeed_timer_set_ctrl(AspeedTimerCtrlState *s, uint32_t reg)
 391{
 392    int i;
 393    int shift;
 394    uint8_t t_old, t_new;
 395    AspeedTimer *t;
 396    const uint8_t enable_mask = BIT(op_enable);
 397
 398    /* Handle a dependency between the 'enable' and remaining three
 399     * configuration bits - i.e. if more than one bit in the control set has
 400     * changed, including the 'enable' bit, then we want either disable the
 401     * timer and perform configuration, or perform configuration and then
 402     * enable the timer
 403     */
 404    for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
 405        t = &s->timers[i];
 406        shift = (i * TIMER_CTRL_BITS);
 407        t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
 408        t_new = (reg >> shift) & TIMER_CTRL_MASK;
 409
 410        /* If we are disabling, do so first */
 411        if ((t_old & enable_mask) && !(t_new & enable_mask)) {
 412            aspeed_timer_ctrl_enable(t, false);
 413        }
 414        aspeed_timer_ctrl_op(t, op_external_clock, t_old, t_new);
 415        aspeed_timer_ctrl_op(t, op_overflow_interrupt, t_old, t_new);
 416        aspeed_timer_ctrl_op(t, op_pulse_enable, t_old, t_new);
 417        /* If we are enabling, do so last */
 418        if (!(t_old & enable_mask) && (t_new & enable_mask)) {
 419            aspeed_timer_ctrl_enable(t, true);
 420        }
 421    }
 422    s->ctrl = reg;
 423}
 424
 425static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
 426{
 427    trace_aspeed_timer_set_ctrl2(value);
 428}
 429
 430static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
 431                               unsigned size)
 432{
 433    const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
 434    const int reg = (offset & 0xf) / 4;
 435    AspeedTimerCtrlState *s = opaque;
 436
 437    switch (offset) {
 438    /* Control Registers */
 439    case 0x30:
 440        aspeed_timer_set_ctrl(s, tv);
 441        break;
 442    /* Timer Registers */
 443    case 0x00 ... 0x2c:
 444        aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
 445        break;
 446    case 0x40 ... 0x8c:
 447        aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
 448        break;
 449    default:
 450        ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value);
 451        break;
 452    }
 453}
 454
 455static const MemoryRegionOps aspeed_timer_ops = {
 456    .read = aspeed_timer_read,
 457    .write = aspeed_timer_write,
 458    .endianness = DEVICE_LITTLE_ENDIAN,
 459    .valid.min_access_size = 4,
 460    .valid.max_access_size = 4,
 461    .valid.unaligned = false,
 462};
 463
 464static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
 465{
 466    uint64_t value;
 467
 468    switch (offset) {
 469    case 0x34:
 470        value = s->ctrl2;
 471        break;
 472    case 0x38:
 473    case 0x3C:
 474    default:
 475        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 476                __func__, offset);
 477        value = 0;
 478        break;
 479    }
 480    return value;
 481}
 482
 483static void aspeed_2400_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
 484                                    uint64_t value)
 485{
 486    const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
 487
 488    switch (offset) {
 489    case 0x34:
 490        aspeed_timer_set_ctrl2(s, tv);
 491        break;
 492    case 0x38:
 493    case 0x3C:
 494    default:
 495        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 496                __func__, offset);
 497        break;
 498    }
 499}
 500
 501static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
 502{
 503    uint64_t value;
 504
 505    switch (offset) {
 506    case 0x34:
 507        value = s->ctrl2;
 508        break;
 509    case 0x38:
 510        value = s->ctrl3 & BIT(0);
 511        break;
 512    case 0x3C:
 513    default:
 514        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 515                __func__, offset);
 516        value = 0;
 517        break;
 518    }
 519    return value;
 520}
 521
 522static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
 523                                    uint64_t value)
 524{
 525    const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
 526    uint8_t command;
 527
 528    switch (offset) {
 529    case 0x34:
 530        aspeed_timer_set_ctrl2(s, tv);
 531        break;
 532    case 0x38:
 533        command = (value >> 1) & 0xFF;
 534        if (command == 0xAE) {
 535            s->ctrl3 = 0x1;
 536        } else if (command == 0xEA) {
 537            s->ctrl3 = 0x0;
 538        }
 539        break;
 540    case 0x3C:
 541        if (s->ctrl3 & BIT(0)) {
 542            aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
 543        }
 544        break;
 545
 546    default:
 547        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 548                __func__, offset);
 549        break;
 550    }
 551}
 552
 553static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
 554{
 555    uint64_t value;
 556
 557    switch (offset) {
 558    case 0x34:
 559        value = s->irq_sts;
 560        break;
 561    case 0x38:
 562    case 0x3C:
 563    default:
 564        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 565                __func__, offset);
 566        value = 0;
 567        break;
 568    }
 569    return value;
 570}
 571
 572static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
 573                                    uint64_t value)
 574{
 575    const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
 576
 577    switch (offset) {
 578    case 0x34:
 579        s->irq_sts &= tv;
 580        break;
 581    case 0x3C:
 582        aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
 583        break;
 584
 585    case 0x38:
 586    default:
 587        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 588                __func__, offset);
 589        break;
 590    }
 591}
 592
 593static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
 594{
 595    AspeedTimer *t = &s->timers[id];
 596
 597    t->id = id;
 598    timer_init_ns(&t->timer, QEMU_CLOCK_VIRTUAL, aspeed_timer_expire, t);
 599}
 600
 601static void aspeed_timer_realize(DeviceState *dev, Error **errp)
 602{
 603    int i;
 604    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 605    AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
 606    Object *obj;
 607    Error *err = NULL;
 608
 609    obj = object_property_get_link(OBJECT(dev), "scu", &err);
 610    if (!obj) {
 611        error_propagate_prepend(errp, err, "required link 'scu' not found: ");
 612        return;
 613    }
 614    s->scu = ASPEED_SCU(obj);
 615
 616    for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
 617        aspeed_init_one_timer(s, i);
 618        sysbus_init_irq(sbd, &s->timers[i].irq);
 619    }
 620    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_timer_ops, s,
 621                          TYPE_ASPEED_TIMER, 0x1000);
 622    sysbus_init_mmio(sbd, &s->iomem);
 623}
 624
 625static void aspeed_timer_reset(DeviceState *dev)
 626{
 627    int i;
 628    AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
 629
 630    for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
 631        AspeedTimer *t = &s->timers[i];
 632        /* Explicitly call helpers to avoid any conditional behaviour through
 633         * aspeed_timer_set_ctrl().
 634         */
 635        aspeed_timer_ctrl_enable(t, false);
 636        aspeed_timer_ctrl_external_clock(t, TIMER_CLOCK_USE_APB);
 637        aspeed_timer_ctrl_overflow_interrupt(t, false);
 638        aspeed_timer_ctrl_pulse_enable(t, false);
 639        t->level = 0;
 640        t->reload = 0;
 641        t->match[0] = 0;
 642        t->match[1] = 0;
 643    }
 644    s->ctrl = 0;
 645    s->ctrl2 = 0;
 646    s->ctrl3 = 0;
 647    s->irq_sts = 0;
 648}
 649
 650static const VMStateDescription vmstate_aspeed_timer = {
 651    .name = "aspeed.timer",
 652    .version_id = 2,
 653    .minimum_version_id = 2,
 654    .fields = (VMStateField[]) {
 655        VMSTATE_UINT8(id, AspeedTimer),
 656        VMSTATE_INT32(level, AspeedTimer),
 657        VMSTATE_TIMER(timer, AspeedTimer),
 658        VMSTATE_UINT32(reload, AspeedTimer),
 659        VMSTATE_UINT32_ARRAY(match, AspeedTimer, 2),
 660        VMSTATE_END_OF_LIST()
 661    }
 662};
 663
 664static const VMStateDescription vmstate_aspeed_timer_state = {
 665    .name = "aspeed.timerctrl",
 666    .version_id = 2,
 667    .minimum_version_id = 2,
 668    .fields = (VMStateField[]) {
 669        VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
 670        VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
 671        VMSTATE_UINT32(ctrl3, AspeedTimerCtrlState),
 672        VMSTATE_UINT32(irq_sts, AspeedTimerCtrlState),
 673        VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
 674                             ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
 675                             AspeedTimer),
 676        VMSTATE_END_OF_LIST()
 677    }
 678};
 679
 680static void timer_class_init(ObjectClass *klass, void *data)
 681{
 682    DeviceClass *dc = DEVICE_CLASS(klass);
 683
 684    dc->realize = aspeed_timer_realize;
 685    dc->reset = aspeed_timer_reset;
 686    dc->desc = "ASPEED Timer";
 687    dc->vmsd = &vmstate_aspeed_timer_state;
 688}
 689
 690static const TypeInfo aspeed_timer_info = {
 691    .name = TYPE_ASPEED_TIMER,
 692    .parent = TYPE_SYS_BUS_DEVICE,
 693    .instance_size = sizeof(AspeedTimerCtrlState),
 694    .class_init = timer_class_init,
 695    .class_size = sizeof(AspeedTimerClass),
 696    .abstract   = true,
 697};
 698
 699static void aspeed_2400_timer_class_init(ObjectClass *klass, void *data)
 700{
 701    DeviceClass *dc = DEVICE_CLASS(klass);
 702    AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
 703
 704    dc->desc = "ASPEED 2400 Timer";
 705    awc->read = aspeed_2400_timer_read;
 706    awc->write = aspeed_2400_timer_write;
 707}
 708
 709static const TypeInfo aspeed_2400_timer_info = {
 710    .name = TYPE_ASPEED_2400_TIMER,
 711    .parent = TYPE_ASPEED_TIMER,
 712    .class_init = aspeed_2400_timer_class_init,
 713};
 714
 715static void aspeed_2500_timer_class_init(ObjectClass *klass, void *data)
 716{
 717    DeviceClass *dc = DEVICE_CLASS(klass);
 718    AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
 719
 720    dc->desc = "ASPEED 2500 Timer";
 721    awc->read = aspeed_2500_timer_read;
 722    awc->write = aspeed_2500_timer_write;
 723}
 724
 725static const TypeInfo aspeed_2500_timer_info = {
 726    .name = TYPE_ASPEED_2500_TIMER,
 727    .parent = TYPE_ASPEED_TIMER,
 728    .class_init = aspeed_2500_timer_class_init,
 729};
 730
 731static void aspeed_2600_timer_class_init(ObjectClass *klass, void *data)
 732{
 733    DeviceClass *dc = DEVICE_CLASS(klass);
 734    AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
 735
 736    dc->desc = "ASPEED 2600 Timer";
 737    awc->read = aspeed_2600_timer_read;
 738    awc->write = aspeed_2600_timer_write;
 739}
 740
 741static const TypeInfo aspeed_2600_timer_info = {
 742    .name = TYPE_ASPEED_2600_TIMER,
 743    .parent = TYPE_ASPEED_TIMER,
 744    .class_init = aspeed_2600_timer_class_init,
 745};
 746
 747static void aspeed_timer_register_types(void)
 748{
 749    type_register_static(&aspeed_timer_info);
 750    type_register_static(&aspeed_2400_timer_info);
 751    type_register_static(&aspeed_2500_timer_info);
 752    type_register_static(&aspeed_2600_timer_info);
 753}
 754
 755type_init(aspeed_timer_register_types)
 756