realview_mpcore.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * RealView ARM11MPCore internal peripheral emulation
  3. *
  4. * Copyright (c) 2006-2007 CodeSourcery.
  5. * Copyright (c) 2013 SUSE LINUX Products GmbH
  6. * Written by Paul Brook and Andreas Färber
  7. *
  8. * This code is licensed under the GPL.
  9. */
  10. #include "qemu/osdep.h"
  11. #include "qapi/error.h"
  12. #include "qemu/module.h"
  13. #include "hw/cpu/arm11mpcore.h"
  14. #include "hw/intc/realview_gic.h"
  15. #include "hw/irq.h"
  16. #include "hw/qdev-properties.h"
  17. #include "qom/object.h"
  18. #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
  19. OBJECT_DECLARE_SIMPLE_TYPE(mpcore_rirq_state, REALVIEW_MPCORE_RIRQ)
  20. /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
  21. controllers. The output of these, plus some of the raw input lines
  22. are fed into a single SMP-aware interrupt controller on the CPU. */
  23. struct mpcore_rirq_state {
  24. SysBusDevice parent_obj;
  25. qemu_irq cpuic[32];
  26. qemu_irq rvic[4][64];
  27. uint32_t num_cpu;
  28. ARM11MPCorePriveState priv;
  29. RealViewGICState gic[4];
  30. };
  31. /* Map baseboard IRQs onto CPU IRQ lines. */
  32. static const int mpcore_irq_map[32] = {
  33. -1, -1, -1, -1, 1, 2, -1, -1,
  34. -1, -1, 6, -1, 4, 5, -1, -1,
  35. -1, 14, 15, 0, 7, 8, -1, -1,
  36. -1, -1, -1, -1, 9, 3, -1, -1,
  37. };
  38. static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
  39. {
  40. mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
  41. int i;
  42. for (i = 0; i < 4; i++) {
  43. qemu_set_irq(s->rvic[i][irq], level);
  44. }
  45. if (irq < 32) {
  46. irq = mpcore_irq_map[irq];
  47. if (irq >= 0) {
  48. qemu_set_irq(s->cpuic[irq], level);
  49. }
  50. }
  51. }
  52. static void realview_mpcore_realize(DeviceState *dev, Error **errp)
  53. {
  54. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  55. mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
  56. DeviceState *priv = DEVICE(&s->priv);
  57. DeviceState *gic;
  58. SysBusDevice *gicbusdev;
  59. int n;
  60. int i;
  61. qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
  62. if (!sysbus_realize(SYS_BUS_DEVICE(&s->priv), errp)) {
  63. return;
  64. }
  65. sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv));
  66. for (i = 0; i < 32; i++) {
  67. s->cpuic[i] = qdev_get_gpio_in(priv, i);
  68. }
  69. /* ??? IRQ routing is hardcoded to "normal" mode. */
  70. for (n = 0; n < 4; n++) {
  71. if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic[n]), errp)) {
  72. return;
  73. }
  74. gic = DEVICE(&s->gic[n]);
  75. gicbusdev = SYS_BUS_DEVICE(&s->gic[n]);
  76. sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000);
  77. sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]);
  78. for (i = 0; i < 64; i++) {
  79. s->rvic[n][i] = qdev_get_gpio_in(gic, i);
  80. }
  81. }
  82. qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
  83. }
  84. static void mpcore_rirq_init(Object *obj)
  85. {
  86. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  87. mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj);
  88. SysBusDevice *privbusdev;
  89. int i;
  90. object_initialize_child(obj, "a11priv", &s->priv, TYPE_ARM11MPCORE_PRIV);
  91. privbusdev = SYS_BUS_DEVICE(&s->priv);
  92. sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
  93. for (i = 0; i < 4; i++) {
  94. object_initialize_child(obj, "gic[*]", &s->gic[i], TYPE_REALVIEW_GIC);
  95. }
  96. }
  97. static Property mpcore_rirq_properties[] = {
  98. DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
  99. DEFINE_PROP_END_OF_LIST(),
  100. };
  101. static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
  102. {
  103. DeviceClass *dc = DEVICE_CLASS(klass);
  104. dc->realize = realview_mpcore_realize;
  105. device_class_set_props(dc, mpcore_rirq_properties);
  106. }
  107. static const TypeInfo mpcore_rirq_info = {
  108. .name = TYPE_REALVIEW_MPCORE_RIRQ,
  109. .parent = TYPE_SYS_BUS_DEVICE,
  110. .instance_size = sizeof(mpcore_rirq_state),
  111. .instance_init = mpcore_rirq_init,
  112. .class_init = mpcore_rirq_class_init,
  113. };
  114. static void realview_mpcore_register_types(void)
  115. {
  116. type_register_static(&mpcore_rirq_info);
  117. }
  118. type_init(realview_mpcore_register_types)