cmsdk-apb-dualtimer.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. * ARM CMSDK APB dual-timer emulation
  3. *
  4. * Copyright (c) 2018 Linaro Limited
  5. * Written by Peter Maydell
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 or
  9. * (at your option) any later version.
  10. */
  11. /*
  12. * This is a model of the "APB dual-input timer" which is part of the Cortex-M
  13. * System Design Kit (CMSDK) and documented in the Cortex-M System
  14. * Design Kit Technical Reference Manual (ARM DDI0479C):
  15. * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
  16. */
  17. #include "qemu/osdep.h"
  18. #include "qemu/log.h"
  19. #include "trace.h"
  20. #include "qapi/error.h"
  21. #include "qemu/module.h"
  22. #include "hw/sysbus.h"
  23. #include "hw/irq.h"
  24. #include "hw/qdev-properties.h"
  25. #include "hw/registerfields.h"
  26. #include "hw/timer/cmsdk-apb-dualtimer.h"
  27. #include "migration/vmstate.h"
  28. REG32(TIMER1LOAD, 0x0)
  29. REG32(TIMER1VALUE, 0x4)
  30. REG32(TIMER1CONTROL, 0x8)
  31. FIELD(CONTROL, ONESHOT, 0, 1)
  32. FIELD(CONTROL, SIZE, 1, 1)
  33. FIELD(CONTROL, PRESCALE, 2, 2)
  34. FIELD(CONTROL, INTEN, 5, 1)
  35. FIELD(CONTROL, MODE, 6, 1)
  36. FIELD(CONTROL, ENABLE, 7, 1)
  37. #define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \
  38. R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \
  39. R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK)
  40. REG32(TIMER1INTCLR, 0xc)
  41. REG32(TIMER1RIS, 0x10)
  42. REG32(TIMER1MIS, 0x14)
  43. REG32(TIMER1BGLOAD, 0x18)
  44. REG32(TIMER2LOAD, 0x20)
  45. REG32(TIMER2VALUE, 0x24)
  46. REG32(TIMER2CONTROL, 0x28)
  47. REG32(TIMER2INTCLR, 0x2c)
  48. REG32(TIMER2RIS, 0x30)
  49. REG32(TIMER2MIS, 0x34)
  50. REG32(TIMER2BGLOAD, 0x38)
  51. REG32(TIMERITCR, 0xf00)
  52. FIELD(TIMERITCR, ENABLE, 0, 1)
  53. #define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK
  54. REG32(TIMERITOP, 0xf04)
  55. FIELD(TIMERITOP, TIMINT1, 0, 1)
  56. FIELD(TIMERITOP, TIMINT2, 1, 1)
  57. #define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \
  58. R_TIMERITOP_TIMINT2_MASK)
  59. REG32(PID4, 0xfd0)
  60. REG32(PID5, 0xfd4)
  61. REG32(PID6, 0xfd8)
  62. REG32(PID7, 0xfdc)
  63. REG32(PID0, 0xfe0)
  64. REG32(PID1, 0xfe4)
  65. REG32(PID2, 0xfe8)
  66. REG32(PID3, 0xfec)
  67. REG32(CID0, 0xff0)
  68. REG32(CID1, 0xff4)
  69. REG32(CID2, 0xff8)
  70. REG32(CID3, 0xffc)
  71. /* PID/CID values */
  72. static const int timer_id[] = {
  73. 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
  74. 0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
  75. 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
  76. };
  77. static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m)
  78. {
  79. /* Return masked interrupt status for the timer module */
  80. return m->intstatus && (m->control & R_CONTROL_INTEN_MASK);
  81. }
  82. static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
  83. {
  84. bool timint1, timint2, timintc;
  85. if (s->timeritcr) {
  86. /* Integration test mode: outputs driven directly from TIMERITOP bits */
  87. timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK;
  88. timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK;
  89. } else {
  90. timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]);
  91. timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]);
  92. }
  93. timintc = timint1 || timint2;
  94. qemu_set_irq(s->timermod[0].timerint, timint1);
  95. qemu_set_irq(s->timermod[1].timerint, timint2);
  96. qemu_set_irq(s->timerintc, timintc);
  97. }
  98. static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
  99. uint32_t newctrl)
  100. {
  101. /* Handle a write to the CONTROL register */
  102. uint32_t changed;
  103. ptimer_transaction_begin(m->timer);
  104. newctrl &= R_CONTROL_VALID_MASK;
  105. changed = m->control ^ newctrl;
  106. if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
  107. /* ENABLE cleared, stop timer before any further changes */
  108. ptimer_stop(m->timer);
  109. }
  110. if (changed & R_CONTROL_PRESCALE_MASK) {
  111. int divisor;
  112. switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
  113. case 0:
  114. divisor = 1;
  115. break;
  116. case 1:
  117. divisor = 16;
  118. break;
  119. case 2:
  120. divisor = 256;
  121. break;
  122. case 3:
  123. /* UNDEFINED; complain, and arbitrarily treat like 2 */
  124. qemu_log_mask(LOG_GUEST_ERROR,
  125. "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
  126. " is undefined behaviour\n");
  127. divisor = 256;
  128. break;
  129. default:
  130. g_assert_not_reached();
  131. }
  132. ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
  133. }
  134. if (changed & R_CONTROL_MODE_MASK) {
  135. uint32_t load;
  136. if (newctrl & R_CONTROL_MODE_MASK) {
  137. /* Periodic: the limit is the LOAD register value */
  138. load = m->load;
  139. } else {
  140. /* Free-running: counter wraps around */
  141. load = ptimer_get_limit(m->timer);
  142. if (!(m->control & R_CONTROL_SIZE_MASK)) {
  143. load = deposit32(m->load, 0, 16, load);
  144. }
  145. m->load = load;
  146. load = 0xffffffff;
  147. }
  148. if (!(m->control & R_CONTROL_SIZE_MASK)) {
  149. load &= 0xffff;
  150. }
  151. ptimer_set_limit(m->timer, load, 0);
  152. }
  153. if (changed & R_CONTROL_SIZE_MASK) {
  154. /* Timer switched between 16 and 32 bit count */
  155. uint32_t value, load;
  156. value = ptimer_get_count(m->timer);
  157. load = ptimer_get_limit(m->timer);
  158. if (newctrl & R_CONTROL_SIZE_MASK) {
  159. /* 16 -> 32, top half of VALUE is in struct field */
  160. value = deposit32(m->value, 0, 16, value);
  161. } else {
  162. /* 32 -> 16: save top half to struct field and truncate */
  163. m->value = value;
  164. value &= 0xffff;
  165. }
  166. if (newctrl & R_CONTROL_MODE_MASK) {
  167. /* Periodic, timer limit has LOAD value */
  168. if (newctrl & R_CONTROL_SIZE_MASK) {
  169. load = deposit32(m->load, 0, 16, load);
  170. } else {
  171. m->load = load;
  172. load &= 0xffff;
  173. }
  174. } else {
  175. /* Free-running, timer limit is set to give wraparound */
  176. if (newctrl & R_CONTROL_SIZE_MASK) {
  177. load = 0xffffffff;
  178. } else {
  179. load = 0xffff;
  180. }
  181. }
  182. ptimer_set_count(m->timer, value);
  183. ptimer_set_limit(m->timer, load, 0);
  184. }
  185. if (newctrl & R_CONTROL_ENABLE_MASK) {
  186. /*
  187. * ENABLE is set; start the timer after all other changes.
  188. * We start it even if the ENABLE bit didn't actually change,
  189. * in case the timer was an expired one-shot timer that has
  190. * now been changed into a free-running or periodic timer.
  191. */
  192. ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
  193. }
  194. m->control = newctrl;
  195. ptimer_transaction_commit(m->timer);
  196. }
  197. static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
  198. unsigned size)
  199. {
  200. CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
  201. uint64_t r;
  202. if (offset >= A_TIMERITCR) {
  203. switch (offset) {
  204. case A_TIMERITCR:
  205. r = s->timeritcr;
  206. break;
  207. case A_PID4 ... A_CID3:
  208. r = timer_id[(offset - A_PID4) / 4];
  209. break;
  210. default:
  211. bad_offset:
  212. qemu_log_mask(LOG_GUEST_ERROR,
  213. "CMSDK APB dual-timer read: bad offset %x\n",
  214. (int) offset);
  215. r = 0;
  216. break;
  217. }
  218. } else {
  219. int timer = offset >> 5;
  220. CMSDKAPBDualTimerModule *m;
  221. if (timer >= ARRAY_SIZE(s->timermod)) {
  222. goto bad_offset;
  223. }
  224. m = &s->timermod[timer];
  225. switch (offset & 0x1F) {
  226. case A_TIMER1LOAD:
  227. case A_TIMER1BGLOAD:
  228. if (m->control & R_CONTROL_MODE_MASK) {
  229. /*
  230. * Periodic: the ptimer limit is the LOAD register value, (or
  231. * just the low 16 bits of it if the timer is in 16-bit mode)
  232. */
  233. r = ptimer_get_limit(m->timer);
  234. if (!(m->control & R_CONTROL_SIZE_MASK)) {
  235. r = deposit32(m->load, 0, 16, r);
  236. }
  237. } else {
  238. /* Free-running: LOAD register value is just in m->load */
  239. r = m->load;
  240. }
  241. break;
  242. case A_TIMER1VALUE:
  243. r = ptimer_get_count(m->timer);
  244. if (!(m->control & R_CONTROL_SIZE_MASK)) {
  245. r = deposit32(m->value, 0, 16, r);
  246. }
  247. break;
  248. case A_TIMER1CONTROL:
  249. r = m->control;
  250. break;
  251. case A_TIMER1RIS:
  252. r = m->intstatus;
  253. break;
  254. case A_TIMER1MIS:
  255. r = cmsdk_dualtimermod_intstatus(m);
  256. break;
  257. default:
  258. goto bad_offset;
  259. }
  260. }
  261. trace_cmsdk_apb_dualtimer_read(offset, r, size);
  262. return r;
  263. }
  264. static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
  265. uint64_t value, unsigned size)
  266. {
  267. CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
  268. trace_cmsdk_apb_dualtimer_write(offset, value, size);
  269. if (offset >= A_TIMERITCR) {
  270. switch (offset) {
  271. case A_TIMERITCR:
  272. s->timeritcr = value & R_TIMERITCR_VALID_MASK;
  273. cmsdk_apb_dualtimer_update(s);
  274. break;
  275. case A_TIMERITOP:
  276. s->timeritop = value & R_TIMERITOP_VALID_MASK;
  277. cmsdk_apb_dualtimer_update(s);
  278. break;
  279. default:
  280. bad_offset:
  281. qemu_log_mask(LOG_GUEST_ERROR,
  282. "CMSDK APB dual-timer write: bad offset %x\n",
  283. (int) offset);
  284. break;
  285. }
  286. } else {
  287. int timer = offset >> 5;
  288. CMSDKAPBDualTimerModule *m;
  289. if (timer >= ARRAY_SIZE(s->timermod)) {
  290. goto bad_offset;
  291. }
  292. m = &s->timermod[timer];
  293. switch (offset & 0x1F) {
  294. case A_TIMER1LOAD:
  295. /* Set the limit, and immediately reload the count from it */
  296. m->load = value;
  297. m->value = value;
  298. if (!(m->control & R_CONTROL_SIZE_MASK)) {
  299. value &= 0xffff;
  300. }
  301. ptimer_transaction_begin(m->timer);
  302. if (!(m->control & R_CONTROL_MODE_MASK)) {
  303. /*
  304. * In free-running mode this won't set the limit but will
  305. * still change the current count value.
  306. */
  307. ptimer_set_count(m->timer, value);
  308. } else {
  309. if (!value) {
  310. ptimer_stop(m->timer);
  311. }
  312. ptimer_set_limit(m->timer, value, 1);
  313. if (value && (m->control & R_CONTROL_ENABLE_MASK)) {
  314. /* Force possibly-expired oneshot timer to restart */
  315. ptimer_run(m->timer, 1);
  316. }
  317. }
  318. ptimer_transaction_commit(m->timer);
  319. break;
  320. case A_TIMER1BGLOAD:
  321. /* Set the limit, but not the current count */
  322. m->load = value;
  323. if (!(m->control & R_CONTROL_MODE_MASK)) {
  324. /* In free-running mode there is no limit */
  325. break;
  326. }
  327. if (!(m->control & R_CONTROL_SIZE_MASK)) {
  328. value &= 0xffff;
  329. }
  330. ptimer_transaction_begin(m->timer);
  331. ptimer_set_limit(m->timer, value, 0);
  332. ptimer_transaction_commit(m->timer);
  333. break;
  334. case A_TIMER1CONTROL:
  335. cmsdk_dualtimermod_write_control(m, value);
  336. cmsdk_apb_dualtimer_update(s);
  337. break;
  338. case A_TIMER1INTCLR:
  339. m->intstatus = 0;
  340. cmsdk_apb_dualtimer_update(s);
  341. break;
  342. default:
  343. goto bad_offset;
  344. }
  345. }
  346. }
  347. static const MemoryRegionOps cmsdk_apb_dualtimer_ops = {
  348. .read = cmsdk_apb_dualtimer_read,
  349. .write = cmsdk_apb_dualtimer_write,
  350. .endianness = DEVICE_LITTLE_ENDIAN,
  351. /* byte/halfword accesses are just zero-padded on reads and writes */
  352. .impl.min_access_size = 4,
  353. .impl.max_access_size = 4,
  354. .valid.min_access_size = 1,
  355. .valid.max_access_size = 4,
  356. };
  357. static void cmsdk_dualtimermod_tick(void *opaque)
  358. {
  359. CMSDKAPBDualTimerModule *m = opaque;
  360. m->intstatus = 1;
  361. cmsdk_apb_dualtimer_update(m->parent);
  362. }
  363. static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
  364. {
  365. m->control = R_CONTROL_INTEN_MASK;
  366. m->intstatus = 0;
  367. m->load = 0;
  368. m->value = 0xffffffff;
  369. ptimer_transaction_begin(m->timer);
  370. ptimer_stop(m->timer);
  371. /*
  372. * We start in free-running mode, with VALUE at 0xffffffff, and
  373. * in 16-bit counter mode. This means that the ptimer count and
  374. * limit must both be set to 0xffff, so we wrap at 16 bits.
  375. */
  376. ptimer_set_limit(m->timer, 0xffff, 1);
  377. ptimer_set_freq(m->timer, m->parent->pclk_frq);
  378. ptimer_transaction_commit(m->timer);
  379. }
  380. static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
  381. {
  382. CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
  383. int i;
  384. trace_cmsdk_apb_dualtimer_reset();
  385. for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
  386. cmsdk_dualtimermod_reset(&s->timermod[i]);
  387. }
  388. s->timeritcr = 0;
  389. s->timeritop = 0;
  390. }
  391. static void cmsdk_apb_dualtimer_init(Object *obj)
  392. {
  393. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  394. CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
  395. int i;
  396. memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops,
  397. s, "cmsdk-apb-dualtimer", 0x1000);
  398. sysbus_init_mmio(sbd, &s->iomem);
  399. sysbus_init_irq(sbd, &s->timerintc);
  400. for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
  401. sysbus_init_irq(sbd, &s->timermod[i].timerint);
  402. }
  403. }
  404. static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
  405. {
  406. CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
  407. int i;
  408. if (s->pclk_frq == 0) {
  409. error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
  410. return;
  411. }
  412. for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
  413. CMSDKAPBDualTimerModule *m = &s->timermod[i];
  414. m->parent = s;
  415. m->timer = ptimer_init(cmsdk_dualtimermod_tick, m,
  416. PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
  417. PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
  418. PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
  419. PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
  420. }
  421. }
  422. static const VMStateDescription cmsdk_dualtimermod_vmstate = {
  423. .name = "cmsdk-apb-dualtimer-module",
  424. .version_id = 1,
  425. .minimum_version_id = 1,
  426. .fields = (VMStateField[]) {
  427. VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule),
  428. VMSTATE_UINT32(load, CMSDKAPBDualTimerModule),
  429. VMSTATE_UINT32(value, CMSDKAPBDualTimerModule),
  430. VMSTATE_UINT32(control, CMSDKAPBDualTimerModule),
  431. VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule),
  432. VMSTATE_END_OF_LIST()
  433. }
  434. };
  435. static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
  436. .name = "cmsdk-apb-dualtimer",
  437. .version_id = 1,
  438. .minimum_version_id = 1,
  439. .fields = (VMStateField[]) {
  440. VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
  441. CMSDK_APB_DUALTIMER_NUM_MODULES,
  442. 1, cmsdk_dualtimermod_vmstate,
  443. CMSDKAPBDualTimerModule),
  444. VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer),
  445. VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer),
  446. VMSTATE_END_OF_LIST()
  447. }
  448. };
  449. static Property cmsdk_apb_dualtimer_properties[] = {
  450. DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
  451. DEFINE_PROP_END_OF_LIST(),
  452. };
  453. static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
  454. {
  455. DeviceClass *dc = DEVICE_CLASS(klass);
  456. dc->realize = cmsdk_apb_dualtimer_realize;
  457. dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
  458. dc->reset = cmsdk_apb_dualtimer_reset;
  459. device_class_set_props(dc, cmsdk_apb_dualtimer_properties);
  460. }
  461. static const TypeInfo cmsdk_apb_dualtimer_info = {
  462. .name = TYPE_CMSDK_APB_DUALTIMER,
  463. .parent = TYPE_SYS_BUS_DEVICE,
  464. .instance_size = sizeof(CMSDKAPBDualTimer),
  465. .instance_init = cmsdk_apb_dualtimer_init,
  466. .class_init = cmsdk_apb_dualtimer_class_init,
  467. };
  468. static void cmsdk_apb_dualtimer_register_types(void)
  469. {
  470. type_register_static(&cmsdk_apb_dualtimer_info);
  471. }
  472. type_init(cmsdk_apb_dualtimer_register_types);