mpcore.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * ARM MPCore internal peripheral emulation.
  3. *
  4. * Copyright (c) 2006-2007 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licenced under the GPL.
  8. */
  9. #include "hw.h"
  10. #include "qemu-timer.h"
  11. #include "primecell.h"
  12. #define MPCORE_PRIV_BASE 0x10100000
  13. #define NCPU 4
  14. /* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
  15. (+ 32 internal). However my test chip only exposes/reports 32.
  16. More importantly Linux falls over if more than 32 are present! */
  17. #define GIC_NIRQ 64
  18. static inline int
  19. gic_get_current_cpu(void)
  20. {
  21. return cpu_single_env->cpu_index;
  22. }
  23. #include "arm_gic.c"
  24. /* MPCore private memory region. */
  25. typedef struct {
  26. uint32_t count;
  27. uint32_t load;
  28. uint32_t control;
  29. uint32_t status;
  30. uint32_t old_status;
  31. int64_t tick;
  32. QEMUTimer *timer;
  33. struct mpcore_priv_state *mpcore;
  34. int id; /* Encodes both timer/watchdog and CPU. */
  35. } mpcore_timer_state;
  36. typedef struct mpcore_priv_state {
  37. gic_state *gic;
  38. uint32_t scu_control;
  39. mpcore_timer_state timer[8];
  40. } mpcore_priv_state;
  41. /* Per-CPU Timers. */
  42. static inline void mpcore_timer_update_irq(mpcore_timer_state *s)
  43. {
  44. if (s->status & ~s->old_status) {
  45. gic_set_pending_private(s->mpcore->gic, s->id >> 1, 29 + (s->id & 1));
  46. }
  47. s->old_status = s->status;
  48. }
  49. /* Return conversion factor from mpcore timer ticks to qemu timer ticks. */
  50. static inline uint32_t mpcore_timer_scale(mpcore_timer_state *s)
  51. {
  52. return (((s->control >> 8) & 0xff) + 1) * 10;
  53. }
  54. static void mpcore_timer_reload(mpcore_timer_state *s, int restart)
  55. {
  56. if (s->count == 0)
  57. return;
  58. if (restart)
  59. s->tick = qemu_get_clock(vm_clock);
  60. s->tick += (int64_t)s->count * mpcore_timer_scale(s);
  61. qemu_mod_timer(s->timer, s->tick);
  62. }
  63. static void mpcore_timer_tick(void *opaque)
  64. {
  65. mpcore_timer_state *s = (mpcore_timer_state *)opaque;
  66. s->status = 1;
  67. if (s->control & 2) {
  68. s->count = s->load;
  69. mpcore_timer_reload(s, 0);
  70. } else {
  71. s->count = 0;
  72. }
  73. mpcore_timer_update_irq(s);
  74. }
  75. static uint32_t mpcore_timer_read(mpcore_timer_state *s, int offset)
  76. {
  77. int64_t val;
  78. switch (offset) {
  79. case 0: /* Load */
  80. return s->load;
  81. /* Fall through. */
  82. case 4: /* Counter. */
  83. if (((s->control & 1) == 0) || (s->count == 0))
  84. return 0;
  85. /* Slow and ugly, but hopefully won't happen too often. */
  86. val = s->tick - qemu_get_clock(vm_clock);
  87. val /= mpcore_timer_scale(s);
  88. if (val < 0)
  89. val = 0;
  90. return val;
  91. case 8: /* Control. */
  92. return s->control;
  93. case 12: /* Interrupt status. */
  94. return s->status;
  95. default:
  96. return 0;
  97. }
  98. }
  99. static void mpcore_timer_write(mpcore_timer_state *s, int offset,
  100. uint32_t value)
  101. {
  102. int64_t old;
  103. switch (offset) {
  104. case 0: /* Load */
  105. s->load = value;
  106. /* Fall through. */
  107. case 4: /* Counter. */
  108. if ((s->control & 1) && s->count) {
  109. /* Cancel the previous timer. */
  110. qemu_del_timer(s->timer);
  111. }
  112. s->count = value;
  113. if (s->control & 1) {
  114. mpcore_timer_reload(s, 1);
  115. }
  116. break;
  117. case 8: /* Control. */
  118. old = s->control;
  119. s->control = value;
  120. if (((old & 1) == 0) && (value & 1)) {
  121. if (s->count == 0 && (s->control & 2))
  122. s->count = s->load;
  123. mpcore_timer_reload(s, 1);
  124. }
  125. break;
  126. case 12: /* Interrupt status. */
  127. s->status &= ~value;
  128. mpcore_timer_update_irq(s);
  129. break;
  130. }
  131. }
  132. static void mpcore_timer_init(mpcore_priv_state *mpcore,
  133. mpcore_timer_state *s, int id)
  134. {
  135. s->id = id;
  136. s->mpcore = mpcore;
  137. s->timer = qemu_new_timer(vm_clock, mpcore_timer_tick, s);
  138. }
  139. /* Per-CPU private memory mapped IO. */
  140. static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
  141. {
  142. mpcore_priv_state *s = (mpcore_priv_state *)opaque;
  143. int id;
  144. offset &= 0xfff;
  145. if (offset < 0x100) {
  146. /* SCU */
  147. switch (offset) {
  148. case 0x00: /* Control. */
  149. return s->scu_control;
  150. case 0x04: /* Configuration. */
  151. return 0xf3;
  152. case 0x08: /* CPU status. */
  153. return 0;
  154. case 0x0c: /* Invalidate all. */
  155. return 0;
  156. default:
  157. goto bad_reg;
  158. }
  159. } else if (offset < 0x600) {
  160. /* Interrupt controller. */
  161. if (offset < 0x200) {
  162. id = gic_get_current_cpu();
  163. } else {
  164. id = (offset - 0x200) >> 8;
  165. }
  166. return gic_cpu_read(s->gic, id, offset & 0xff);
  167. } else if (offset < 0xb00) {
  168. /* Timers. */
  169. if (offset < 0x700) {
  170. id = gic_get_current_cpu();
  171. } else {
  172. id = (offset - 0x700) >> 8;
  173. }
  174. id <<= 1;
  175. if (offset & 0x20)
  176. id++;
  177. return mpcore_timer_read(&s->timer[id], offset & 0xf);
  178. }
  179. bad_reg:
  180. cpu_abort(cpu_single_env, "mpcore_priv_read: Bad offset %x\n",
  181. (int)offset);
  182. return 0;
  183. }
  184. static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
  185. uint32_t value)
  186. {
  187. mpcore_priv_state *s = (mpcore_priv_state *)opaque;
  188. int id;
  189. offset &= 0xfff;
  190. if (offset < 0x100) {
  191. /* SCU */
  192. switch (offset) {
  193. case 0: /* Control register. */
  194. s->scu_control = value & 1;
  195. break;
  196. case 0x0c: /* Invalidate all. */
  197. /* This is a no-op as cache is not emulated. */
  198. break;
  199. default:
  200. goto bad_reg;
  201. }
  202. } else if (offset < 0x600) {
  203. /* Interrupt controller. */
  204. if (offset < 0x200) {
  205. id = gic_get_current_cpu();
  206. } else {
  207. id = (offset - 0x200) >> 8;
  208. }
  209. gic_cpu_write(s->gic, id, offset & 0xff, value);
  210. } else if (offset < 0xb00) {
  211. /* Timers. */
  212. if (offset < 0x700) {
  213. id = gic_get_current_cpu();
  214. } else {
  215. id = (offset - 0x700) >> 8;
  216. }
  217. id <<= 1;
  218. if (offset & 0x20)
  219. id++;
  220. mpcore_timer_write(&s->timer[id], offset & 0xf, value);
  221. return;
  222. }
  223. return;
  224. bad_reg:
  225. cpu_abort(cpu_single_env, "mpcore_priv_read: Bad offset %x\n",
  226. (int)offset);
  227. }
  228. static CPUReadMemoryFunc *mpcore_priv_readfn[] = {
  229. mpcore_priv_read,
  230. mpcore_priv_read,
  231. mpcore_priv_read
  232. };
  233. static CPUWriteMemoryFunc *mpcore_priv_writefn[] = {
  234. mpcore_priv_write,
  235. mpcore_priv_write,
  236. mpcore_priv_write
  237. };
  238. static qemu_irq *mpcore_priv_init(uint32_t base, qemu_irq *pic_irq)
  239. {
  240. mpcore_priv_state *s;
  241. int iomemtype;
  242. int i;
  243. s = (mpcore_priv_state *)qemu_mallocz(sizeof(mpcore_priv_state));
  244. s->gic = gic_init(base + 0x1000, pic_irq);
  245. if (!s->gic)
  246. return NULL;
  247. iomemtype = cpu_register_io_memory(0, mpcore_priv_readfn,
  248. mpcore_priv_writefn, s);
  249. cpu_register_physical_memory(base, 0x00001000, iomemtype);
  250. for (i = 0; i < 8; i++) {
  251. mpcore_timer_init(s, &s->timer[i], i);
  252. }
  253. return s->gic->in;
  254. }
  255. /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
  256. controllers. The output of these, plus some of the raw input lines
  257. are fed into a single SMP-aware interrupt controller on the CPU. */
  258. typedef struct {
  259. qemu_irq *cpuic;
  260. qemu_irq *rvic[4];
  261. } mpcore_rirq_state;
  262. /* Map baseboard IRQs onto CPU IRQ lines. */
  263. static const int mpcore_irq_map[32] = {
  264. -1, -1, -1, -1, 1, 2, -1, -1,
  265. -1, -1, 6, -1, 4, 5, -1, -1,
  266. -1, 14, 15, 0, 7, 8, -1, -1,
  267. -1, -1, -1, -1, 9, 3, -1, -1,
  268. };
  269. static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
  270. {
  271. mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
  272. int i;
  273. for (i = 0; i < 4; i++) {
  274. qemu_set_irq(s->rvic[i][irq], level);
  275. }
  276. if (irq < 32) {
  277. irq = mpcore_irq_map[irq];
  278. if (irq >= 0) {
  279. qemu_set_irq(s->cpuic[irq], level);
  280. }
  281. }
  282. }
  283. qemu_irq *mpcore_irq_init(qemu_irq *cpu_irq)
  284. {
  285. mpcore_rirq_state *s;
  286. int n;
  287. /* ??? IRQ routing is hardcoded to "normal" mode. */
  288. s = qemu_mallocz(sizeof(mpcore_rirq_state));
  289. s->cpuic = mpcore_priv_init(MPCORE_PRIV_BASE, cpu_irq);
  290. for (n = 0; n < 4; n++) {
  291. s->rvic[n] = realview_gic_init(0x10040000 + n * 0x10000,
  292. s->cpuic[10 + n]);
  293. }
  294. return qemu_allocate_irqs(mpcore_rirq_set_irq, s, 64);
  295. }