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