a9scu.c 4.1 KB

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