2
0

armv7m_systick.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * ARMv7M SysTick timer
  3. *
  4. * Copyright (c) 2006-2007 CodeSourcery.
  5. * Written by Paul Brook
  6. * Copyright (c) 2017 Linaro Ltd
  7. * Written by Peter Maydell
  8. *
  9. * This code is licensed under the GPL (version 2 or later).
  10. */
  11. #include "qemu/osdep.h"
  12. #include "hw/timer/armv7m_systick.h"
  13. #include "migration/vmstate.h"
  14. #include "hw/irq.h"
  15. #include "hw/sysbus.h"
  16. #include "qemu/timer.h"
  17. #include "qemu/log.h"
  18. #include "qemu/module.h"
  19. #include "trace.h"
  20. /* qemu timers run at 1GHz. We want something closer to 1MHz. */
  21. #define SYSTICK_SCALE 1000ULL
  22. #define SYSTICK_ENABLE (1 << 0)
  23. #define SYSTICK_TICKINT (1 << 1)
  24. #define SYSTICK_CLKSOURCE (1 << 2)
  25. #define SYSTICK_COUNTFLAG (1 << 16)
  26. int system_clock_scale;
  27. /* Conversion factor from qemu timer to SysTick frequencies. */
  28. static inline int64_t systick_scale(SysTickState *s)
  29. {
  30. if (s->control & SYSTICK_CLKSOURCE) {
  31. return system_clock_scale;
  32. } else {
  33. return 1000;
  34. }
  35. }
  36. static void systick_reload(SysTickState *s, int reset)
  37. {
  38. /* The Cortex-M3 Devices Generic User Guide says that "When the
  39. * ENABLE bit is set to 1, the counter loads the RELOAD value from the
  40. * SYST RVR register and then counts down". So, we need to check the
  41. * ENABLE bit before reloading the value.
  42. */
  43. trace_systick_reload();
  44. if ((s->control & SYSTICK_ENABLE) == 0) {
  45. return;
  46. }
  47. if (reset) {
  48. s->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  49. }
  50. s->tick += (s->reload + 1) * systick_scale(s);
  51. timer_mod(s->timer, s->tick);
  52. }
  53. static void systick_timer_tick(void *opaque)
  54. {
  55. SysTickState *s = (SysTickState *)opaque;
  56. trace_systick_timer_tick();
  57. s->control |= SYSTICK_COUNTFLAG;
  58. if (s->control & SYSTICK_TICKINT) {
  59. /* Tell the NVIC to pend the SysTick exception */
  60. qemu_irq_pulse(s->irq);
  61. }
  62. if (s->reload == 0) {
  63. s->control &= ~SYSTICK_ENABLE;
  64. } else {
  65. systick_reload(s, 0);
  66. }
  67. }
  68. static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data,
  69. unsigned size, MemTxAttrs attrs)
  70. {
  71. SysTickState *s = opaque;
  72. uint32_t val;
  73. if (attrs.user) {
  74. /* Generate BusFault for unprivileged accesses */
  75. return MEMTX_ERROR;
  76. }
  77. switch (addr) {
  78. case 0x0: /* SysTick Control and Status. */
  79. val = s->control;
  80. s->control &= ~SYSTICK_COUNTFLAG;
  81. break;
  82. case 0x4: /* SysTick Reload Value. */
  83. val = s->reload;
  84. break;
  85. case 0x8: /* SysTick Current Value. */
  86. {
  87. int64_t t;
  88. if ((s->control & SYSTICK_ENABLE) == 0) {
  89. val = 0;
  90. break;
  91. }
  92. t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  93. if (t >= s->tick) {
  94. val = 0;
  95. break;
  96. }
  97. val = ((s->tick - (t + 1)) / systick_scale(s)) + 1;
  98. /* The interrupt in triggered when the timer reaches zero.
  99. However the counter is not reloaded until the next clock
  100. tick. This is a hack to return zero during the first tick. */
  101. if (val > s->reload) {
  102. val = 0;
  103. }
  104. break;
  105. }
  106. case 0xc: /* SysTick Calibration Value. */
  107. val = 10000;
  108. break;
  109. default:
  110. val = 0;
  111. qemu_log_mask(LOG_GUEST_ERROR,
  112. "SysTick: Bad read offset 0x%" HWADDR_PRIx "\n", addr);
  113. break;
  114. }
  115. trace_systick_read(addr, val, size);
  116. *data = val;
  117. return MEMTX_OK;
  118. }
  119. static MemTxResult systick_write(void *opaque, hwaddr addr,
  120. uint64_t value, unsigned size,
  121. MemTxAttrs attrs)
  122. {
  123. SysTickState *s = opaque;
  124. if (attrs.user) {
  125. /* Generate BusFault for unprivileged accesses */
  126. return MEMTX_ERROR;
  127. }
  128. trace_systick_write(addr, value, size);
  129. switch (addr) {
  130. case 0x0: /* SysTick Control and Status. */
  131. {
  132. uint32_t oldval = s->control;
  133. s->control &= 0xfffffff8;
  134. s->control |= value & 7;
  135. if ((oldval ^ value) & SYSTICK_ENABLE) {
  136. int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  137. if (value & SYSTICK_ENABLE) {
  138. if (s->tick) {
  139. s->tick += now;
  140. timer_mod(s->timer, s->tick);
  141. } else {
  142. systick_reload(s, 1);
  143. }
  144. } else {
  145. timer_del(s->timer);
  146. s->tick -= now;
  147. if (s->tick < 0) {
  148. s->tick = 0;
  149. }
  150. }
  151. } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
  152. /* This is a hack. Force the timer to be reloaded
  153. when the reference clock is changed. */
  154. systick_reload(s, 1);
  155. }
  156. break;
  157. }
  158. case 0x4: /* SysTick Reload Value. */
  159. s->reload = value;
  160. break;
  161. case 0x8: /* SysTick Current Value. Writes reload the timer. */
  162. systick_reload(s, 1);
  163. s->control &= ~SYSTICK_COUNTFLAG;
  164. break;
  165. default:
  166. qemu_log_mask(LOG_GUEST_ERROR,
  167. "SysTick: Bad write offset 0x%" HWADDR_PRIx "\n", addr);
  168. }
  169. return MEMTX_OK;
  170. }
  171. static const MemoryRegionOps systick_ops = {
  172. .read_with_attrs = systick_read,
  173. .write_with_attrs = systick_write,
  174. .endianness = DEVICE_NATIVE_ENDIAN,
  175. .valid.min_access_size = 4,
  176. .valid.max_access_size = 4,
  177. };
  178. static void systick_reset(DeviceState *dev)
  179. {
  180. SysTickState *s = SYSTICK(dev);
  181. /*
  182. * Forgetting to set system_clock_scale is always a board code
  183. * bug. We can't check this earlier because for some boards
  184. * (like stellaris) it is not yet configured at the point where
  185. * the systick device is realized.
  186. */
  187. assert(system_clock_scale != 0);
  188. s->control = 0;
  189. s->reload = 0;
  190. s->tick = 0;
  191. timer_del(s->timer);
  192. }
  193. static void systick_instance_init(Object *obj)
  194. {
  195. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  196. SysTickState *s = SYSTICK(obj);
  197. memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0);
  198. sysbus_init_mmio(sbd, &s->iomem);
  199. sysbus_init_irq(sbd, &s->irq);
  200. }
  201. static void systick_realize(DeviceState *dev, Error **errp)
  202. {
  203. SysTickState *s = SYSTICK(dev);
  204. s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
  205. }
  206. static const VMStateDescription vmstate_systick = {
  207. .name = "armv7m_systick",
  208. .version_id = 1,
  209. .minimum_version_id = 1,
  210. .fields = (VMStateField[]) {
  211. VMSTATE_UINT32(control, SysTickState),
  212. VMSTATE_UINT32(reload, SysTickState),
  213. VMSTATE_INT64(tick, SysTickState),
  214. VMSTATE_TIMER_PTR(timer, SysTickState),
  215. VMSTATE_END_OF_LIST()
  216. }
  217. };
  218. static void systick_class_init(ObjectClass *klass, void *data)
  219. {
  220. DeviceClass *dc = DEVICE_CLASS(klass);
  221. dc->vmsd = &vmstate_systick;
  222. dc->reset = systick_reset;
  223. dc->realize = systick_realize;
  224. }
  225. static const TypeInfo armv7m_systick_info = {
  226. .name = TYPE_SYSTICK,
  227. .parent = TYPE_SYS_BUS_DEVICE,
  228. .instance_init = systick_instance_init,
  229. .instance_size = sizeof(SysTickState),
  230. .class_init = systick_class_init,
  231. };
  232. static void armv7m_systick_register_types(void)
  233. {
  234. type_register_static(&armv7m_systick_info);
  235. }
  236. type_init(armv7m_systick_register_types)