pl031.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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 "hw.h"
  12. #include "primecell.h"
  13. #include "qemu-timer.h"
  14. #include "sysemu.h"
  15. //#define DEBUG_PL031
  16. #ifdef DEBUG_PL031
  17. #define DPRINTF(fmt, args...) \
  18. do { printf("pl031: " fmt , ##args); } while (0)
  19. #else
  20. #define DPRINTF(fmt, args...) do {} while(0)
  21. #endif
  22. #define RTC_DR 0x00 /* Data read register */
  23. #define RTC_MR 0x04 /* Match register */
  24. #define RTC_LR 0x08 /* Data load register */
  25. #define RTC_CR 0x0c /* Control register */
  26. #define RTC_IMSC 0x10 /* Interrupt mask and set register */
  27. #define RTC_RIS 0x14 /* Raw interrupt status register */
  28. #define RTC_MIS 0x18 /* Masked interrupt status register */
  29. #define RTC_ICR 0x1c /* Interrupt clear register */
  30. typedef struct {
  31. QEMUTimer *timer;
  32. qemu_irq irq;
  33. uint32_t tick_offset;
  34. uint32_t mr;
  35. uint32_t lr;
  36. uint32_t cr;
  37. uint32_t im;
  38. uint32_t is;
  39. } pl031_state;
  40. static const unsigned char pl031_id[] = {
  41. 0x31, 0x10, 0x14, 0x00, /* Device ID */
  42. 0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
  43. };
  44. static void pl031_update(pl031_state *s)
  45. {
  46. qemu_set_irq(s->irq, s->is & s->im);
  47. }
  48. static void pl031_interrupt(void * opaque)
  49. {
  50. pl031_state *s = (pl031_state *)opaque;
  51. s->im = 1;
  52. DPRINTF("Alarm raised\n");
  53. pl031_update(s);
  54. }
  55. static uint32_t pl031_get_count(pl031_state *s)
  56. {
  57. /* This assumes qemu_get_clock returns the time since the machine was
  58. created. */
  59. return s->tick_offset + qemu_get_clock(vm_clock) / ticks_per_sec;
  60. }
  61. static void pl031_set_alarm(pl031_state *s)
  62. {
  63. int64_t now;
  64. uint32_t ticks;
  65. now = qemu_get_clock(vm_clock);
  66. ticks = s->tick_offset + now / ticks_per_sec;
  67. /* The timer wraps around. This subtraction also wraps in the same way,
  68. and gives correct results when alarm < now_ticks. */
  69. ticks = s->mr - ticks;
  70. DPRINTF("Alarm set in %ud ticks\n", ticks);
  71. if (ticks == 0) {
  72. qemu_del_timer(s->timer);
  73. pl031_interrupt(s);
  74. } else {
  75. qemu_mod_timer(s->timer, now + (int64_t)ticks * ticks_per_sec);
  76. }
  77. }
  78. static uint32_t pl031_read(void *opaque, target_phys_addr_t offset)
  79. {
  80. pl031_state *s = (pl031_state *)opaque;
  81. if (offset >= 0xfe0 && offset < 0x1000)
  82. return pl031_id[(offset - 0xfe0) >> 2];
  83. switch (offset) {
  84. case RTC_DR:
  85. return pl031_get_count(s);
  86. case RTC_MR:
  87. return s->mr;
  88. case RTC_IMSC:
  89. return s->im;
  90. case RTC_RIS:
  91. return s->is;
  92. case RTC_LR:
  93. return s->lr;
  94. case RTC_CR:
  95. /* RTC is permanently enabled. */
  96. return 1;
  97. case RTC_MIS:
  98. return s->is & s->im;
  99. case RTC_ICR:
  100. fprintf(stderr, "qemu: pl031_read: Unexpected offset 0x%x\n",
  101. (int)offset);
  102. break;
  103. default:
  104. cpu_abort(cpu_single_env, "pl031_read: Bad offset 0x%x\n",
  105. (int)offset);
  106. break;
  107. }
  108. return 0;
  109. }
  110. static void pl031_write(void * opaque, target_phys_addr_t offset,
  111. uint32_t value)
  112. {
  113. pl031_state *s = (pl031_state *)opaque;
  114. switch (offset) {
  115. case RTC_LR:
  116. s->tick_offset += value - pl031_get_count(s);
  117. pl031_set_alarm(s);
  118. break;
  119. case RTC_MR:
  120. s->mr = value;
  121. pl031_set_alarm(s);
  122. break;
  123. case RTC_IMSC:
  124. s->im = value & 1;
  125. DPRINTF("Interrupt mask %d\n", s->im);
  126. pl031_update(s);
  127. break;
  128. case RTC_ICR:
  129. /* The PL031 documentation (DDI0224B) states that the interupt is
  130. cleared when bit 0 of the written value is set. However the
  131. arm926e documentation (DDI0287B) states that the interrupt is
  132. cleared when any value is written. */
  133. DPRINTF("Interrupt cleared");
  134. s->is = 0;
  135. pl031_update(s);
  136. break;
  137. case RTC_CR:
  138. /* Written value is ignored. */
  139. break;
  140. case RTC_DR:
  141. case RTC_MIS:
  142. case RTC_RIS:
  143. fprintf(stderr, "qemu: pl031_write: Unexpected offset 0x%x\n",
  144. (int)offset);
  145. break;
  146. default:
  147. cpu_abort(cpu_single_env, "pl031_write: Bad offset 0x%x\n",
  148. (int)offset);
  149. break;
  150. }
  151. }
  152. static CPUWriteMemoryFunc * pl031_writefn[] = {
  153. pl031_write,
  154. pl031_write,
  155. pl031_write
  156. };
  157. static CPUReadMemoryFunc * pl031_readfn[] = {
  158. pl031_read,
  159. pl031_read,
  160. pl031_read
  161. };
  162. void pl031_init(uint32_t base, qemu_irq irq)
  163. {
  164. int iomemtype;
  165. pl031_state *s;
  166. struct tm tm;
  167. s = qemu_mallocz(sizeof(pl031_state));
  168. iomemtype = cpu_register_io_memory(0, pl031_readfn, pl031_writefn, s);
  169. if (iomemtype == -1)
  170. cpu_abort(cpu_single_env, "pl031_init: Can't register I/O memory\n");
  171. cpu_register_physical_memory(base, 0x00001000, iomemtype);
  172. s->irq = irq;
  173. /* ??? We assume vm_clock is zero at this point. */
  174. qemu_get_timedate(&tm, 0);
  175. s->tick_offset = mktimegm(&tm);
  176. s->timer = qemu_new_timer(vm_clock, pl031_interrupt, s);
  177. }