pl031.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * ARM AMBA PrimeCell PL031 RTC
  3. *
  4. * Copyright (c) 2007 CodeSourcery
  5. *
  6. * This file is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. */
  11. #include "sysbus.h"
  12. #include "qemu-timer.h"
  13. //#define DEBUG_PL031
  14. #ifdef DEBUG_PL031
  15. #define DPRINTF(fmt, ...) \
  16. do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
  17. #else
  18. #define DPRINTF(fmt, ...) do {} while(0)
  19. #endif
  20. #define RTC_DR 0x00 /* Data read register */
  21. #define RTC_MR 0x04 /* Match register */
  22. #define RTC_LR 0x08 /* Data load register */
  23. #define RTC_CR 0x0c /* Control register */
  24. #define RTC_IMSC 0x10 /* Interrupt mask and set register */
  25. #define RTC_RIS 0x14 /* Raw interrupt status register */
  26. #define RTC_MIS 0x18 /* Masked interrupt status register */
  27. #define RTC_ICR 0x1c /* Interrupt clear register */
  28. typedef struct {
  29. SysBusDevice busdev;
  30. QEMUTimer *timer;
  31. qemu_irq irq;
  32. uint32_t tick_offset;
  33. uint32_t mr;
  34. uint32_t lr;
  35. uint32_t cr;
  36. uint32_t im;
  37. uint32_t is;
  38. } pl031_state;
  39. static const VMStateDescription vmstate_pl031 = {
  40. .name = "pl031",
  41. .version_id = 1,
  42. .minimum_version_id = 1,
  43. .fields = (VMStateField[]) {
  44. VMSTATE_UINT32(tick_offset, pl031_state),
  45. VMSTATE_UINT32(mr, pl031_state),
  46. VMSTATE_UINT32(lr, pl031_state),
  47. VMSTATE_UINT32(cr, pl031_state),
  48. VMSTATE_UINT32(im, pl031_state),
  49. VMSTATE_UINT32(is, pl031_state),
  50. VMSTATE_END_OF_LIST()
  51. }
  52. };
  53. static const unsigned char pl031_id[] = {
  54. 0x31, 0x10, 0x14, 0x00, /* Device ID */
  55. 0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
  56. };
  57. static void pl031_update(pl031_state *s)
  58. {
  59. qemu_set_irq(s->irq, s->is & s->im);
  60. }
  61. static void pl031_interrupt(void * opaque)
  62. {
  63. pl031_state *s = (pl031_state *)opaque;
  64. s->im = 1;
  65. DPRINTF("Alarm raised\n");
  66. pl031_update(s);
  67. }
  68. static uint32_t pl031_get_count(pl031_state *s)
  69. {
  70. /* This assumes qemu_get_clock_ns returns the time since the machine was
  71. created. */
  72. return s->tick_offset + qemu_get_clock_ns(vm_clock) / get_ticks_per_sec();
  73. }
  74. static void pl031_set_alarm(pl031_state *s)
  75. {
  76. int64_t now;
  77. uint32_t ticks;
  78. now = qemu_get_clock_ns(vm_clock);
  79. ticks = s->tick_offset + now / get_ticks_per_sec();
  80. /* The timer wraps around. This subtraction also wraps in the same way,
  81. and gives correct results when alarm < now_ticks. */
  82. ticks = s->mr - ticks;
  83. DPRINTF("Alarm set in %ud ticks\n", ticks);
  84. if (ticks == 0) {
  85. qemu_del_timer(s->timer);
  86. pl031_interrupt(s);
  87. } else {
  88. qemu_mod_timer(s->timer, now + (int64_t)ticks * get_ticks_per_sec());
  89. }
  90. }
  91. static uint32_t pl031_read(void *opaque, target_phys_addr_t offset)
  92. {
  93. pl031_state *s = (pl031_state *)opaque;
  94. if (offset >= 0xfe0 && offset < 0x1000)
  95. return pl031_id[(offset - 0xfe0) >> 2];
  96. switch (offset) {
  97. case RTC_DR:
  98. return pl031_get_count(s);
  99. case RTC_MR:
  100. return s->mr;
  101. case RTC_IMSC:
  102. return s->im;
  103. case RTC_RIS:
  104. return s->is;
  105. case RTC_LR:
  106. return s->lr;
  107. case RTC_CR:
  108. /* RTC is permanently enabled. */
  109. return 1;
  110. case RTC_MIS:
  111. return s->is & s->im;
  112. case RTC_ICR:
  113. fprintf(stderr, "qemu: pl031_read: Unexpected offset 0x%x\n",
  114. (int)offset);
  115. break;
  116. default:
  117. hw_error("pl031_read: Bad offset 0x%x\n", (int)offset);
  118. break;
  119. }
  120. return 0;
  121. }
  122. static void pl031_write(void * opaque, target_phys_addr_t offset,
  123. uint32_t value)
  124. {
  125. pl031_state *s = (pl031_state *)opaque;
  126. switch (offset) {
  127. case RTC_LR:
  128. s->tick_offset += value - pl031_get_count(s);
  129. pl031_set_alarm(s);
  130. break;
  131. case RTC_MR:
  132. s->mr = value;
  133. pl031_set_alarm(s);
  134. break;
  135. case RTC_IMSC:
  136. s->im = value & 1;
  137. DPRINTF("Interrupt mask %d\n", s->im);
  138. pl031_update(s);
  139. break;
  140. case RTC_ICR:
  141. /* The PL031 documentation (DDI0224B) states that the interrupt is
  142. cleared when bit 0 of the written value is set. However the
  143. arm926e documentation (DDI0287B) states that the interrupt is
  144. cleared when any value is written. */
  145. DPRINTF("Interrupt cleared");
  146. s->is = 0;
  147. pl031_update(s);
  148. break;
  149. case RTC_CR:
  150. /* Written value is ignored. */
  151. break;
  152. case RTC_DR:
  153. case RTC_MIS:
  154. case RTC_RIS:
  155. fprintf(stderr, "qemu: pl031_write: Unexpected offset 0x%x\n",
  156. (int)offset);
  157. break;
  158. default:
  159. hw_error("pl031_write: Bad offset 0x%x\n", (int)offset);
  160. break;
  161. }
  162. }
  163. static CPUWriteMemoryFunc * const pl031_writefn[] = {
  164. pl031_write,
  165. pl031_write,
  166. pl031_write
  167. };
  168. static CPUReadMemoryFunc * const pl031_readfn[] = {
  169. pl031_read,
  170. pl031_read,
  171. pl031_read
  172. };
  173. static int pl031_init(SysBusDevice *dev)
  174. {
  175. int iomemtype;
  176. pl031_state *s = FROM_SYSBUS(pl031_state, dev);
  177. struct tm tm;
  178. iomemtype = cpu_register_io_memory(pl031_readfn, pl031_writefn, s,
  179. DEVICE_NATIVE_ENDIAN);
  180. if (iomemtype == -1) {
  181. hw_error("pl031_init: Can't register I/O memory\n");
  182. }
  183. sysbus_init_mmio(dev, 0x1000, iomemtype);
  184. sysbus_init_irq(dev, &s->irq);
  185. /* ??? We assume vm_clock is zero at this point. */
  186. qemu_get_timedate(&tm, 0);
  187. s->tick_offset = mktimegm(&tm);
  188. s->timer = qemu_new_timer_ns(vm_clock, pl031_interrupt, s);
  189. return 0;
  190. }
  191. static SysBusDeviceInfo pl031_info = {
  192. .init = pl031_init,
  193. .qdev.name = "pl031",
  194. .qdev.size = sizeof(pl031_state),
  195. .qdev.vmsd = &vmstate_pl031,
  196. .qdev.no_user = 1,
  197. };
  198. static void pl031_register_devices(void)
  199. {
  200. sysbus_register_withprop(&pl031_info);
  201. }
  202. device_init(pl031_register_devices)