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