realview_mpcore.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
  18. #define REALVIEW_MPCORE_RIRQ(obj) \
  19. OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_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. typedef struct {
  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. } mpcore_rirq_state;
  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. Error *err = NULL;
  60. int n;
  61. int i;
  62. qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
  63. object_property_set_bool(OBJECT(&s->priv), true, "realized", &err);
  64. if (err != NULL) {
  65. error_propagate(errp, err);
  66. return;
  67. }
  68. sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv));
  69. for (i = 0; i < 32; i++) {
  70. s->cpuic[i] = qdev_get_gpio_in(priv, i);
  71. }
  72. /* ??? IRQ routing is hardcoded to "normal" mode. */
  73. for (n = 0; n < 4; n++) {
  74. object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err);
  75. if (err != NULL) {
  76. error_propagate(errp, err);
  77. return;
  78. }
  79. gic = DEVICE(&s->gic[n]);
  80. gicbusdev = SYS_BUS_DEVICE(&s->gic[n]);
  81. sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000);
  82. sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]);
  83. for (i = 0; i < 64; i++) {
  84. s->rvic[n][i] = qdev_get_gpio_in(gic, i);
  85. }
  86. }
  87. qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
  88. }
  89. static void mpcore_rirq_init(Object *obj)
  90. {
  91. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  92. mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj);
  93. SysBusDevice *privbusdev;
  94. int i;
  95. sysbus_init_child_obj(obj, "a11priv", &s->priv, sizeof(s->priv),
  96. TYPE_ARM11MPCORE_PRIV);
  97. privbusdev = SYS_BUS_DEVICE(&s->priv);
  98. sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
  99. for (i = 0; i < 4; i++) {
  100. sysbus_init_child_obj(obj, "gic[*]", &s->gic[i], sizeof(s->gic[i]),
  101. TYPE_REALVIEW_GIC);
  102. }
  103. }
  104. static Property mpcore_rirq_properties[] = {
  105. DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
  106. DEFINE_PROP_END_OF_LIST(),
  107. };
  108. static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
  109. {
  110. DeviceClass *dc = DEVICE_CLASS(klass);
  111. dc->realize = realview_mpcore_realize;
  112. dc->props = mpcore_rirq_properties;
  113. }
  114. static const TypeInfo mpcore_rirq_info = {
  115. .name = TYPE_REALVIEW_MPCORE_RIRQ,
  116. .parent = TYPE_SYS_BUS_DEVICE,
  117. .instance_size = sizeof(mpcore_rirq_state),
  118. .instance_init = mpcore_rirq_init,
  119. .class_init = mpcore_rirq_class_init,
  120. };
  121. static void realview_mpcore_register_types(void)
  122. {
  123. type_register_static(&mpcore_rirq_info);
  124. }
  125. type_init(realview_mpcore_register_types)