qemu/hw/timer/nrf51_timer.c
<<
>>
Prefs
   1/*
   2 * nRF51 System-on-Chip Timer peripheral
   3 *
   4 * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
   5 * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
   6 *
   7 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
   8 * Copyright (c) 2019 Red Hat, Inc.
   9 *
  10 * This code is licensed under the GPL version 2 or later.  See
  11 * the COPYING file in the top-level directory.
  12 */
  13
  14#include "qemu/osdep.h"
  15#include "qemu/log.h"
  16#include "qemu/module.h"
  17#include "hw/arm/nrf51.h"
  18#include "hw/irq.h"
  19#include "hw/timer/nrf51_timer.h"
  20#include "migration/vmstate.h"
  21#include "trace.h"
  22
  23#define TIMER_CLK_FREQ 16000000UL
  24
  25static uint32_t const bitwidths[] = {16, 8, 24, 32};
  26
  27static uint32_t ns_to_ticks(NRF51TimerState *s, int64_t ns)
  28{
  29    uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
  30
  31    return muldiv64(ns, freq, NANOSECONDS_PER_SECOND);
  32}
  33
  34static int64_t ticks_to_ns(NRF51TimerState *s, uint32_t ticks)
  35{
  36    uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
  37
  38    return muldiv64(ticks, NANOSECONDS_PER_SECOND, freq);
  39}
  40
  41/* Returns number of ticks since last call */
  42static uint32_t update_counter(NRF51TimerState *s, int64_t now)
  43{
  44    uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
  45
  46    s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
  47    s->update_counter_ns = now;
  48    return ticks;
  49}
  50
  51/* Assumes s->counter is up-to-date */
  52static void rearm_timer(NRF51TimerState *s, int64_t now)
  53{
  54    int64_t min_ns = INT64_MAX;
  55    size_t i;
  56
  57    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
  58        int64_t delta_ns;
  59
  60        if (s->events_compare[i]) {
  61            continue; /* already expired, ignore it for now */
  62        }
  63
  64        if (s->cc[i] <= s->counter) {
  65            delta_ns = ticks_to_ns(s, BIT(bitwidths[s->bitmode]) -
  66                                      s->counter + s->cc[i]);
  67        } else {
  68            delta_ns = ticks_to_ns(s, s->cc[i] - s->counter);
  69        }
  70
  71        if (delta_ns < min_ns) {
  72            min_ns = delta_ns;
  73        }
  74    }
  75
  76    if (min_ns != INT64_MAX) {
  77        timer_mod_ns(&s->timer, now + min_ns);
  78    }
  79}
  80
  81static void update_irq(NRF51TimerState *s)
  82{
  83    bool flag = false;
  84    size_t i;
  85
  86    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
  87        flag |= s->events_compare[i] && extract32(s->inten, 16 + i, 1);
  88    }
  89    qemu_set_irq(s->irq, flag);
  90}
  91
  92static void timer_expire(void *opaque)
  93{
  94    NRF51TimerState *s = NRF51_TIMER(opaque);
  95    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  96    uint32_t cc_remaining[NRF51_TIMER_REG_COUNT];
  97    bool should_stop = false;
  98    uint32_t ticks;
  99    size_t i;
 100
 101    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
 102        if (s->cc[i] > s->counter) {
 103            cc_remaining[i] = s->cc[i] - s->counter;
 104        } else {
 105            cc_remaining[i] = BIT(bitwidths[s->bitmode]) -
 106                              s->counter + s->cc[i];
 107        }
 108    }
 109
 110    ticks = update_counter(s, now);
 111
 112    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
 113        if (cc_remaining[i] <= ticks) {
 114            s->events_compare[i] = 1;
 115
 116            if (s->shorts & BIT(i)) {
 117                s->timer_start_ns = now;
 118                s->update_counter_ns = s->timer_start_ns;
 119                s->counter = 0;
 120            }
 121
 122            should_stop |= s->shorts & BIT(i + 8);
 123        }
 124    }
 125
 126    update_irq(s);
 127
 128    if (should_stop) {
 129        s->running = false;
 130        timer_del(&s->timer);
 131    } else {
 132        rearm_timer(s, now);
 133    }
 134}
 135
 136static void counter_compare(NRF51TimerState *s)
 137{
 138    uint32_t counter = s->counter;
 139    size_t i;
 140
 141    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
 142        if (counter == s->cc[i]) {
 143            s->events_compare[i] = 1;
 144
 145            if (s->shorts & BIT(i)) {
 146                s->counter = 0;
 147            }
 148        }
 149    }
 150}
 151
 152static uint64_t nrf51_timer_read(void *opaque, hwaddr offset, unsigned int size)
 153{
 154    NRF51TimerState *s = NRF51_TIMER(opaque);
 155    uint64_t r = 0;
 156
 157    switch (offset) {
 158    case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
 159        r = s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4];
 160        break;
 161    case NRF51_TIMER_REG_SHORTS:
 162        r = s->shorts;
 163        break;
 164    case NRF51_TIMER_REG_INTENSET:
 165        r = s->inten;
 166        break;
 167    case NRF51_TIMER_REG_INTENCLR:
 168        r = s->inten;
 169        break;
 170    case NRF51_TIMER_REG_MODE:
 171        r = s->mode;
 172        break;
 173    case NRF51_TIMER_REG_BITMODE:
 174        r = s->bitmode;
 175        break;
 176    case NRF51_TIMER_REG_PRESCALER:
 177        r = s->prescaler;
 178        break;
 179    case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
 180        r = s->cc[(offset - NRF51_TIMER_REG_CC0) / 4];
 181        break;
 182    default:
 183        qemu_log_mask(LOG_GUEST_ERROR,
 184                "%s: bad read offset 0x%" HWADDR_PRIx "\n",
 185                      __func__, offset);
 186    }
 187
 188    trace_nrf51_timer_read(offset, r, size);
 189
 190    return r;
 191}
 192
 193static void nrf51_timer_write(void *opaque, hwaddr offset,
 194                       uint64_t value, unsigned int size)
 195{
 196    NRF51TimerState *s = NRF51_TIMER(opaque);
 197    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 198    size_t idx;
 199
 200    trace_nrf51_timer_write(offset, value, size);
 201
 202    switch (offset) {
 203    case NRF51_TIMER_TASK_START:
 204        if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_TIMER) {
 205            s->running = true;
 206            s->timer_start_ns = now - ticks_to_ns(s, s->counter);
 207            s->update_counter_ns = s->timer_start_ns;
 208            rearm_timer(s, now);
 209        }
 210        break;
 211    case NRF51_TIMER_TASK_STOP:
 212    case NRF51_TIMER_TASK_SHUTDOWN:
 213        if (value == NRF51_TRIGGER_TASK) {
 214            s->running = false;
 215            timer_del(&s->timer);
 216        }
 217        break;
 218    case NRF51_TIMER_TASK_COUNT:
 219        if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_COUNTER) {
 220            s->counter = (s->counter + 1) % BIT(bitwidths[s->bitmode]);
 221            counter_compare(s);
 222        }
 223        break;
 224    case NRF51_TIMER_TASK_CLEAR:
 225        if (value == NRF51_TRIGGER_TASK) {
 226            s->timer_start_ns = now;
 227            s->update_counter_ns = s->timer_start_ns;
 228            s->counter = 0;
 229            if (s->running) {
 230                rearm_timer(s, now);
 231            }
 232        }
 233        break;
 234    case NRF51_TIMER_TASK_CAPTURE_0 ... NRF51_TIMER_TASK_CAPTURE_3:
 235        if (value == NRF51_TRIGGER_TASK) {
 236            if (s->running) {
 237                timer_expire(s); /* update counter and all state */
 238            }
 239
 240            idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4;
 241            s->cc[idx] = s->counter;
 242        }
 243        break;
 244    case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
 245        if (value == NRF51_EVENT_CLEAR) {
 246            s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4] = 0;
 247
 248            if (s->running) {
 249                timer_expire(s); /* update counter and all state */
 250            }
 251        }
 252        break;
 253    case NRF51_TIMER_REG_SHORTS:
 254        s->shorts = value & NRF51_TIMER_REG_SHORTS_MASK;
 255        break;
 256    case NRF51_TIMER_REG_INTENSET:
 257        s->inten |= value & NRF51_TIMER_REG_INTEN_MASK;
 258        break;
 259    case NRF51_TIMER_REG_INTENCLR:
 260        s->inten &= ~(value & NRF51_TIMER_REG_INTEN_MASK);
 261        break;
 262    case NRF51_TIMER_REG_MODE:
 263        s->mode = value;
 264        break;
 265    case NRF51_TIMER_REG_BITMODE:
 266        if (s->mode == NRF51_TIMER_TIMER && s->running) {
 267            qemu_log_mask(LOG_GUEST_ERROR,
 268                    "%s: erroneous change of BITMODE while timer is running\n",
 269                    __func__);
 270        }
 271        s->bitmode = value & NRF51_TIMER_REG_BITMODE_MASK;
 272        break;
 273    case NRF51_TIMER_REG_PRESCALER:
 274        if (s->mode == NRF51_TIMER_TIMER && s->running) {
 275            qemu_log_mask(LOG_GUEST_ERROR,
 276                "%s: erroneous change of PRESCALER while timer is running\n",
 277                __func__);
 278        }
 279        s->prescaler = value & NRF51_TIMER_REG_PRESCALER_MASK;
 280        break;
 281    case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
 282        if (s->running) {
 283            timer_expire(s); /* update counter */
 284        }
 285
 286        idx = (offset - NRF51_TIMER_REG_CC0) / 4;
 287        s->cc[idx] = value % BIT(bitwidths[s->bitmode]);
 288
 289        if (s->running) {
 290            rearm_timer(s, now);
 291        }
 292        break;
 293    default:
 294        qemu_log_mask(LOG_GUEST_ERROR,
 295                      "%s: bad write offset 0x%" HWADDR_PRIx "\n",
 296                      __func__, offset);
 297    }
 298
 299    update_irq(s);
 300}
 301
 302static const MemoryRegionOps rng_ops = {
 303    .read =  nrf51_timer_read,
 304    .write = nrf51_timer_write,
 305    .endianness = DEVICE_LITTLE_ENDIAN,
 306    .impl.min_access_size = 4,
 307    .impl.max_access_size = 4,
 308};
 309
 310static void nrf51_timer_init(Object *obj)
 311{
 312    NRF51TimerState *s = NRF51_TIMER(obj);
 313    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 314
 315    memory_region_init_io(&s->iomem, obj, &rng_ops, s,
 316            TYPE_NRF51_TIMER, NRF51_TIMER_SIZE);
 317    sysbus_init_mmio(sbd, &s->iomem);
 318    sysbus_init_irq(sbd, &s->irq);
 319
 320    timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, timer_expire, s);
 321}
 322
 323static void nrf51_timer_reset(DeviceState *dev)
 324{
 325    NRF51TimerState *s = NRF51_TIMER(dev);
 326
 327    timer_del(&s->timer);
 328    s->timer_start_ns = 0x00;
 329    s->update_counter_ns = 0x00;
 330    s->counter = 0x00;
 331    s->running = false;
 332
 333    memset(s->events_compare, 0x00, sizeof(s->events_compare));
 334    memset(s->cc, 0x00, sizeof(s->cc));
 335
 336    s->shorts = 0x00;
 337    s->inten = 0x00;
 338    s->mode = 0x00;
 339    s->bitmode = 0x00;
 340    s->prescaler = 0x00;
 341}
 342
 343static int nrf51_timer_post_load(void *opaque, int version_id)
 344{
 345    NRF51TimerState *s = NRF51_TIMER(opaque);
 346
 347    if (s->running && s->mode == NRF51_TIMER_TIMER) {
 348        timer_expire(s);
 349    }
 350    return 0;
 351}
 352
 353static const VMStateDescription vmstate_nrf51_timer = {
 354    .name = TYPE_NRF51_TIMER,
 355    .version_id = 1,
 356    .post_load = nrf51_timer_post_load,
 357    .fields = (VMStateField[]) {
 358        VMSTATE_TIMER(timer, NRF51TimerState),
 359        VMSTATE_INT64(timer_start_ns, NRF51TimerState),
 360        VMSTATE_INT64(update_counter_ns, NRF51TimerState),
 361        VMSTATE_UINT32(counter, NRF51TimerState),
 362        VMSTATE_BOOL(running, NRF51TimerState),
 363        VMSTATE_UINT8_ARRAY(events_compare, NRF51TimerState,
 364                            NRF51_TIMER_REG_COUNT),
 365        VMSTATE_UINT32_ARRAY(cc, NRF51TimerState, NRF51_TIMER_REG_COUNT),
 366        VMSTATE_UINT32(shorts, NRF51TimerState),
 367        VMSTATE_UINT32(inten, NRF51TimerState),
 368        VMSTATE_UINT32(mode, NRF51TimerState),
 369        VMSTATE_UINT32(bitmode, NRF51TimerState),
 370        VMSTATE_UINT32(prescaler, NRF51TimerState),
 371        VMSTATE_END_OF_LIST()
 372    }
 373};
 374
 375static void nrf51_timer_class_init(ObjectClass *klass, void *data)
 376{
 377    DeviceClass *dc = DEVICE_CLASS(klass);
 378
 379    dc->reset = nrf51_timer_reset;
 380    dc->vmsd = &vmstate_nrf51_timer;
 381}
 382
 383static const TypeInfo nrf51_timer_info = {
 384    .name = TYPE_NRF51_TIMER,
 385    .parent = TYPE_SYS_BUS_DEVICE,
 386    .instance_size = sizeof(NRF51TimerState),
 387    .instance_init = nrf51_timer_init,
 388    .class_init = nrf51_timer_class_init
 389};
 390
 391static void nrf51_timer_register_types(void)
 392{
 393    type_register_static(&nrf51_timer_info);
 394}
 395
 396type_init(nrf51_timer_register_types)
 397