a9scu.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
  3. *
  4. * Copyright (c) 2009 CodeSourcery.
  5. * Copyright (c) 2011 Linaro Limited.
  6. * Written by Paul Brook, Peter Maydell.
  7. *
  8. * This code is licensed under the GPL.
  9. */
  10. #include "qemu/osdep.h"
  11. #include "hw/misc/a9scu.h"
  12. #include "hw/qdev-properties.h"
  13. #include "migration/vmstate.h"
  14. #include "qemu/module.h"
  15. static uint64_t a9_scu_read(void *opaque, hwaddr offset,
  16. unsigned size)
  17. {
  18. A9SCUState *s = (A9SCUState *)opaque;
  19. switch (offset) {
  20. case 0x00: /* Control */
  21. return s->control;
  22. case 0x04: /* Configuration */
  23. return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
  24. case 0x08: /* CPU Power Status */
  25. return s->status;
  26. case 0x09: /* CPU status. */
  27. return s->status >> 8;
  28. case 0x0a: /* CPU status. */
  29. return s->status >> 16;
  30. case 0x0b: /* CPU status. */
  31. return s->status >> 24;
  32. case 0x0c: /* Invalidate All Registers In Secure State */
  33. return 0;
  34. case 0x40: /* Filtering Start Address Register */
  35. case 0x44: /* Filtering End Address Register */
  36. /* RAZ/WI, like an implementation with only one AXI master */
  37. return 0;
  38. case 0x50: /* SCU Access Control Register */
  39. case 0x54: /* SCU Non-secure Access Control Register */
  40. /* unimplemented, fall through */
  41. default:
  42. return 0;
  43. }
  44. }
  45. static void a9_scu_write(void *opaque, hwaddr offset,
  46. uint64_t value, unsigned size)
  47. {
  48. A9SCUState *s = (A9SCUState *)opaque;
  49. uint32_t mask;
  50. uint32_t shift;
  51. switch (size) {
  52. case 1:
  53. mask = 0xff;
  54. break;
  55. case 2:
  56. mask = 0xffff;
  57. break;
  58. case 4:
  59. mask = 0xffffffff;
  60. break;
  61. default:
  62. fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
  63. size, (unsigned)offset);
  64. return;
  65. }
  66. switch (offset) {
  67. case 0x00: /* Control */
  68. s->control = value & 1;
  69. break;
  70. case 0x4: /* Configuration: RO */
  71. break;
  72. case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
  73. shift = (offset - 0x8) * 8;
  74. s->status &= ~(mask << shift);
  75. s->status |= ((value & mask) << shift);
  76. break;
  77. case 0x0c: /* Invalidate All Registers In Secure State */
  78. /* no-op as we do not implement caches */
  79. break;
  80. case 0x40: /* Filtering Start Address Register */
  81. case 0x44: /* Filtering End Address Register */
  82. /* RAZ/WI, like an implementation with only one AXI master */
  83. break;
  84. case 0x50: /* SCU Access Control Register */
  85. case 0x54: /* SCU Non-secure Access Control Register */
  86. /* unimplemented, fall through */
  87. default:
  88. break;
  89. }
  90. }
  91. static const MemoryRegionOps a9_scu_ops = {
  92. .read = a9_scu_read,
  93. .write = a9_scu_write,
  94. .endianness = DEVICE_NATIVE_ENDIAN,
  95. };
  96. static void a9_scu_reset(DeviceState *dev)
  97. {
  98. A9SCUState *s = A9_SCU(dev);
  99. s->control = 0;
  100. }
  101. static void a9_scu_init(Object *obj)
  102. {
  103. A9SCUState *s = A9_SCU(obj);
  104. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  105. memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
  106. "a9-scu", 0x100);
  107. sysbus_init_mmio(sbd, &s->iomem);
  108. }
  109. static const VMStateDescription vmstate_a9_scu = {
  110. .name = "a9-scu",
  111. .version_id = 1,
  112. .minimum_version_id = 1,
  113. .fields = (VMStateField[]) {
  114. VMSTATE_UINT32(control, A9SCUState),
  115. VMSTATE_UINT32(status, A9SCUState),
  116. VMSTATE_END_OF_LIST()
  117. }
  118. };
  119. static Property a9_scu_properties[] = {
  120. DEFINE_PROP_UINT32("num-cpu", A9SCUState, num_cpu, 1),
  121. DEFINE_PROP_END_OF_LIST(),
  122. };
  123. static void a9_scu_class_init(ObjectClass *klass, void *data)
  124. {
  125. DeviceClass *dc = DEVICE_CLASS(klass);
  126. device_class_set_props(dc, a9_scu_properties);
  127. dc->vmsd = &vmstate_a9_scu;
  128. dc->reset = a9_scu_reset;
  129. }
  130. static const TypeInfo a9_scu_info = {
  131. .name = TYPE_A9_SCU,
  132. .parent = TYPE_SYS_BUS_DEVICE,
  133. .instance_size = sizeof(A9SCUState),
  134. .instance_init = a9_scu_init,
  135. .class_init = a9_scu_class_init,
  136. };
  137. static void a9mp_register_types(void)
  138. {
  139. type_register_static(&a9_scu_info);
  140. }
  141. type_init(a9mp_register_types)