2
0

pxa2xx_timer.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /*
  2. * Intel XScale PXA255/270 OS Timers.
  3. *
  4. * Copyright (c) 2006 Openedhand Ltd.
  5. * Copyright (c) 2006 Thorsten Zitterell
  6. *
  7. * This code is licensed under the GPL.
  8. */
  9. #include "hw.h"
  10. #include "qemu-timer.h"
  11. #include "sysemu.h"
  12. #include "pxa.h"
  13. #include "sysbus.h"
  14. #define OSMR0 0x00
  15. #define OSMR1 0x04
  16. #define OSMR2 0x08
  17. #define OSMR3 0x0c
  18. #define OSMR4 0x80
  19. #define OSMR5 0x84
  20. #define OSMR6 0x88
  21. #define OSMR7 0x8c
  22. #define OSMR8 0x90
  23. #define OSMR9 0x94
  24. #define OSMR10 0x98
  25. #define OSMR11 0x9c
  26. #define OSCR 0x10 /* OS Timer Count */
  27. #define OSCR4 0x40
  28. #define OSCR5 0x44
  29. #define OSCR6 0x48
  30. #define OSCR7 0x4c
  31. #define OSCR8 0x50
  32. #define OSCR9 0x54
  33. #define OSCR10 0x58
  34. #define OSCR11 0x5c
  35. #define OSSR 0x14 /* Timer status register */
  36. #define OWER 0x18
  37. #define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
  38. #define OMCR4 0xc0 /* OS Match Control registers */
  39. #define OMCR5 0xc4
  40. #define OMCR6 0xc8
  41. #define OMCR7 0xcc
  42. #define OMCR8 0xd0
  43. #define OMCR9 0xd4
  44. #define OMCR10 0xd8
  45. #define OMCR11 0xdc
  46. #define OSNR 0x20
  47. #define PXA25X_FREQ 3686400 /* 3.6864 MHz */
  48. #define PXA27X_FREQ 3250000 /* 3.25 MHz */
  49. static int pxa2xx_timer4_freq[8] = {
  50. [0] = 0,
  51. [1] = 32768,
  52. [2] = 1000,
  53. [3] = 1,
  54. [4] = 1000000,
  55. /* [5] is the "Externally supplied clock". Assign if necessary. */
  56. [5 ... 7] = 0,
  57. };
  58. typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
  59. typedef struct {
  60. uint32_t value;
  61. qemu_irq irq;
  62. QEMUTimer *qtimer;
  63. int num;
  64. PXA2xxTimerInfo *info;
  65. } PXA2xxTimer0;
  66. typedef struct {
  67. PXA2xxTimer0 tm;
  68. int32_t oldclock;
  69. int32_t clock;
  70. uint64_t lastload;
  71. uint32_t freq;
  72. uint32_t control;
  73. } PXA2xxTimer4;
  74. struct PXA2xxTimerInfo {
  75. SysBusDevice busdev;
  76. uint32_t flags;
  77. int32_t clock;
  78. int32_t oldclock;
  79. uint64_t lastload;
  80. uint32_t freq;
  81. PXA2xxTimer0 timer[4];
  82. uint32_t events;
  83. uint32_t irq_enabled;
  84. uint32_t reset3;
  85. uint32_t snapshot;
  86. qemu_irq irq4;
  87. PXA2xxTimer4 tm4[8];
  88. };
  89. #define PXA2XX_TIMER_HAVE_TM4 0
  90. static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
  91. {
  92. return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
  93. }
  94. static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
  95. {
  96. PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
  97. int i;
  98. uint32_t now_vm;
  99. uint64_t new_qemu;
  100. now_vm = s->clock +
  101. muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
  102. for (i = 0; i < 4; i ++) {
  103. new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
  104. get_ticks_per_sec(), s->freq);
  105. qemu_mod_timer(s->timer[i].qtimer, new_qemu);
  106. }
  107. }
  108. static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
  109. {
  110. PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
  111. uint32_t now_vm;
  112. uint64_t new_qemu;
  113. static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
  114. int counter;
  115. if (s->tm4[n].control & (1 << 7))
  116. counter = n;
  117. else
  118. counter = counters[n];
  119. if (!s->tm4[counter].freq) {
  120. qemu_del_timer(s->tm4[n].tm.qtimer);
  121. return;
  122. }
  123. now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
  124. s->tm4[counter].lastload,
  125. s->tm4[counter].freq, get_ticks_per_sec());
  126. new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
  127. get_ticks_per_sec(), s->tm4[counter].freq);
  128. qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
  129. }
  130. static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
  131. {
  132. PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
  133. int tm = 0;
  134. switch (offset) {
  135. case OSMR3: tm ++;
  136. case OSMR2: tm ++;
  137. case OSMR1: tm ++;
  138. case OSMR0:
  139. return s->timer[tm].value;
  140. case OSMR11: tm ++;
  141. case OSMR10: tm ++;
  142. case OSMR9: tm ++;
  143. case OSMR8: tm ++;
  144. case OSMR7: tm ++;
  145. case OSMR6: tm ++;
  146. case OSMR5: tm ++;
  147. case OSMR4:
  148. if (!pxa2xx_timer_has_tm4(s))
  149. goto badreg;
  150. return s->tm4[tm].tm.value;
  151. case OSCR:
  152. return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) -
  153. s->lastload, s->freq, get_ticks_per_sec());
  154. case OSCR11: tm ++;
  155. case OSCR10: tm ++;
  156. case OSCR9: tm ++;
  157. case OSCR8: tm ++;
  158. case OSCR7: tm ++;
  159. case OSCR6: tm ++;
  160. case OSCR5: tm ++;
  161. case OSCR4:
  162. if (!pxa2xx_timer_has_tm4(s))
  163. goto badreg;
  164. if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
  165. if (s->tm4[tm - 1].freq)
  166. s->snapshot = s->tm4[tm - 1].clock + muldiv64(
  167. qemu_get_clock_ns(vm_clock) -
  168. s->tm4[tm - 1].lastload,
  169. s->tm4[tm - 1].freq, get_ticks_per_sec());
  170. else
  171. s->snapshot = s->tm4[tm - 1].clock;
  172. }
  173. if (!s->tm4[tm].freq)
  174. return s->tm4[tm].clock;
  175. return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) -
  176. s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
  177. case OIER:
  178. return s->irq_enabled;
  179. case OSSR: /* Status register */
  180. return s->events;
  181. case OWER:
  182. return s->reset3;
  183. case OMCR11: tm ++;
  184. case OMCR10: tm ++;
  185. case OMCR9: tm ++;
  186. case OMCR8: tm ++;
  187. case OMCR7: tm ++;
  188. case OMCR6: tm ++;
  189. case OMCR5: tm ++;
  190. case OMCR4:
  191. if (!pxa2xx_timer_has_tm4(s))
  192. goto badreg;
  193. return s->tm4[tm].control;
  194. case OSNR:
  195. return s->snapshot;
  196. default:
  197. badreg:
  198. hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
  199. }
  200. return 0;
  201. }
  202. static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
  203. uint32_t value)
  204. {
  205. int i, tm = 0;
  206. PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
  207. switch (offset) {
  208. case OSMR3: tm ++;
  209. case OSMR2: tm ++;
  210. case OSMR1: tm ++;
  211. case OSMR0:
  212. s->timer[tm].value = value;
  213. pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock));
  214. break;
  215. case OSMR11: tm ++;
  216. case OSMR10: tm ++;
  217. case OSMR9: tm ++;
  218. case OSMR8: tm ++;
  219. case OSMR7: tm ++;
  220. case OSMR6: tm ++;
  221. case OSMR5: tm ++;
  222. case OSMR4:
  223. if (!pxa2xx_timer_has_tm4(s))
  224. goto badreg;
  225. s->tm4[tm].tm.value = value;
  226. pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
  227. break;
  228. case OSCR:
  229. s->oldclock = s->clock;
  230. s->lastload = qemu_get_clock_ns(vm_clock);
  231. s->clock = value;
  232. pxa2xx_timer_update(s, s->lastload);
  233. break;
  234. case OSCR11: tm ++;
  235. case OSCR10: tm ++;
  236. case OSCR9: tm ++;
  237. case OSCR8: tm ++;
  238. case OSCR7: tm ++;
  239. case OSCR6: tm ++;
  240. case OSCR5: tm ++;
  241. case OSCR4:
  242. if (!pxa2xx_timer_has_tm4(s))
  243. goto badreg;
  244. s->tm4[tm].oldclock = s->tm4[tm].clock;
  245. s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock);
  246. s->tm4[tm].clock = value;
  247. pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
  248. break;
  249. case OIER:
  250. s->irq_enabled = value & 0xfff;
  251. break;
  252. case OSSR: /* Status register */
  253. value &= s->events;
  254. s->events &= ~value;
  255. for (i = 0; i < 4; i ++, value >>= 1)
  256. if (value & 1)
  257. qemu_irq_lower(s->timer[i].irq);
  258. if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
  259. qemu_irq_lower(s->irq4);
  260. break;
  261. case OWER: /* XXX: Reset on OSMR3 match? */
  262. s->reset3 = value;
  263. break;
  264. case OMCR7: tm ++;
  265. case OMCR6: tm ++;
  266. case OMCR5: tm ++;
  267. case OMCR4:
  268. if (!pxa2xx_timer_has_tm4(s))
  269. goto badreg;
  270. s->tm4[tm].control = value & 0x0ff;
  271. /* XXX Stop if running (shouldn't happen) */
  272. if ((value & (1 << 7)) || tm == 0)
  273. s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
  274. else {
  275. s->tm4[tm].freq = 0;
  276. pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
  277. }
  278. break;
  279. case OMCR11: tm ++;
  280. case OMCR10: tm ++;
  281. case OMCR9: tm ++;
  282. case OMCR8: tm += 4;
  283. if (!pxa2xx_timer_has_tm4(s))
  284. goto badreg;
  285. s->tm4[tm].control = value & 0x3ff;
  286. /* XXX Stop if running (shouldn't happen) */
  287. if ((value & (1 << 7)) || !(tm & 1))
  288. s->tm4[tm].freq =
  289. pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)];
  290. else {
  291. s->tm4[tm].freq = 0;
  292. pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
  293. }
  294. break;
  295. default:
  296. badreg:
  297. hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
  298. }
  299. }
  300. static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
  301. pxa2xx_timer_read,
  302. pxa2xx_timer_read,
  303. pxa2xx_timer_read,
  304. };
  305. static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
  306. pxa2xx_timer_write,
  307. pxa2xx_timer_write,
  308. pxa2xx_timer_write,
  309. };
  310. static void pxa2xx_timer_tick(void *opaque)
  311. {
  312. PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
  313. PXA2xxTimerInfo *i = t->info;
  314. if (i->irq_enabled & (1 << t->num)) {
  315. i->events |= 1 << t->num;
  316. qemu_irq_raise(t->irq);
  317. }
  318. if (t->num == 3)
  319. if (i->reset3 & 1) {
  320. i->reset3 = 0;
  321. qemu_system_reset_request();
  322. }
  323. }
  324. static void pxa2xx_timer_tick4(void *opaque)
  325. {
  326. PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
  327. PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
  328. pxa2xx_timer_tick(&t->tm);
  329. if (t->control & (1 << 3))
  330. t->clock = 0;
  331. if (t->control & (1 << 6))
  332. pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
  333. if (i->events & 0xff0)
  334. qemu_irq_raise(i->irq4);
  335. }
  336. static int pxa25x_timer_post_load(void *opaque, int version_id)
  337. {
  338. PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
  339. int64_t now;
  340. int i;
  341. now = qemu_get_clock_ns(vm_clock);
  342. pxa2xx_timer_update(s, now);
  343. if (pxa2xx_timer_has_tm4(s))
  344. for (i = 0; i < 8; i ++)
  345. pxa2xx_timer_update4(s, now, i);
  346. return 0;
  347. }
  348. static int pxa2xx_timer_init(SysBusDevice *dev)
  349. {
  350. int i;
  351. int iomemtype;
  352. PXA2xxTimerInfo *s;
  353. s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
  354. s->irq_enabled = 0;
  355. s->oldclock = 0;
  356. s->clock = 0;
  357. s->lastload = qemu_get_clock_ns(vm_clock);
  358. s->reset3 = 0;
  359. for (i = 0; i < 4; i ++) {
  360. s->timer[i].value = 0;
  361. sysbus_init_irq(dev, &s->timer[i].irq);
  362. s->timer[i].info = s;
  363. s->timer[i].num = i;
  364. s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
  365. pxa2xx_timer_tick, &s->timer[i]);
  366. }
  367. if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
  368. sysbus_init_irq(dev, &s->irq4);
  369. for (i = 0; i < 8; i ++) {
  370. s->tm4[i].tm.value = 0;
  371. s->tm4[i].tm.info = s;
  372. s->tm4[i].tm.num = i + 4;
  373. s->tm4[i].freq = 0;
  374. s->tm4[i].control = 0x0;
  375. s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
  376. pxa2xx_timer_tick4, &s->tm4[i]);
  377. }
  378. }
  379. iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
  380. pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
  381. sysbus_init_mmio(dev, 0x00001000, iomemtype);
  382. return 0;
  383. }
  384. static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
  385. .name = "pxa2xx_timer0",
  386. .version_id = 2,
  387. .minimum_version_id = 2,
  388. .minimum_version_id_old = 2,
  389. .fields = (VMStateField[]) {
  390. VMSTATE_UINT32(value, PXA2xxTimer0),
  391. VMSTATE_END_OF_LIST(),
  392. },
  393. };
  394. static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
  395. .name = "pxa2xx_timer4",
  396. .version_id = 1,
  397. .minimum_version_id = 1,
  398. .minimum_version_id_old = 1,
  399. .fields = (VMStateField[]) {
  400. VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
  401. vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
  402. VMSTATE_INT32(oldclock, PXA2xxTimer4),
  403. VMSTATE_INT32(clock, PXA2xxTimer4),
  404. VMSTATE_UINT64(lastload, PXA2xxTimer4),
  405. VMSTATE_UINT32(freq, PXA2xxTimer4),
  406. VMSTATE_UINT32(control, PXA2xxTimer4),
  407. VMSTATE_END_OF_LIST(),
  408. },
  409. };
  410. static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
  411. {
  412. return pxa2xx_timer_has_tm4(opaque);
  413. }
  414. static const VMStateDescription vmstate_pxa2xx_timer_regs = {
  415. .name = "pxa2xx_timer",
  416. .version_id = 1,
  417. .minimum_version_id = 1,
  418. .minimum_version_id_old = 1,
  419. .post_load = pxa25x_timer_post_load,
  420. .fields = (VMStateField[]) {
  421. VMSTATE_INT32(clock, PXA2xxTimerInfo),
  422. VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
  423. VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
  424. VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
  425. vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
  426. VMSTATE_UINT32(events, PXA2xxTimerInfo),
  427. VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
  428. VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
  429. VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
  430. VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
  431. pxa2xx_timer_has_tm4_test, 0,
  432. vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
  433. VMSTATE_END_OF_LIST(),
  434. }
  435. };
  436. static SysBusDeviceInfo pxa25x_timer_dev_info = {
  437. .init = pxa2xx_timer_init,
  438. .qdev.name = "pxa25x-timer",
  439. .qdev.desc = "PXA25x timer",
  440. .qdev.size = sizeof(PXA2xxTimerInfo),
  441. .qdev.vmsd = &vmstate_pxa2xx_timer_regs,
  442. .qdev.props = (Property[]) {
  443. DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
  444. DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
  445. PXA2XX_TIMER_HAVE_TM4, false),
  446. DEFINE_PROP_END_OF_LIST(),
  447. },
  448. };
  449. static SysBusDeviceInfo pxa27x_timer_dev_info = {
  450. .init = pxa2xx_timer_init,
  451. .qdev.name = "pxa27x-timer",
  452. .qdev.desc = "PXA27x timer",
  453. .qdev.size = sizeof(PXA2xxTimerInfo),
  454. .qdev.vmsd = &vmstate_pxa2xx_timer_regs,
  455. .qdev.props = (Property[]) {
  456. DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
  457. DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
  458. PXA2XX_TIMER_HAVE_TM4, true),
  459. DEFINE_PROP_END_OF_LIST(),
  460. },
  461. };
  462. static void pxa2xx_timer_register(void)
  463. {
  464. sysbus_register_withprop(&pxa25x_timer_dev_info);
  465. sysbus_register_withprop(&pxa27x_timer_dev_info);
  466. };
  467. device_init(pxa2xx_timer_register);