xref: /openbmc/qemu/hw/timer/nrf51_timer.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
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  
26  static uint32_t const bitwidths[] = {16, 8, 24, 32};
27  
ns_to_ticks(NRF51TimerState * s,int64_t ns)28  static 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  
ticks_to_ns(NRF51TimerState * s,uint32_t ticks)35  static 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 */
update_counter(NRF51TimerState * s,int64_t now)43  static 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      /*
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);
54      return ticks;
55  }
56  
57  /* Assumes s->counter is up-to-date */
rearm_timer(NRF51TimerState * s,int64_t now)58  static 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  
update_irq(NRF51TimerState * s)87  static 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  
timer_expire(void * opaque)98  static 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  
counter_compare(NRF51TimerState * s)142  static 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  
nrf51_timer_read(void * opaque,hwaddr offset,unsigned int size)158  static 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  
194      trace_nrf51_timer_read(s->id, offset, r, size);
195  
196      return r;
197  }
198  
nrf51_timer_write(void * opaque,hwaddr offset,uint64_t value,unsigned int size)199  static 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  
206      trace_nrf51_timer_write(s->id, offset, value, size);
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;
248              trace_nrf51_timer_set_count(s->id, idx, s->counter);
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  
309  static 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  
nrf51_timer_init(Object * obj)317  static 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,
323                            TYPE_NRF51_TIMER, NRF51_PERIPHERAL_SIZE);
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  
nrf51_timer_reset(DeviceState * dev)330  static 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  
nrf51_timer_post_load(void * opaque,int version_id)350  static 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  
360  static const VMStateDescription vmstate_nrf51_timer = {
361      .name = TYPE_NRF51_TIMER,
362      .version_id = 1,
363      .post_load = nrf51_timer_post_load,
364      .fields = (const VMStateField[]) {
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  
382  static Property nrf51_timer_properties[] = {
383      DEFINE_PROP_UINT8("id", NRF51TimerState, id, 0),
384      DEFINE_PROP_END_OF_LIST(),
385  };
386  
nrf51_timer_class_init(ObjectClass * klass,void * data)387  static void nrf51_timer_class_init(ObjectClass *klass, void *data)
388  {
389      DeviceClass *dc = DEVICE_CLASS(klass);
390  
391      device_class_set_legacy_reset(dc, nrf51_timer_reset);
392      dc->vmsd = &vmstate_nrf51_timer;
393      device_class_set_props(dc, nrf51_timer_properties);
394  }
395  
396  static 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  
nrf51_timer_register_types(void)404  static void nrf51_timer_register_types(void)
405  {
406      type_register_static(&nrf51_timer_info);
407  }
408  
409  type_init(nrf51_timer_register_types)
410