realview_mpcore.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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 "qom/object.h"
  17. #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
  18. OBJECT_DECLARE_SIMPLE_TYPE(mpcore_rirq_state, REALVIEW_MPCORE_RIRQ)
  19. /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
  20. controllers. The output of these, plus some of the raw input lines
  21. are fed into a single SMP-aware interrupt controller on the CPU. */
  22. struct mpcore_rirq_state {
  23. SysBusDevice parent_obj;
  24. qemu_irq cpuic[32];
  25. qemu_irq rvic[4][64];
  26. uint32_t num_cpu;
  27. ARM11MPCorePriveState priv;
  28. RealViewGICState gic[4];
  29. };
  30. /* Map baseboard IRQs onto CPU IRQ lines. */
  31. static const int mpcore_irq_map[32] = {
  32. -1, -1, -1, -1, 1, 2, -1, -1,
  33. -1, -1, 6, -1, 4, 5, -1, -1,
  34. -1, 14, 15, 0, 7, 8, -1, -1,
  35. -1, -1, -1, -1, 9, 3, -1, -1,
  36. };
  37. static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
  38. {
  39. mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
  40. int i;
  41. for (i = 0; i < 4; i++) {
  42. qemu_set_irq(s->rvic[i][irq], level);
  43. }
  44. if (irq < 32) {
  45. irq = mpcore_irq_map[irq];
  46. if (irq >= 0) {
  47. qemu_set_irq(s->cpuic[irq], level);
  48. }
  49. }
  50. }
  51. static void realview_mpcore_realize(DeviceState *dev, Error **errp)
  52. {
  53. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  54. mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
  55. DeviceState *priv = DEVICE(&s->priv);
  56. DeviceState *gic;
  57. SysBusDevice *gicbusdev;
  58. int n;
  59. int i;
  60. if (!sysbus_realize(SYS_BUS_DEVICE(&s->priv), errp)) {
  61. return;
  62. }
  63. sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv));
  64. for (i = 0; i < 32; i++) {
  65. s->cpuic[i] = qdev_get_gpio_in(priv, i);
  66. }
  67. /* ??? IRQ routing is hardcoded to "normal" mode. */
  68. for (n = 0; n < 4; n++) {
  69. if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic[n]), errp)) {
  70. return;
  71. }
  72. gic = DEVICE(&s->gic[n]);
  73. gicbusdev = SYS_BUS_DEVICE(&s->gic[n]);
  74. sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000);
  75. sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]);
  76. for (i = 0; i < 64; i++) {
  77. s->rvic[n][i] = qdev_get_gpio_in(gic, i);
  78. }
  79. }
  80. qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
  81. }
  82. static void mpcore_rirq_init(Object *obj)
  83. {
  84. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  85. mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj);
  86. SysBusDevice *privbusdev;
  87. int i;
  88. object_initialize_child(obj, "a11priv", &s->priv, TYPE_ARM11MPCORE_PRIV);
  89. object_property_add_alias(obj, "num-cpu", OBJECT(&s->priv), "num-cpu");
  90. privbusdev = SYS_BUS_DEVICE(&s->priv);
  91. sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
  92. for (i = 0; i < 4; i++) {
  93. object_initialize_child(obj, "gic[*]", &s->gic[i], TYPE_REALVIEW_GIC);
  94. }
  95. }
  96. static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
  97. {
  98. DeviceClass *dc = DEVICE_CLASS(klass);
  99. dc->realize = realview_mpcore_realize;
  100. }
  101. static const TypeInfo realview_mpcore_types[] = {
  102. {
  103. .name = TYPE_REALVIEW_MPCORE_RIRQ,
  104. .parent = TYPE_SYS_BUS_DEVICE,
  105. .instance_size = sizeof(mpcore_rirq_state),
  106. .instance_init = mpcore_rirq_init,
  107. .class_init = mpcore_rirq_class_init,
  108. },
  109. };
  110. DEFINE_TYPES(realview_mpcore_types)