2
0

cadence_ttc.c 12 KB

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