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