a9mpcore.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Cortex-A9MPCore internal peripheral emulation.
  3. *
  4. * Copyright (c) 2009 CodeSourcery.
  5. * Copyright (c) 2011 Linaro Limited.
  6. * Written by Paul Brook, Peter Maydell.
  7. *
  8. * This code is licensed under the GPL.
  9. */
  10. #include "sysbus.h"
  11. /* A9MP private memory region. */
  12. typedef struct a9mp_priv_state {
  13. SysBusDevice busdev;
  14. uint32_t scu_control;
  15. uint32_t scu_status;
  16. uint32_t old_timer_status[8];
  17. uint32_t num_cpu;
  18. MemoryRegion scu_iomem;
  19. MemoryRegion ptimer_iomem;
  20. MemoryRegion container;
  21. DeviceState *mptimer;
  22. DeviceState *gic;
  23. uint32_t num_irq;
  24. } a9mp_priv_state;
  25. static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
  26. unsigned size)
  27. {
  28. a9mp_priv_state *s = (a9mp_priv_state *)opaque;
  29. switch (offset) {
  30. case 0x00: /* Control */
  31. return s->scu_control;
  32. case 0x04: /* Configuration */
  33. return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
  34. case 0x08: /* CPU Power Status */
  35. return s->scu_status;
  36. case 0x09: /* CPU status. */
  37. return s->scu_status >> 8;
  38. case 0x0a: /* CPU status. */
  39. return s->scu_status >> 16;
  40. case 0x0b: /* CPU status. */
  41. return s->scu_status >> 24;
  42. case 0x0c: /* Invalidate All Registers In Secure State */
  43. return 0;
  44. case 0x40: /* Filtering Start Address Register */
  45. case 0x44: /* Filtering End Address Register */
  46. /* RAZ/WI, like an implementation with only one AXI master */
  47. return 0;
  48. case 0x50: /* SCU Access Control Register */
  49. case 0x54: /* SCU Non-secure Access Control Register */
  50. /* unimplemented, fall through */
  51. default:
  52. return 0;
  53. }
  54. }
  55. static void a9_scu_write(void *opaque, target_phys_addr_t offset,
  56. uint64_t value, unsigned size)
  57. {
  58. a9mp_priv_state *s = (a9mp_priv_state *)opaque;
  59. uint32_t mask;
  60. uint32_t shift;
  61. switch (size) {
  62. case 1:
  63. mask = 0xff;
  64. break;
  65. case 2:
  66. mask = 0xffff;
  67. break;
  68. case 4:
  69. mask = 0xffffffff;
  70. break;
  71. default:
  72. fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
  73. size, (unsigned)offset);
  74. return;
  75. }
  76. switch (offset) {
  77. case 0x00: /* Control */
  78. s->scu_control = value & 1;
  79. break;
  80. case 0x4: /* Configuration: RO */
  81. break;
  82. case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
  83. shift = (offset - 0x8) * 8;
  84. s->scu_status &= ~(mask << shift);
  85. s->scu_status |= ((value & mask) << shift);
  86. break;
  87. case 0x0c: /* Invalidate All Registers In Secure State */
  88. /* no-op as we do not implement caches */
  89. break;
  90. case 0x40: /* Filtering Start Address Register */
  91. case 0x44: /* Filtering End Address Register */
  92. /* RAZ/WI, like an implementation with only one AXI master */
  93. break;
  94. case 0x50: /* SCU Access Control Register */
  95. case 0x54: /* SCU Non-secure Access Control Register */
  96. /* unimplemented, fall through */
  97. default:
  98. break;
  99. }
  100. }
  101. static const MemoryRegionOps a9_scu_ops = {
  102. .read = a9_scu_read,
  103. .write = a9_scu_write,
  104. .endianness = DEVICE_NATIVE_ENDIAN,
  105. };
  106. static void a9mp_priv_reset(DeviceState *dev)
  107. {
  108. a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, sysbus_from_qdev(dev));
  109. int i;
  110. s->scu_control = 0;
  111. for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
  112. s->old_timer_status[i] = 0;
  113. }
  114. }
  115. static void a9mp_priv_set_irq(void *opaque, int irq, int level)
  116. {
  117. a9mp_priv_state *s = (a9mp_priv_state *)opaque;
  118. qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
  119. }
  120. static int a9mp_priv_init(SysBusDevice *dev)
  121. {
  122. a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, dev);
  123. SysBusDevice *busdev, *gicbusdev;
  124. int i;
  125. s->gic = qdev_create(NULL, "arm_gic");
  126. qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
  127. qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
  128. qdev_init_nofail(s->gic);
  129. gicbusdev = sysbus_from_qdev(s->gic);
  130. /* Pass through outbound IRQ lines from the GIC */
  131. sysbus_pass_irq(dev, gicbusdev);
  132. /* Pass through inbound GPIO lines to the GIC */
  133. qdev_init_gpio_in(&s->busdev.qdev, a9mp_priv_set_irq, s->num_irq - 32);
  134. s->mptimer = qdev_create(NULL, "arm_mptimer");
  135. qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
  136. qdev_init_nofail(s->mptimer);
  137. busdev = sysbus_from_qdev(s->mptimer);
  138. /* Memory map (addresses are offsets from PERIPHBASE):
  139. * 0x0000-0x00ff -- Snoop Control Unit
  140. * 0x0100-0x01ff -- GIC CPU interface
  141. * 0x0200-0x02ff -- Global Timer
  142. * 0x0300-0x05ff -- nothing
  143. * 0x0600-0x06ff -- private timers and watchdogs
  144. * 0x0700-0x0fff -- nothing
  145. * 0x1000-0x1fff -- GIC Distributor
  146. *
  147. * We should implement the global timer but don't currently do so.
  148. */
  149. memory_region_init(&s->container, "a9mp-priv-container", 0x2000);
  150. memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100);
  151. memory_region_add_subregion(&s->container, 0, &s->scu_iomem);
  152. /* GIC CPU interface */
  153. memory_region_add_subregion(&s->container, 0x100,
  154. sysbus_mmio_get_region(gicbusdev, 1));
  155. /* Note that the A9 exposes only the "timer/watchdog for this core"
  156. * memory region, not the "timer/watchdog for core X" ones 11MPcore has.
  157. */
  158. memory_region_add_subregion(&s->container, 0x600,
  159. sysbus_mmio_get_region(busdev, 0));
  160. memory_region_add_subregion(&s->container, 0x620,
  161. sysbus_mmio_get_region(busdev, 1));
  162. memory_region_add_subregion(&s->container, 0x1000,
  163. sysbus_mmio_get_region(gicbusdev, 0));
  164. sysbus_init_mmio(dev, &s->container);
  165. /* Wire up the interrupt from each watchdog and timer.
  166. * For each core the timer is PPI 29 and the watchdog PPI 30.
  167. */
  168. for (i = 0; i < s->num_cpu; i++) {
  169. int ppibase = (s->num_irq - 32) + i * 32;
  170. sysbus_connect_irq(busdev, i * 2,
  171. qdev_get_gpio_in(s->gic, ppibase + 29));
  172. sysbus_connect_irq(busdev, i * 2 + 1,
  173. qdev_get_gpio_in(s->gic, ppibase + 30));
  174. }
  175. return 0;
  176. }
  177. static const VMStateDescription vmstate_a9mp_priv = {
  178. .name = "a9mpcore_priv",
  179. .version_id = 2,
  180. .minimum_version_id = 1,
  181. .fields = (VMStateField[]) {
  182. VMSTATE_UINT32(scu_control, a9mp_priv_state),
  183. VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8),
  184. VMSTATE_UINT32_V(scu_status, a9mp_priv_state, 2),
  185. VMSTATE_END_OF_LIST()
  186. }
  187. };
  188. static Property a9mp_priv_properties[] = {
  189. DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
  190. /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
  191. * IRQ lines (with another 32 internal). We default to 64+32, which
  192. * is the number provided by the Cortex-A9MP test chip in the
  193. * Realview PBX-A9 and Versatile Express A9 development boards.
  194. * Other boards may differ and should set this property appropriately.
  195. */
  196. DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
  197. DEFINE_PROP_END_OF_LIST(),
  198. };
  199. static void a9mp_priv_class_init(ObjectClass *klass, void *data)
  200. {
  201. DeviceClass *dc = DEVICE_CLASS(klass);
  202. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  203. k->init = a9mp_priv_init;
  204. dc->props = a9mp_priv_properties;
  205. dc->vmsd = &vmstate_a9mp_priv;
  206. dc->reset = a9mp_priv_reset;
  207. }
  208. static TypeInfo a9mp_priv_info = {
  209. .name = "a9mpcore_priv",
  210. .parent = TYPE_SYS_BUS_DEVICE,
  211. .instance_size = sizeof(a9mp_priv_state),
  212. .class_init = a9mp_priv_class_init,
  213. };
  214. static void a9mp_register_types(void)
  215. {
  216. type_register_static(&a9mp_priv_info);
  217. }
  218. type_init(a9mp_register_types)