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