2
0

xilinx_timer.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * QEMU model of the Xilinx timer block.
  3. *
  4. * Copyright (c) 2009 Edgar E. Iglesias.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "sysbus.h"
  25. #include "qemu-timer.h"
  26. #define D(x)
  27. #define R_TCSR 0
  28. #define R_TLR 1
  29. #define R_TCR 2
  30. #define R_MAX 4
  31. #define TCSR_MDT (1<<0)
  32. #define TCSR_UDT (1<<1)
  33. #define TCSR_GENT (1<<2)
  34. #define TCSR_CAPT (1<<3)
  35. #define TCSR_ARHT (1<<4)
  36. #define TCSR_LOAD (1<<5)
  37. #define TCSR_ENIT (1<<6)
  38. #define TCSR_ENT (1<<7)
  39. #define TCSR_TINT (1<<8)
  40. #define TCSR_PWMA (1<<9)
  41. #define TCSR_ENALL (1<<10)
  42. struct xlx_timer
  43. {
  44. QEMUBH *bh;
  45. ptimer_state *ptimer;
  46. void *parent;
  47. int nr; /* for debug. */
  48. unsigned long timer_div;
  49. uint32_t regs[R_MAX];
  50. };
  51. struct timerblock
  52. {
  53. SysBusDevice busdev;
  54. qemu_irq irq;
  55. uint32_t nr_timers;
  56. uint32_t freq_hz;
  57. struct xlx_timer *timers;
  58. };
  59. static inline unsigned int timer_from_addr(target_phys_addr_t addr)
  60. {
  61. /* Timers get a 4x32bit control reg area each. */
  62. return addr >> 2;
  63. }
  64. static void timer_update_irq(struct timerblock *t)
  65. {
  66. unsigned int i, irq = 0;
  67. uint32_t csr;
  68. for (i = 0; i < t->nr_timers; i++) {
  69. csr = t->timers[i].regs[R_TCSR];
  70. irq |= (csr & TCSR_TINT) && (csr & TCSR_ENIT);
  71. }
  72. /* All timers within the same slave share a single IRQ line. */
  73. qemu_set_irq(t->irq, !!irq);
  74. }
  75. static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
  76. {
  77. struct timerblock *t = opaque;
  78. struct xlx_timer *xt;
  79. uint32_t r = 0;
  80. unsigned int timer;
  81. addr >>= 2;
  82. timer = timer_from_addr(addr);
  83. xt = &t->timers[timer];
  84. /* Further decoding to address a specific timers reg. */
  85. addr &= 0x3;
  86. switch (addr)
  87. {
  88. case R_TCR:
  89. r = ptimer_get_count(xt->ptimer);
  90. if (!(xt->regs[R_TCSR] & TCSR_UDT))
  91. r = ~r;
  92. D(qemu_log("xlx_timer t=%d read counter=%x udt=%d\n",
  93. timer, r, xt->regs[R_TCSR] & TCSR_UDT));
  94. break;
  95. default:
  96. if (addr < ARRAY_SIZE(xt->regs))
  97. r = xt->regs[addr];
  98. break;
  99. }
  100. D(printf("%s timer=%d %x=%x\n", __func__, timer, addr * 4, r));
  101. return r;
  102. }
  103. static void timer_enable(struct xlx_timer *xt)
  104. {
  105. uint64_t count;
  106. D(printf("%s timer=%d down=%d\n", __func__,
  107. xt->nr, xt->regs[R_TCSR] & TCSR_UDT));
  108. ptimer_stop(xt->ptimer);
  109. if (xt->regs[R_TCSR] & TCSR_UDT)
  110. count = xt->regs[R_TLR];
  111. else
  112. count = ~0 - xt->regs[R_TLR];
  113. ptimer_set_count(xt->ptimer, count);
  114. ptimer_run(xt->ptimer, 1);
  115. }
  116. static void
  117. timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
  118. {
  119. struct timerblock *t = opaque;
  120. struct xlx_timer *xt;
  121. unsigned int timer;
  122. addr >>= 2;
  123. timer = timer_from_addr(addr);
  124. xt = &t->timers[timer];
  125. D(printf("%s addr=%x val=%x (timer=%d off=%d)\n",
  126. __func__, addr * 4, value, timer, addr & 3));
  127. /* Further decoding to address a specific timers reg. */
  128. addr &= 3;
  129. switch (addr)
  130. {
  131. case R_TCSR:
  132. if (value & TCSR_TINT)
  133. value &= ~TCSR_TINT;
  134. xt->regs[addr] = value;
  135. if (value & TCSR_ENT)
  136. timer_enable(xt);
  137. break;
  138. default:
  139. if (addr < ARRAY_SIZE(xt->regs))
  140. xt->regs[addr] = value;
  141. break;
  142. }
  143. timer_update_irq(t);
  144. }
  145. static CPUReadMemoryFunc * const timer_read[] = {
  146. NULL, NULL,
  147. &timer_readl,
  148. };
  149. static CPUWriteMemoryFunc * const timer_write[] = {
  150. NULL, NULL,
  151. &timer_writel,
  152. };
  153. static void timer_hit(void *opaque)
  154. {
  155. struct xlx_timer *xt = opaque;
  156. struct timerblock *t = xt->parent;
  157. D(printf("%s %d\n", __func__, timer));
  158. xt->regs[R_TCSR] |= TCSR_TINT;
  159. if (xt->regs[R_TCSR] & TCSR_ARHT)
  160. timer_enable(xt);
  161. timer_update_irq(t);
  162. }
  163. static int xilinx_timer_init(SysBusDevice *dev)
  164. {
  165. struct timerblock *t = FROM_SYSBUS(typeof (*t), dev);
  166. unsigned int i;
  167. int timer_regs;
  168. /* All timers share a single irq line. */
  169. sysbus_init_irq(dev, &t->irq);
  170. /* Init all the ptimers. */
  171. t->timers = qemu_mallocz(sizeof t->timers[0] * t->nr_timers);
  172. for (i = 0; i < t->nr_timers; i++) {
  173. struct xlx_timer *xt = &t->timers[i];
  174. xt->parent = t;
  175. xt->nr = i;
  176. xt->bh = qemu_bh_new(timer_hit, xt);
  177. xt->ptimer = ptimer_init(xt->bh);
  178. ptimer_set_freq(xt->ptimer, t->freq_hz);
  179. }
  180. timer_regs = cpu_register_io_memory(timer_read, timer_write, t,
  181. DEVICE_NATIVE_ENDIAN);
  182. sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs);
  183. return 0;
  184. }
  185. static SysBusDeviceInfo xilinx_timer_info = {
  186. .init = xilinx_timer_init,
  187. .qdev.name = "xilinx,timer",
  188. .qdev.size = sizeof(struct timerblock),
  189. .qdev.props = (Property[]) {
  190. DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 0),
  191. DEFINE_PROP_UINT32("nr-timers", struct timerblock, nr_timers, 0),
  192. DEFINE_PROP_END_OF_LIST(),
  193. }
  194. };
  195. static void xilinx_timer_register(void)
  196. {
  197. sysbus_register_withprop(&xilinx_timer_info);
  198. }
  199. device_init(xilinx_timer_register)