cadence_ttc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. * Xilinx Zynq cadence TTC model
  3. *
  4. * Copyright (c) 2011 Xilinx Inc.
  5. * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
  6. * Copyright (c) 2012 PetaLogix Pty Ltd.
  7. * Written By Haibing Ma
  8. * M. Habib
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version
  13. * 2 of the License, or (at your option) any later version.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "qemu/osdep.h"
  19. #include "hw/irq.h"
  20. #include "hw/sysbus.h"
  21. #include "migration/vmstate.h"
  22. #include "qemu/module.h"
  23. #include "qemu/timer.h"
  24. #ifdef CADENCE_TTC_ERR_DEBUG
  25. #define DB_PRINT(...) do { \
  26. fprintf(stderr, ": %s: ", __func__); \
  27. fprintf(stderr, ## __VA_ARGS__); \
  28. } while (0)
  29. #else
  30. #define DB_PRINT(...)
  31. #endif
  32. #define COUNTER_INTR_IV 0x00000001
  33. #define COUNTER_INTR_M1 0x00000002
  34. #define COUNTER_INTR_M2 0x00000004
  35. #define COUNTER_INTR_M3 0x00000008
  36. #define COUNTER_INTR_OV 0x00000010
  37. #define COUNTER_INTR_EV 0x00000020
  38. #define COUNTER_CTRL_DIS 0x00000001
  39. #define COUNTER_CTRL_INT 0x00000002
  40. #define COUNTER_CTRL_DEC 0x00000004
  41. #define COUNTER_CTRL_MATCH 0x00000008
  42. #define COUNTER_CTRL_RST 0x00000010
  43. #define CLOCK_CTRL_PS_EN 0x00000001
  44. #define CLOCK_CTRL_PS_V 0x0000001e
  45. typedef struct {
  46. QEMUTimer *timer;
  47. int freq;
  48. uint32_t reg_clock;
  49. uint32_t reg_count;
  50. uint32_t reg_value;
  51. uint16_t reg_interval;
  52. uint16_t reg_match[3];
  53. uint32_t reg_intr;
  54. uint32_t reg_intr_en;
  55. uint32_t reg_event_ctrl;
  56. uint32_t reg_event;
  57. uint64_t cpu_time;
  58. unsigned int cpu_time_valid;
  59. qemu_irq irq;
  60. } CadenceTimerState;
  61. #define TYPE_CADENCE_TTC "cadence_ttc"
  62. #define CADENCE_TTC(obj) \
  63. OBJECT_CHECK(CadenceTTCState, (obj), TYPE_CADENCE_TTC)
  64. typedef struct CadenceTTCState {
  65. SysBusDevice parent_obj;
  66. MemoryRegion iomem;
  67. CadenceTimerState timer[3];
  68. } CadenceTTCState;
  69. static void cadence_timer_update(CadenceTimerState *s)
  70. {
  71. qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
  72. }
  73. static CadenceTimerState *cadence_timer_from_addr(void *opaque,
  74. hwaddr offset)
  75. {
  76. unsigned int index;
  77. CadenceTTCState *s = (CadenceTTCState *)opaque;
  78. index = (offset >> 2) % 3;
  79. return &s->timer[index];
  80. }
  81. static uint64_t cadence_timer_get_ns(CadenceTimerState *s, uint64_t timer_steps)
  82. {
  83. /* timer_steps has max value of 0x100000000. double check it
  84. * (or overflow can happen below) */
  85. assert(timer_steps <= 1ULL << 32);
  86. uint64_t r = timer_steps * 1000000000ULL;
  87. if (s->reg_clock & CLOCK_CTRL_PS_EN) {
  88. r >>= 16 - (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1);
  89. } else {
  90. r >>= 16;
  91. }
  92. r /= (uint64_t)s->freq;
  93. return r;
  94. }
  95. static uint64_t cadence_timer_get_steps(CadenceTimerState *s, uint64_t ns)
  96. {
  97. uint64_t to_divide = 1000000000ULL;
  98. uint64_t r = ns;
  99. /* for very large intervals (> 8s) do some division first to stop
  100. * overflow (costs some prescision) */
  101. while (r >= 8ULL << 30 && to_divide > 1) {
  102. r /= 1000;
  103. to_divide /= 1000;
  104. }
  105. r <<= 16;
  106. /* keep early-dividing as needed */
  107. while (r >= 8ULL << 30 && to_divide > 1) {
  108. r /= 1000;
  109. to_divide /= 1000;
  110. }
  111. r *= (uint64_t)s->freq;
  112. if (s->reg_clock & CLOCK_CTRL_PS_EN) {
  113. r /= 1 << (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1);
  114. }
  115. r /= to_divide;
  116. return r;
  117. }
  118. /* determine if x is in between a and b, exclusive of a, inclusive of b */
  119. static inline int64_t is_between(int64_t x, int64_t a, int64_t b)
  120. {
  121. if (a < b) {
  122. return x > a && x <= b;
  123. }
  124. return x < a && x >= b;
  125. }
  126. static void cadence_timer_run(CadenceTimerState *s)
  127. {
  128. int i;
  129. int64_t event_interval, next_value;
  130. assert(s->cpu_time_valid); /* cadence_timer_sync must be called first */
  131. if (s->reg_count & COUNTER_CTRL_DIS) {
  132. s->cpu_time_valid = 0;
  133. return;
  134. }
  135. { /* figure out what's going to happen next (rollover or match) */
  136. int64_t interval = (uint64_t)((s->reg_count & COUNTER_CTRL_INT) ?
  137. (int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
  138. next_value = (s->reg_count & COUNTER_CTRL_DEC) ? -1ULL : interval;
  139. for (i = 0; i < 3; ++i) {
  140. int64_t cand = (uint64_t)s->reg_match[i] << 16;
  141. if (is_between(cand, (uint64_t)s->reg_value, next_value)) {
  142. next_value = cand;
  143. }
  144. }
  145. }
  146. DB_PRINT("next timer event value: %09llx\n",
  147. (unsigned long long)next_value);
  148. event_interval = next_value - (int64_t)s->reg_value;
  149. event_interval = (event_interval < 0) ? -event_interval : event_interval;
  150. timer_mod(s->timer, s->cpu_time +
  151. cadence_timer_get_ns(s, event_interval));
  152. }
  153. static void cadence_timer_sync(CadenceTimerState *s)
  154. {
  155. int i;
  156. int64_t r, x;
  157. int64_t interval = ((s->reg_count & COUNTER_CTRL_INT) ?
  158. (int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
  159. uint64_t old_time = s->cpu_time;
  160. s->cpu_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  161. DB_PRINT("cpu time: %lld ns\n", (long long)old_time);
  162. if (!s->cpu_time_valid || old_time == s->cpu_time) {
  163. s->cpu_time_valid = 1;
  164. return;
  165. }
  166. r = (int64_t)cadence_timer_get_steps(s, s->cpu_time - old_time);
  167. x = (int64_t)s->reg_value + ((s->reg_count & COUNTER_CTRL_DEC) ? -r : r);
  168. for (i = 0; i < 3; ++i) {
  169. int64_t m = (int64_t)s->reg_match[i] << 16;
  170. if (m > interval) {
  171. continue;
  172. }
  173. /* check to see if match event has occurred. check m +/- interval
  174. * to account for match events in wrap around cases */
  175. if (is_between(m, s->reg_value, x) ||
  176. is_between(m + interval, s->reg_value, x) ||
  177. is_between(m - interval, s->reg_value, x)) {
  178. s->reg_intr |= (2 << i);
  179. }
  180. }
  181. if ((x < 0) || (x >= interval)) {
  182. s->reg_intr |= (s->reg_count & COUNTER_CTRL_INT) ?
  183. COUNTER_INTR_IV : COUNTER_INTR_OV;
  184. }
  185. while (x < 0) {
  186. x += interval;
  187. }
  188. s->reg_value = (uint32_t)(x % interval);
  189. cadence_timer_update(s);
  190. }
  191. static void cadence_timer_tick(void *opaque)
  192. {
  193. CadenceTimerState *s = opaque;
  194. DB_PRINT("\n");
  195. cadence_timer_sync(s);
  196. cadence_timer_run(s);
  197. }
  198. static uint32_t cadence_ttc_read_imp(void *opaque, hwaddr offset)
  199. {
  200. CadenceTimerState *s = cadence_timer_from_addr(opaque, offset);
  201. uint32_t value;
  202. cadence_timer_sync(s);
  203. cadence_timer_run(s);
  204. switch (offset) {
  205. case 0x00: /* clock control */
  206. case 0x04:
  207. case 0x08:
  208. return s->reg_clock;
  209. case 0x0c: /* counter control */
  210. case 0x10:
  211. case 0x14:
  212. return s->reg_count;
  213. case 0x18: /* counter value */
  214. case 0x1c:
  215. case 0x20:
  216. return (uint16_t)(s->reg_value >> 16);
  217. case 0x24: /* reg_interval counter */
  218. case 0x28:
  219. case 0x2c:
  220. return s->reg_interval;
  221. case 0x30: /* match 1 counter */
  222. case 0x34:
  223. case 0x38:
  224. return s->reg_match[0];
  225. case 0x3c: /* match 2 counter */
  226. case 0x40:
  227. case 0x44:
  228. return s->reg_match[1];
  229. case 0x48: /* match 3 counter */
  230. case 0x4c:
  231. case 0x50:
  232. return s->reg_match[2];
  233. case 0x54: /* interrupt register */
  234. case 0x58:
  235. case 0x5c:
  236. /* cleared after read */
  237. value = s->reg_intr;
  238. s->reg_intr = 0;
  239. cadence_timer_update(s);
  240. return value;
  241. case 0x60: /* interrupt enable */
  242. case 0x64:
  243. case 0x68:
  244. return s->reg_intr_en;
  245. case 0x6c:
  246. case 0x70:
  247. case 0x74:
  248. return s->reg_event_ctrl;
  249. case 0x78:
  250. case 0x7c:
  251. case 0x80:
  252. return s->reg_event;
  253. default:
  254. return 0;
  255. }
  256. }
  257. static uint64_t cadence_ttc_read(void *opaque, hwaddr offset,
  258. unsigned size)
  259. {
  260. uint32_t ret = cadence_ttc_read_imp(opaque, offset);
  261. DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret);
  262. return ret;
  263. }
  264. static void cadence_ttc_write(void *opaque, hwaddr offset,
  265. uint64_t value, unsigned size)
  266. {
  267. CadenceTimerState *s = cadence_timer_from_addr(opaque, offset);
  268. DB_PRINT("addr: %08x data %08x\n", (unsigned)offset, (unsigned)value);
  269. cadence_timer_sync(s);
  270. switch (offset) {
  271. case 0x00: /* clock control */
  272. case 0x04:
  273. case 0x08:
  274. s->reg_clock = value & 0x3F;
  275. break;
  276. case 0x0c: /* counter control */
  277. case 0x10:
  278. case 0x14:
  279. if (value & COUNTER_CTRL_RST) {
  280. s->reg_value = 0;
  281. }
  282. s->reg_count = value & 0x3f & ~COUNTER_CTRL_RST;
  283. break;
  284. case 0x24: /* interval register */
  285. case 0x28:
  286. case 0x2c:
  287. s->reg_interval = value & 0xffff;
  288. break;
  289. case 0x30: /* match register */
  290. case 0x34:
  291. case 0x38:
  292. s->reg_match[0] = value & 0xffff;
  293. break;
  294. case 0x3c: /* match register */
  295. case 0x40:
  296. case 0x44:
  297. s->reg_match[1] = value & 0xffff;
  298. break;
  299. case 0x48: /* match register */
  300. case 0x4c:
  301. case 0x50:
  302. s->reg_match[2] = value & 0xffff;
  303. break;
  304. case 0x54: /* interrupt register */
  305. case 0x58:
  306. case 0x5c:
  307. break;
  308. case 0x60: /* interrupt enable */
  309. case 0x64:
  310. case 0x68:
  311. s->reg_intr_en = value & 0x3f;
  312. break;
  313. case 0x6c: /* event control */
  314. case 0x70:
  315. case 0x74:
  316. s->reg_event_ctrl = value & 0x07;
  317. break;
  318. default:
  319. return;
  320. }
  321. cadence_timer_run(s);
  322. cadence_timer_update(s);
  323. }
  324. static const MemoryRegionOps cadence_ttc_ops = {
  325. .read = cadence_ttc_read,
  326. .write = cadence_ttc_write,
  327. .endianness = DEVICE_NATIVE_ENDIAN,
  328. };
  329. static void cadence_timer_reset(CadenceTimerState *s)
  330. {
  331. s->reg_count = 0x21;
  332. }
  333. static void cadence_timer_init(uint32_t freq, CadenceTimerState *s)
  334. {
  335. memset(s, 0, sizeof(CadenceTimerState));
  336. s->freq = freq;
  337. cadence_timer_reset(s);
  338. s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_timer_tick, s);
  339. }
  340. static void cadence_ttc_init(Object *obj)
  341. {
  342. CadenceTTCState *s = CADENCE_TTC(obj);
  343. memory_region_init_io(&s->iomem, obj, &cadence_ttc_ops, s,
  344. "timer", 0x1000);
  345. sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
  346. }
  347. static void cadence_ttc_realize(DeviceState *dev, Error **errp)
  348. {
  349. CadenceTTCState *s = CADENCE_TTC(dev);
  350. int i;
  351. for (i = 0; i < 3; ++i) {
  352. cadence_timer_init(133000000, &s->timer[i]);
  353. sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->timer[i].irq);
  354. }
  355. }
  356. static int cadence_timer_pre_save(void *opaque)
  357. {
  358. cadence_timer_sync((CadenceTimerState *)opaque);
  359. return 0;
  360. }
  361. static int cadence_timer_post_load(void *opaque, int version_id)
  362. {
  363. CadenceTimerState *s = opaque;
  364. s->cpu_time_valid = 0;
  365. cadence_timer_sync(s);
  366. cadence_timer_run(s);
  367. cadence_timer_update(s);
  368. return 0;
  369. }
  370. static const VMStateDescription vmstate_cadence_timer = {
  371. .name = "cadence_timer",
  372. .version_id = 1,
  373. .minimum_version_id = 1,
  374. .pre_save = cadence_timer_pre_save,
  375. .post_load = cadence_timer_post_load,
  376. .fields = (VMStateField[]) {
  377. VMSTATE_UINT32(reg_clock, CadenceTimerState),
  378. VMSTATE_UINT32(reg_count, CadenceTimerState),
  379. VMSTATE_UINT32(reg_value, CadenceTimerState),
  380. VMSTATE_UINT16(reg_interval, CadenceTimerState),
  381. VMSTATE_UINT16_ARRAY(reg_match, CadenceTimerState, 3),
  382. VMSTATE_UINT32(reg_intr, CadenceTimerState),
  383. VMSTATE_UINT32(reg_intr_en, CadenceTimerState),
  384. VMSTATE_UINT32(reg_event_ctrl, CadenceTimerState),
  385. VMSTATE_UINT32(reg_event, CadenceTimerState),
  386. VMSTATE_END_OF_LIST()
  387. }
  388. };
  389. static const VMStateDescription vmstate_cadence_ttc = {
  390. .name = "cadence_TTC",
  391. .version_id = 1,
  392. .minimum_version_id = 1,
  393. .fields = (VMStateField[]) {
  394. VMSTATE_STRUCT_ARRAY(timer, CadenceTTCState, 3, 0,
  395. vmstate_cadence_timer,
  396. CadenceTimerState),
  397. VMSTATE_END_OF_LIST()
  398. }
  399. };
  400. static void cadence_ttc_class_init(ObjectClass *klass, void *data)
  401. {
  402. DeviceClass *dc = DEVICE_CLASS(klass);
  403. dc->vmsd = &vmstate_cadence_ttc;
  404. dc->realize = cadence_ttc_realize;
  405. }
  406. static const TypeInfo cadence_ttc_info = {
  407. .name = TYPE_CADENCE_TTC,
  408. .parent = TYPE_SYS_BUS_DEVICE,
  409. .instance_size = sizeof(CadenceTTCState),
  410. .instance_init = cadence_ttc_init,
  411. .class_init = cadence_ttc_class_init,
  412. };
  413. static void cadence_ttc_register_types(void)
  414. {
  415. type_register_static(&cadence_ttc_info);
  416. }
  417. type_init(cadence_ttc_register_types)