arm11mpcore.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * ARM11MPCore internal peripheral emulation.
  3. *
  4. * Copyright (c) 2006-2007 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licensed under the GPL.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "qapi/error.h"
  11. #include "qemu/module.h"
  12. #include "hw/cpu/arm11mpcore.h"
  13. #include "hw/intc/realview_gic.h"
  14. #include "hw/irq.h"
  15. #include "hw/qdev-properties.h"
  16. #define ARM11MPCORE_NUM_GIC_PRIORITY_BITS 4
  17. static void mpcore_priv_set_irq(void *opaque, int irq, int level)
  18. {
  19. ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
  20. qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
  21. }
  22. static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
  23. {
  24. int i;
  25. SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
  26. DeviceState *gicdev = DEVICE(&s->gic);
  27. SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic);
  28. SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
  29. SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer);
  30. memory_region_add_subregion(&s->container, 0,
  31. sysbus_mmio_get_region(scubusdev, 0));
  32. /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
  33. * at 0x200, 0x300...
  34. */
  35. for (i = 0; i < (s->num_cpu + 1); i++) {
  36. hwaddr offset = 0x100 + (i * 0x100);
  37. memory_region_add_subregion(&s->container, offset,
  38. sysbus_mmio_get_region(gicbusdev, i + 1));
  39. }
  40. /* Add the regions for timer and watchdog for "current CPU" and
  41. * for each specific CPU.
  42. */
  43. for (i = 0; i < (s->num_cpu + 1); i++) {
  44. /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
  45. hwaddr offset = 0x600 + i * 0x100;
  46. memory_region_add_subregion(&s->container, offset,
  47. sysbus_mmio_get_region(timerbusdev, i));
  48. memory_region_add_subregion(&s->container, offset + 0x20,
  49. sysbus_mmio_get_region(wdtbusdev, i));
  50. }
  51. memory_region_add_subregion(&s->container, 0x1000,
  52. sysbus_mmio_get_region(gicbusdev, 0));
  53. /* Wire up the interrupt from each watchdog and timer.
  54. * For each core the timer is PPI 29 and the watchdog PPI 30.
  55. */
  56. for (i = 0; i < s->num_cpu; i++) {
  57. int ppibase = (s->num_irq - 32) + i * 32;
  58. sysbus_connect_irq(timerbusdev, i,
  59. qdev_get_gpio_in(gicdev, ppibase + 29));
  60. sysbus_connect_irq(wdtbusdev, i,
  61. qdev_get_gpio_in(gicdev, ppibase + 30));
  62. }
  63. }
  64. static void mpcore_priv_realize(DeviceState *dev, Error **errp)
  65. {
  66. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  67. ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
  68. DeviceState *scudev = DEVICE(&s->scu);
  69. DeviceState *gicdev = DEVICE(&s->gic);
  70. DeviceState *mptimerdev = DEVICE(&s->mptimer);
  71. DeviceState *wdtimerdev = DEVICE(&s->wdtimer);
  72. qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
  73. if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
  74. return;
  75. }
  76. qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
  77. qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
  78. qdev_prop_set_uint32(gicdev, "num-priority-bits",
  79. ARM11MPCORE_NUM_GIC_PRIORITY_BITS);
  80. if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) {
  81. return;
  82. }
  83. /* Pass through outbound IRQ lines from the GIC */
  84. sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->gic));
  85. /* Pass through inbound GPIO lines to the GIC */
  86. qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32);
  87. qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
  88. if (!sysbus_realize(SYS_BUS_DEVICE(&s->mptimer), errp)) {
  89. return;
  90. }
  91. qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu);
  92. if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdtimer), errp)) {
  93. return;
  94. }
  95. mpcore_priv_map_setup(s);
  96. }
  97. static void mpcore_priv_initfn(Object *obj)
  98. {
  99. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  100. ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(obj);
  101. memory_region_init(&s->container, OBJECT(s),
  102. "mpcore-priv-container", 0x2000);
  103. sysbus_init_mmio(sbd, &s->container);
  104. object_initialize_child(obj, "scu", &s->scu, TYPE_ARM11_SCU);
  105. object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC);
  106. /* Request the legacy 11MPCore GIC behaviour: */
  107. qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 0);
  108. object_initialize_child(obj, "mptimer", &s->mptimer, TYPE_ARM_MPTIMER);
  109. object_initialize_child(obj, "wdtimer", &s->wdtimer, TYPE_ARM_MPTIMER);
  110. }
  111. static const Property mpcore_priv_properties[] = {
  112. DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1),
  113. /* The ARM11 MPCORE TRM says the on-chip controller may have
  114. * anything from 0 to 224 external interrupt IRQ lines (with another
  115. * 32 internal). We default to 32+32, which is the number provided by
  116. * the ARM11 MPCore test chip in the Realview Versatile Express
  117. * coretile. Other boards may differ and should set this property
  118. * appropriately. Some Linux kernels may not boot if the hardware
  119. * has more IRQ lines than the kernel expects.
  120. */
  121. DEFINE_PROP_UINT32("num-irq", ARM11MPCorePriveState, num_irq, 64),
  122. };
  123. static void mpcore_priv_class_init(ObjectClass *klass, void *data)
  124. {
  125. DeviceClass *dc = DEVICE_CLASS(klass);
  126. dc->realize = mpcore_priv_realize;
  127. device_class_set_props(dc, mpcore_priv_properties);
  128. }
  129. static const TypeInfo arm11mp_types[] = {
  130. {
  131. .name = TYPE_ARM11MPCORE_PRIV,
  132. .parent = TYPE_SYS_BUS_DEVICE,
  133. .instance_size = sizeof(ARM11MPCorePriveState),
  134. .instance_init = mpcore_priv_initfn,
  135. .class_init = mpcore_priv_class_init,
  136. },
  137. };
  138. DEFINE_TYPES(arm11mp_types)