or-irq.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * QEMU IRQ/GPIO common code.
  3. *
  4. * Copyright (c) 2016 Alistair Francis <alistair@alistair23.me>.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "hw/irq.h"
  26. #include "hw/or-irq.h"
  27. #include "hw/qdev-properties.h"
  28. #include "migration/vmstate.h"
  29. #include "qemu/module.h"
  30. static void or_irq_handler(void *opaque, int n, int level)
  31. {
  32. qemu_or_irq *s = OR_IRQ(opaque);
  33. int or_level = 0;
  34. int i;
  35. s->levels[n] = level;
  36. for (i = 0; i < s->num_lines; i++) {
  37. or_level |= s->levels[i];
  38. }
  39. qemu_set_irq(s->out_irq, or_level);
  40. }
  41. static void or_irq_reset(DeviceState *dev)
  42. {
  43. qemu_or_irq *s = OR_IRQ(dev);
  44. int i;
  45. for (i = 0; i < MAX_OR_LINES; i++) {
  46. s->levels[i] = false;
  47. }
  48. }
  49. static void or_irq_realize(DeviceState *dev, Error **errp)
  50. {
  51. qemu_or_irq *s = OR_IRQ(dev);
  52. assert(s->num_lines <= MAX_OR_LINES);
  53. qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
  54. }
  55. static void or_irq_init(Object *obj)
  56. {
  57. qemu_or_irq *s = OR_IRQ(obj);
  58. qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1);
  59. }
  60. /* The original version of this device had a fixed 16 entries in its
  61. * VMState array; devices with more inputs than this need to
  62. * migrate the extra lines via a subsection.
  63. * The subsection migrates as much of the levels[] array as is needed
  64. * (including repeating the first 16 elements), to avoid the awkwardness
  65. * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16.
  66. */
  67. #define OLD_MAX_OR_LINES 16
  68. #if MAX_OR_LINES < OLD_MAX_OR_LINES
  69. #error MAX_OR_LINES must be at least 16 for migration compatibility
  70. #endif
  71. static bool vmstate_extras_needed(void *opaque)
  72. {
  73. qemu_or_irq *s = OR_IRQ(opaque);
  74. return s->num_lines >= OLD_MAX_OR_LINES;
  75. }
  76. static const VMStateDescription vmstate_or_irq_extras = {
  77. .name = "or-irq-extras",
  78. .version_id = 1,
  79. .minimum_version_id = 1,
  80. .needed = vmstate_extras_needed,
  81. .fields = (VMStateField[]) {
  82. VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0,
  83. vmstate_info_bool, bool),
  84. VMSTATE_END_OF_LIST(),
  85. },
  86. };
  87. static const VMStateDescription vmstate_or_irq = {
  88. .name = TYPE_OR_IRQ,
  89. .version_id = 1,
  90. .minimum_version_id = 1,
  91. .fields = (VMStateField[]) {
  92. VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES),
  93. VMSTATE_END_OF_LIST(),
  94. },
  95. .subsections = (const VMStateDescription*[]) {
  96. &vmstate_or_irq_extras,
  97. NULL
  98. },
  99. };
  100. static Property or_irq_properties[] = {
  101. DEFINE_PROP_UINT16("num-lines", qemu_or_irq, num_lines, 1),
  102. DEFINE_PROP_END_OF_LIST(),
  103. };
  104. static void or_irq_class_init(ObjectClass *klass, void *data)
  105. {
  106. DeviceClass *dc = DEVICE_CLASS(klass);
  107. dc->reset = or_irq_reset;
  108. device_class_set_props(dc, or_irq_properties);
  109. dc->realize = or_irq_realize;
  110. dc->vmsd = &vmstate_or_irq;
  111. /* Reason: Needs to be wired up to work, e.g. see stm32f205_soc.c */
  112. dc->user_creatable = false;
  113. }
  114. static const TypeInfo or_irq_type_info = {
  115. .name = TYPE_OR_IRQ,
  116. .parent = TYPE_DEVICE,
  117. .instance_size = sizeof(qemu_or_irq),
  118. .instance_init = or_irq_init,
  119. .class_init = or_irq_class_init,
  120. };
  121. static void or_irq_register_types(void)
  122. {
  123. type_register_static(&or_irq_type_info);
  124. }
  125. type_init(or_irq_register_types)