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