nrf51_timer.c (11583B)
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)