2
0

ibex_timer.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * QEMU lowRISC Ibex Timer device
  3. *
  4. * Copyright (c) 2021 Western Digital
  5. *
  6. * For details check the documentation here:
  7. * https://docs.opentitan.org/hw/ip/rv_timer/doc/
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include "qemu/osdep.h"
  28. #include "qemu/log.h"
  29. #include "qemu/timer.h"
  30. #include "hw/timer/ibex_timer.h"
  31. #include "hw/irq.h"
  32. #include "hw/qdev-properties.h"
  33. #include "target/riscv/cpu.h"
  34. #include "migration/vmstate.h"
  35. REG32(ALERT_TEST, 0x00)
  36. FIELD(ALERT_TEST, FATAL_FAULT, 0, 1)
  37. REG32(CTRL, 0x04)
  38. FIELD(CTRL, ACTIVE, 0, 1)
  39. REG32(CFG0, 0x100)
  40. FIELD(CFG0, PRESCALE, 0, 12)
  41. FIELD(CFG0, STEP, 16, 8)
  42. REG32(LOWER0, 0x104)
  43. REG32(UPPER0, 0x108)
  44. REG32(COMPARE_LOWER0, 0x10C)
  45. REG32(COMPARE_UPPER0, 0x110)
  46. REG32(INTR_ENABLE, 0x114)
  47. FIELD(INTR_ENABLE, IE_0, 0, 1)
  48. REG32(INTR_STATE, 0x118)
  49. FIELD(INTR_STATE, IS_0, 0, 1)
  50. REG32(INTR_TEST, 0x11C)
  51. FIELD(INTR_TEST, T_0, 0, 1)
  52. static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
  53. {
  54. return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
  55. timebase_freq, NANOSECONDS_PER_SECOND);
  56. }
  57. static void ibex_timer_update_irqs(IbexTimerState *s)
  58. {
  59. uint64_t value = s->timer_compare_lower0 |
  60. ((uint64_t)s->timer_compare_upper0 << 32);
  61. uint64_t next, diff;
  62. uint64_t now = cpu_riscv_read_rtc(s->timebase_freq);
  63. if (!(s->timer_ctrl & R_CTRL_ACTIVE_MASK)) {
  64. /* Timer isn't active */
  65. return;
  66. }
  67. /* Update the CPUs mtimecmp */
  68. s->mtimecmp = value;
  69. if (s->mtimecmp <= now) {
  70. /*
  71. * If the mtimecmp was in the past raise the interrupt now.
  72. */
  73. qemu_irq_raise(s->m_timer_irq);
  74. if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
  75. s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
  76. qemu_set_irq(s->irq, true);
  77. }
  78. return;
  79. }
  80. /* Setup a timer to trigger the interrupt in the future */
  81. qemu_irq_lower(s->m_timer_irq);
  82. qemu_set_irq(s->irq, false);
  83. diff = s->mtimecmp - now;
  84. next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
  85. muldiv64(diff,
  86. NANOSECONDS_PER_SECOND,
  87. s->timebase_freq);
  88. if (next < qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) {
  89. /* We overflowed the timer, just set it as large as we can */
  90. timer_mod(s->mtimer, 0x7FFFFFFFFFFFFFFF);
  91. } else {
  92. timer_mod(s->mtimer, next);
  93. }
  94. }
  95. static void ibex_timer_cb(void *opaque)
  96. {
  97. IbexTimerState *s = opaque;
  98. qemu_irq_raise(s->m_timer_irq);
  99. if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
  100. s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
  101. qemu_set_irq(s->irq, true);
  102. }
  103. }
  104. static void ibex_timer_reset(DeviceState *dev)
  105. {
  106. IbexTimerState *s = IBEX_TIMER(dev);
  107. s->mtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
  108. &ibex_timer_cb, s);
  109. s->mtimecmp = 0;
  110. s->timer_ctrl = 0x00000000;
  111. s->timer_cfg0 = 0x00010000;
  112. s->timer_compare_lower0 = 0xFFFFFFFF;
  113. s->timer_compare_upper0 = 0xFFFFFFFF;
  114. s->timer_intr_enable = 0x00000000;
  115. s->timer_intr_state = 0x00000000;
  116. ibex_timer_update_irqs(s);
  117. }
  118. static uint64_t ibex_timer_read(void *opaque, hwaddr addr,
  119. unsigned int size)
  120. {
  121. IbexTimerState *s = opaque;
  122. uint64_t now = cpu_riscv_read_rtc(s->timebase_freq);
  123. uint64_t retvalue = 0;
  124. switch (addr >> 2) {
  125. case R_ALERT_TEST:
  126. qemu_log_mask(LOG_GUEST_ERROR,
  127. "Attempted to read ALERT_TEST, a write only register");
  128. break;
  129. case R_CTRL:
  130. retvalue = s->timer_ctrl;
  131. break;
  132. case R_CFG0:
  133. retvalue = s->timer_cfg0;
  134. break;
  135. case R_LOWER0:
  136. retvalue = now;
  137. break;
  138. case R_UPPER0:
  139. retvalue = now >> 32;
  140. break;
  141. case R_COMPARE_LOWER0:
  142. retvalue = s->timer_compare_lower0;
  143. break;
  144. case R_COMPARE_UPPER0:
  145. retvalue = s->timer_compare_upper0;
  146. break;
  147. case R_INTR_ENABLE:
  148. retvalue = s->timer_intr_enable;
  149. break;
  150. case R_INTR_STATE:
  151. retvalue = s->timer_intr_state;
  152. break;
  153. case R_INTR_TEST:
  154. qemu_log_mask(LOG_GUEST_ERROR,
  155. "Attempted to read INTR_TEST, a write only register");
  156. break;
  157. default:
  158. qemu_log_mask(LOG_GUEST_ERROR,
  159. "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
  160. return 0;
  161. }
  162. return retvalue;
  163. }
  164. static void ibex_timer_write(void *opaque, hwaddr addr,
  165. uint64_t val64, unsigned int size)
  166. {
  167. IbexTimerState *s = opaque;
  168. uint32_t val = val64;
  169. switch (addr >> 2) {
  170. case R_ALERT_TEST:
  171. qemu_log_mask(LOG_UNIMP, "Alert triggering not supported");
  172. break;
  173. case R_CTRL:
  174. s->timer_ctrl = val;
  175. break;
  176. case R_CFG0:
  177. qemu_log_mask(LOG_UNIMP, "Changing prescale or step not supported");
  178. s->timer_cfg0 = val;
  179. break;
  180. case R_LOWER0:
  181. qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported");
  182. break;
  183. case R_UPPER0:
  184. qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported");
  185. break;
  186. case R_COMPARE_LOWER0:
  187. s->timer_compare_lower0 = val;
  188. ibex_timer_update_irqs(s);
  189. break;
  190. case R_COMPARE_UPPER0:
  191. s->timer_compare_upper0 = val;
  192. ibex_timer_update_irqs(s);
  193. break;
  194. case R_INTR_ENABLE:
  195. s->timer_intr_enable = val;
  196. break;
  197. case R_INTR_STATE:
  198. /* Write 1 to clear */
  199. s->timer_intr_state &= ~val;
  200. break;
  201. case R_INTR_TEST:
  202. if (s->timer_intr_enable & val & R_INTR_ENABLE_IE_0_MASK) {
  203. s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
  204. qemu_set_irq(s->irq, true);
  205. }
  206. break;
  207. default:
  208. qemu_log_mask(LOG_GUEST_ERROR,
  209. "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
  210. }
  211. }
  212. static const MemoryRegionOps ibex_timer_ops = {
  213. .read = ibex_timer_read,
  214. .write = ibex_timer_write,
  215. .endianness = DEVICE_NATIVE_ENDIAN,
  216. .impl.min_access_size = 4,
  217. .impl.max_access_size = 4,
  218. };
  219. static int ibex_timer_post_load(void *opaque, int version_id)
  220. {
  221. IbexTimerState *s = opaque;
  222. ibex_timer_update_irqs(s);
  223. return 0;
  224. }
  225. static const VMStateDescription vmstate_ibex_timer = {
  226. .name = TYPE_IBEX_TIMER,
  227. .version_id = 2,
  228. .minimum_version_id = 2,
  229. .post_load = ibex_timer_post_load,
  230. .fields = (const VMStateField[]) {
  231. VMSTATE_UINT32(timer_ctrl, IbexTimerState),
  232. VMSTATE_UINT32(timer_cfg0, IbexTimerState),
  233. VMSTATE_UINT32(timer_compare_lower0, IbexTimerState),
  234. VMSTATE_UINT32(timer_compare_upper0, IbexTimerState),
  235. VMSTATE_UINT32(timer_intr_enable, IbexTimerState),
  236. VMSTATE_UINT32(timer_intr_state, IbexTimerState),
  237. VMSTATE_END_OF_LIST()
  238. }
  239. };
  240. static const Property ibex_timer_properties[] = {
  241. DEFINE_PROP_UINT32("timebase-freq", IbexTimerState, timebase_freq, 10000),
  242. };
  243. static void ibex_timer_init(Object *obj)
  244. {
  245. IbexTimerState *s = IBEX_TIMER(obj);
  246. sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
  247. memory_region_init_io(&s->mmio, obj, &ibex_timer_ops, s,
  248. TYPE_IBEX_TIMER, 0x400);
  249. sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
  250. }
  251. static void ibex_timer_realize(DeviceState *dev, Error **errp)
  252. {
  253. IbexTimerState *s = IBEX_TIMER(dev);
  254. qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
  255. }
  256. static void ibex_timer_class_init(ObjectClass *klass, void *data)
  257. {
  258. DeviceClass *dc = DEVICE_CLASS(klass);
  259. device_class_set_legacy_reset(dc, ibex_timer_reset);
  260. dc->vmsd = &vmstate_ibex_timer;
  261. dc->realize = ibex_timer_realize;
  262. device_class_set_props(dc, ibex_timer_properties);
  263. }
  264. static const TypeInfo ibex_timer_info = {
  265. .name = TYPE_IBEX_TIMER,
  266. .parent = TYPE_SYS_BUS_DEVICE,
  267. .instance_size = sizeof(IbexTimerState),
  268. .instance_init = ibex_timer_init,
  269. .class_init = ibex_timer_class_init,
  270. };
  271. static void ibex_timer_register_types(void)
  272. {
  273. type_register_static(&ibex_timer_info);
  274. }
  275. type_init(ibex_timer_register_types)