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/sysbus.h"
  15#include "hw/timer/aspeed_timer.h"
  16#include "qemu/bitops.h"
  17#include "qemu/timer.h"
  18#include "qemu/log.h"
  19#include "qemu/module.h"
  20#include "trace.h"
  21
  22#define TIMER_NR_REGS 4
  23
  24#define TIMER_CTRL_BITS 4
  25#define TIMER_CTRL_MASK ((1 << TIMER_CTRL_BITS) - 1)
  26
  27#define TIMER_CLOCK_USE_EXT true
  28#define TIMER_CLOCK_EXT_HZ 1000000
  29#define TIMER_CLOCK_USE_APB false
  30
  31#define TIMER_REG_STATUS 0
  32#define TIMER_REG_RELOAD 1
  33#define TIMER_REG_MATCH_FIRST 2
  34#define TIMER_REG_MATCH_SECOND 3
  35
  36#define TIMER_FIRST_CAP_PULSE 4
  37
  38enum timer_ctrl_op {
  39    op_enable = 0,
  40    op_external_clock,
  41    op_overflow_interrupt,
  42    op_pulse_enable
  43};
  44
  45/**
  46 * Avoid mutual references between AspeedTimerCtrlState and AspeedTimer
  47 * structs, as it's a waste of memory. The ptimer BH callback needs to know
  48 * whether a specific AspeedTimer is enabled, but this information is held in
  49 * AspeedTimerCtrlState. So, provide a helper to hoist ourselves from an
  50 * arbitrary AspeedTimer to AspeedTimerCtrlState.
  51 */
  52static inline AspeedTimerCtrlState *timer_to_ctrl(AspeedTimer *t)
  53{
  54    const AspeedTimer (*timers)[] = (void *)t - (t->id * sizeof(*t));
  55    return container_of(timers, AspeedTimerCtrlState, timers);
  56}
  57
  58static inline bool timer_ctrl_status(AspeedTimer *t, enum timer_ctrl_op op)
  59{
  60    return !!(timer_to_ctrl(t)->ctrl & BIT(t->id * TIMER_CTRL_BITS + op));
  61}
  62
  63static inline bool timer_enabled(AspeedTimer *t)
  64{
  65    return timer_ctrl_status(t, op_enable);
  66}
  67
  68static inline bool timer_overflow_interrupt(AspeedTimer *t)
  69{
  70    return timer_ctrl_status(t, op_overflow_interrupt);
  71}
  72
  73static inline bool timer_can_pulse(AspeedTimer *t)
  74{
  75    return t->id >= TIMER_FIRST_CAP_PULSE;
  76}
  77
  78static inline bool timer_external_clock(AspeedTimer *t)
  79{
  80    return timer_ctrl_status(t, op_external_clock);
  81}
  82
  83static inline uint32_t calculate_rate(struct AspeedTimer *t)
  84{
  85    AspeedTimerCtrlState *s = timer_to_ctrl(t);
  86
  87    return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq;
  88}
  89
  90static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
  91{
  92    uint64_t delta_ns = now_ns - MIN(now_ns, t->start);
  93    uint32_t rate = calculate_rate(t);
  94    uint64_t ticks = muldiv64(delta_ns, rate, NANOSECONDS_PER_SECOND);
  95
  96    return t->reload - MIN(t->reload, ticks);
  97}
  98
  99static inline uint64_t calculate_time(struct AspeedTimer *t, uint32_t ticks)
 100{
 101    uint64_t delta_ns;
 102    uint64_t delta_ticks;
 103
 104    delta_ticks = t->reload - MIN(t->reload, ticks);
 105    delta_ns = muldiv64(delta_ticks, NANOSECONDS_PER_SECOND, calculate_rate(t));
 106
 107    return t->start + delta_ns;
 108}
 109
 110static inline uint32_t calculate_match(struct AspeedTimer *t, int i)
 111{
 112    return t->match[i] < t->reload ? t->match[i] : 0;
 113}
 114
 115static uint64_t calculate_next(struct AspeedTimer *t)
 116{
 117    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 118    uint64_t next;
 119
 120    /*
 121     * We don't know the relationship between the values in the match
 122     * registers, so sort using MAX/MIN/zero. We sort in that order as
 123     * the timer counts down to zero.
 124     */
 125
 126    next = calculate_time(t, MAX(calculate_match(t, 0), calculate_match(t, 1)));
 127    if (now < next) {
 128        return next;
 129    }
 130
 131    next = calculate_time(t, MIN(calculate_match(t, 0), calculate_match(t, 1)));
 132    if (now < next) {
 133        return next;
 134    }
 135
 136    next = calculate_time(t, 0);
 137    if (now < next) {
 138        return next;
 139    }
 140
 141    /* We've missed all deadlines, fire interrupt and try again */
 142    timer_del(&t->timer);
 143
 144    if (timer_overflow_interrupt(t)) {
 145        t->level = !t->level;
 146        qemu_set_irq(t->irq, t->level);
 147    }
 148
 149    next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0);
 150    t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 151
 152    return calculate_time(t, next);
 153}
 154
 155static void aspeed_timer_mod(AspeedTimer *t)
 156{
 157    uint64_t next = calculate_next(t);
 158    if (next) {
 159        timer_mod(&t->timer, next);
 160    }
 161}
 162
 163static void aspeed_timer_expire(void *opaque)
 164{
 165    AspeedTimer *t = opaque;
 166    bool interrupt = false;
 167    uint32_t ticks;
 168
 169    if (!timer_enabled(t)) {
 170        return;
 171    }
 172
 173    ticks = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 174
 175    if (!ticks) {
 176        interrupt = timer_overflow_interrupt(t) || !t->match[0] || !t->match[1];
 177    } else if (ticks <= MIN(t->match[0], t->match[1])) {
 178        interrupt = true;
 179    } else if (ticks <= MAX(t->match[0], t->match[1])) {
 180        interrupt = true;
 181    }
 182
 183    if (interrupt) {
 184        t->level = !t->level;
 185        qemu_set_irq(t->irq, t->level);
 186    }
 187
 188    aspeed_timer_mod(t);
 189}
 190
 191static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
 192{
 193    uint64_t value;
 194
 195    switch (reg) {
 196    case TIMER_REG_STATUS:
 197        if (timer_enabled(t)) {
 198            value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 199        } else {
 200            value = t->reload;
 201        }
 202        break;
 203    case TIMER_REG_RELOAD:
 204        value = t->reload;
 205        break;
 206    case TIMER_REG_MATCH_FIRST:
 207    case TIMER_REG_MATCH_SECOND:
 208        value = t->match[reg - 2];
 209        break;
 210    default:
 211        qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
 212                      __func__, reg);
 213        value = 0;
 214        break;
 215    }
 216    return value;
 217}
 218
 219static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
 220{
 221    AspeedTimerCtrlState *s = opaque;
 222    const int reg = (offset & 0xf) / 4;
 223    uint64_t value;
 224
 225    switch (offset) {
 226    case 0x30: /* Control Register */
 227        value = s->ctrl;
 228        break;
 229    case 0x34: /* Control Register 2 */
 230        value = s->ctrl2;
 231        break;
 232    case 0x00 ... 0x2c: /* Timers 1 - 4 */
 233        value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
 234        break;
 235    case 0x40 ... 0x8c: /* Timers 5 - 8 */
 236        value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
 237        break;
 238    /* Illegal */
 239    case 0x38:
 240    case 0x3C:
 241    default:
 242        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 243                __func__, offset);
 244        value = 0;
 245        break;
 246    }
 247    trace_aspeed_timer_read(offset, size, value);
 248    return value;
 249}
 250
 251static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
 252                                   uint32_t value)
 253{
 254    AspeedTimer *t;
 255    uint32_t old_reload;
 256
 257    trace_aspeed_timer_set_value(timer, reg, value);
 258    t = &s->timers[timer];
 259    switch (reg) {
 260    case TIMER_REG_RELOAD:
 261        old_reload = t->reload;
 262        t->reload = value;
 263
 264        /* If the reload value was not previously set, or zero, and
 265         * the current value is valid, try to start the timer if it is
 266         * enabled.
 267         */
 268        if (old_reload || !t->reload) {
 269            break;
 270        }
 271
 272    case TIMER_REG_STATUS:
 273        if (timer_enabled(t)) {
 274            uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 275            int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now);
 276            uint32_t rate = calculate_rate(t);
 277
 278            if (delta >= 0) {
 279                t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
 280            } else {
 281                t->start -= muldiv64(-delta, NANOSECONDS_PER_SECOND, rate);
 282            }
 283            aspeed_timer_mod(t);
 284        }
 285        break;
 286    case TIMER_REG_MATCH_FIRST:
 287    case TIMER_REG_MATCH_SECOND:
 288        t->match[reg - 2] = value;
 289        if (timer_enabled(t)) {
 290            aspeed_timer_mod(t);
 291        }
 292        break;
 293    default:
 294        qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
 295                      __func__, reg);
 296        break;
 297    }
 298}
 299
 300/* Control register operations are broken out into helpers that can be
 301 * explicitly called on aspeed_timer_reset(), but also from
 302 * aspeed_timer_ctrl_op().
 303 */
 304
 305static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
 306{
 307    trace_aspeed_timer_ctrl_enable(t->id, enable);
 308    if (enable) {
 309        t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 310        aspeed_timer_mod(t);
 311    } else {
 312        timer_del(&t->timer);
 313    }
 314}
 315
 316static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable)
 317{
 318    trace_aspeed_timer_ctrl_external_clock(t->id, enable);
 319}
 320
 321static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)
 322{
 323    trace_aspeed_timer_ctrl_overflow_interrupt(t->id, enable);
 324}
 325
 326static void aspeed_timer_ctrl_pulse_enable(AspeedTimer *t, bool enable)
 327{
 328    if (timer_can_pulse(t)) {
 329        trace_aspeed_timer_ctrl_pulse_enable(t->id, enable);
 330    } else {
 331        qemu_log_mask(LOG_GUEST_ERROR,
 332                "%s: Timer does not support pulse mode\n", __func__);
 333    }
 334}
 335
 336/**
 337 * Given the actions are fixed in number and completely described in helper
 338 * functions, dispatch with a lookup table rather than manage control flow with
 339 * a switch statement.
 340 */
 341static void (*const ctrl_ops[])(AspeedTimer *, bool) = {
 342    [op_enable] = aspeed_timer_ctrl_enable,
 343    [op_external_clock] = aspeed_timer_ctrl_external_clock,
 344    [op_overflow_interrupt] = aspeed_timer_ctrl_overflow_interrupt,
 345    [op_pulse_enable] = aspeed_timer_ctrl_pulse_enable,
 346};
 347
 348/**
 349 * Conditionally affect changes chosen by a timer's control bit.
 350 *
 351 * The aspeed_timer_ctrl_op() interface is convenient for the
 352 * aspeed_timer_set_ctrl() function as the "no change" early exit can be
 353 * calculated for all operations, which cleans up the caller code. However the
 354 * interface isn't convenient for the reset function where we want to enter a
 355 * specific state without artificially constructing old and new values that
 356 * will fall through the change guard (and motivates extracting the actions
 357 * out to helper functions).
 358 *
 359 * @t: The timer to manipulate
 360 * @op: The type of operation to be performed
 361 * @old: The old state of the timer's control bits
 362 * @new: The incoming state for the timer's control bits
 363 */
 364static void aspeed_timer_ctrl_op(AspeedTimer *t, enum timer_ctrl_op op,
 365                                 uint8_t old, uint8_t new)
 366{
 367    const uint8_t mask = BIT(op);
 368    const bool enable = !!(new & mask);
 369    const bool changed = ((old ^ new) & mask);
 370    if (!changed) {
 371        return;
 372    }
 373    ctrl_ops[op](t, enable);
 374}
 375
 376static void aspeed_timer_set_ctrl(AspeedTimerCtrlState *s, uint32_t reg)
 377{
 378    int i;
 379    int shift;
 380    uint8_t t_old, t_new;
 381    AspeedTimer *t;
 382    const uint8_t enable_mask = BIT(op_enable);
 383
 384    /* Handle a dependency between the 'enable' and remaining three
 385     * configuration bits - i.e. if more than one bit in the control set has
 386     * changed, including the 'enable' bit, then we want either disable the
 387     * timer and perform configuration, or perform configuration and then
 388     * enable the timer
 389     */
 390    for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
 391        t = &s->timers[i];
 392        shift = (i * TIMER_CTRL_BITS);
 393        t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
 394        t_new = (reg >> shift) & TIMER_CTRL_MASK;
 395
 396        /* If we are disabling, do so first */
 397        if ((t_old & enable_mask) && !(t_new & enable_mask)) {
 398            aspeed_timer_ctrl_enable(t, false);
 399        }
 400        aspeed_timer_ctrl_op(t, op_external_clock, t_old, t_new);
 401        aspeed_timer_ctrl_op(t, op_overflow_interrupt, t_old, t_new);
 402        aspeed_timer_ctrl_op(t, op_pulse_enable, t_old, t_new);
 403        /* If we are enabling, do so last */
 404        if (!(t_old & enable_mask) && (t_new & enable_mask)) {
 405            aspeed_timer_ctrl_enable(t, true);
 406        }
 407    }
 408    s->ctrl = reg;
 409}
 410
 411static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
 412{
 413    trace_aspeed_timer_set_ctrl2(value);
 414}
 415
 416static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
 417                               unsigned size)
 418{
 419    const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
 420    const int reg = (offset & 0xf) / 4;
 421    AspeedTimerCtrlState *s = opaque;
 422
 423    switch (offset) {
 424    /* Control Registers */
 425    case 0x30:
 426        aspeed_timer_set_ctrl(s, tv);
 427        break;
 428    case 0x34:
 429        aspeed_timer_set_ctrl2(s, tv);
 430        break;
 431    /* Timer Registers */
 432    case 0x00 ... 0x2c:
 433        aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
 434        break;
 435    case 0x40 ... 0x8c:
 436        aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
 437        break;
 438    /* Illegal */
 439    case 0x38:
 440    case 0x3C:
 441    default:
 442        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
 443                __func__, offset);
 444        break;
 445    }
 446}
 447
 448static const MemoryRegionOps aspeed_timer_ops = {
 449    .read = aspeed_timer_read,
 450    .write = aspeed_timer_write,
 451    .endianness = DEVICE_LITTLE_ENDIAN,
 452    .valid.min_access_size = 4,
 453    .valid.max_access_size = 4,
 454    .valid.unaligned = false,
 455};
 456
 457static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
 458{
 459    AspeedTimer *t = &s->timers[id];
 460
 461    t->id = id;
 462    timer_init_ns(&t->timer, QEMU_CLOCK_VIRTUAL, aspeed_timer_expire, t);
 463}
 464
 465static void aspeed_timer_realize(DeviceState *dev, Error **errp)
 466{
 467    int i;
 468    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 469    AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
 470    Object *obj;
 471    Error *err = NULL;
 472
 473    obj = object_property_get_link(OBJECT(dev), "scu", &err);
 474    if (!obj) {
 475        error_propagate_prepend(errp, err, "required link 'scu' not found: ");
 476        return;
 477    }
 478    s->scu = ASPEED_SCU(obj);
 479
 480    for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
 481        aspeed_init_one_timer(s, i);
 482        sysbus_init_irq(sbd, &s->timers[i].irq);
 483    }
 484    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_timer_ops, s,
 485                          TYPE_ASPEED_TIMER, 0x1000);
 486    sysbus_init_mmio(sbd, &s->iomem);
 487}
 488
 489static void aspeed_timer_reset(DeviceState *dev)
 490{
 491    int i;
 492    AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
 493
 494    for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
 495        AspeedTimer *t = &s->timers[i];
 496        /* Explicitly call helpers to avoid any conditional behaviour through
 497         * aspeed_timer_set_ctrl().
 498         */
 499        aspeed_timer_ctrl_enable(t, false);
 500        aspeed_timer_ctrl_external_clock(t, TIMER_CLOCK_USE_APB);
 501        aspeed_timer_ctrl_overflow_interrupt(t, false);
 502        aspeed_timer_ctrl_pulse_enable(t, false);
 503        t->level = 0;
 504        t->reload = 0;
 505        t->match[0] = 0;
 506        t->match[1] = 0;
 507    }
 508    s->ctrl = 0;
 509    s->ctrl2 = 0;
 510}
 511
 512static const VMStateDescription vmstate_aspeed_timer = {
 513    .name = "aspeed.timer",
 514    .version_id = 2,
 515    .minimum_version_id = 2,
 516    .fields = (VMStateField[]) {
 517        VMSTATE_UINT8(id, AspeedTimer),
 518        VMSTATE_INT32(level, AspeedTimer),
 519        VMSTATE_TIMER(timer, AspeedTimer),
 520        VMSTATE_UINT32(reload, AspeedTimer),
 521        VMSTATE_UINT32_ARRAY(match, AspeedTimer, 2),
 522        VMSTATE_END_OF_LIST()
 523    }
 524};
 525
 526static const VMStateDescription vmstate_aspeed_timer_state = {
 527    .name = "aspeed.timerctrl",
 528    .version_id = 1,
 529    .minimum_version_id = 1,
 530    .fields = (VMStateField[]) {
 531        VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
 532        VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
 533        VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
 534                             ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
 535                             AspeedTimer),
 536        VMSTATE_END_OF_LIST()
 537    }
 538};
 539
 540static void timer_class_init(ObjectClass *klass, void *data)
 541{
 542    DeviceClass *dc = DEVICE_CLASS(klass);
 543
 544    dc->realize = aspeed_timer_realize;
 545    dc->reset = aspeed_timer_reset;
 546    dc->desc = "ASPEED Timer";
 547    dc->vmsd = &vmstate_aspeed_timer_state;
 548}
 549
 550static const TypeInfo aspeed_timer_info = {
 551    .name = TYPE_ASPEED_TIMER,
 552    .parent = TYPE_SYS_BUS_DEVICE,
 553    .instance_size = sizeof(AspeedTimerCtrlState),
 554    .class_init = timer_class_init,
 555};
 556
 557static void aspeed_timer_register_types(void)
 558{
 559    type_register_static(&aspeed_timer_info);
 560}
 561
 562type_init(aspeed_timer_register_types)
 563