xref: /openbmc/qemu/hw/timer/nrf51_timer.c (revision f363d039)
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 
25 static uint32_t const bitwidths[] = {16, 8, 24, 32};
26 
27 static 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 
34 static 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 */
42 static 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 */
52 static 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 
81 static 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 
92 static 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 
136 static 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 
152 static 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 
193 static 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 
302 static 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 
310 static 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 
323 static 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 
343 static 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 
353 static 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 
375 static 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 
383 static 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 
391 static void nrf51_timer_register_types(void)
392 {
393     type_register_static(&nrf51_timer_info);
394 }
395 
396 type_init(nrf51_timer_register_types)
397