arm_l2x0.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * ARM dummy L210, L220, PL310 cache controller.
  3. *
  4. * Copyright (c) 2010-2012 Calxeda
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2 or any later version, as published by the Free Software
  9. * Foundation.
  10. *
  11. * This program is distributed in the hope it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "qemu/osdep.h"
  21. #include "hw/qdev-properties.h"
  22. #include "hw/sysbus.h"
  23. #include "migration/vmstate.h"
  24. #include "qemu/log.h"
  25. #include "qemu/module.h"
  26. /* L2C-310 r3p2 */
  27. #define CACHE_ID 0x410000c8
  28. #define TYPE_ARM_L2X0 "l2x0"
  29. #define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0)
  30. typedef struct L2x0State {
  31. SysBusDevice parent_obj;
  32. MemoryRegion iomem;
  33. uint32_t cache_type;
  34. uint32_t ctrl;
  35. uint32_t aux_ctrl;
  36. uint32_t data_ctrl;
  37. uint32_t tag_ctrl;
  38. uint32_t filter_start;
  39. uint32_t filter_end;
  40. } L2x0State;
  41. static const VMStateDescription vmstate_l2x0 = {
  42. .name = "l2x0",
  43. .version_id = 1,
  44. .minimum_version_id = 1,
  45. .fields = (VMStateField[]) {
  46. VMSTATE_UINT32(ctrl, L2x0State),
  47. VMSTATE_UINT32(aux_ctrl, L2x0State),
  48. VMSTATE_UINT32(data_ctrl, L2x0State),
  49. VMSTATE_UINT32(tag_ctrl, L2x0State),
  50. VMSTATE_UINT32(filter_start, L2x0State),
  51. VMSTATE_UINT32(filter_end, L2x0State),
  52. VMSTATE_END_OF_LIST()
  53. }
  54. };
  55. static uint64_t l2x0_priv_read(void *opaque, hwaddr offset,
  56. unsigned size)
  57. {
  58. uint32_t cache_data;
  59. L2x0State *s = (L2x0State *)opaque;
  60. offset &= 0xfff;
  61. if (offset >= 0x730 && offset < 0x800) {
  62. return 0; /* cache ops complete */
  63. }
  64. switch (offset) {
  65. case 0:
  66. return CACHE_ID;
  67. case 0x4:
  68. /* aux_ctrl values affect cache_type values */
  69. cache_data = (s->aux_ctrl & (7 << 17)) >> 15;
  70. cache_data |= (s->aux_ctrl & (1 << 16)) >> 16;
  71. return s->cache_type |= (cache_data << 18) | (cache_data << 6);
  72. case 0x100:
  73. return s->ctrl;
  74. case 0x104:
  75. return s->aux_ctrl;
  76. case 0x108:
  77. return s->tag_ctrl;
  78. case 0x10C:
  79. return s->data_ctrl;
  80. case 0xC00:
  81. return s->filter_start;
  82. case 0xC04:
  83. return s->filter_end;
  84. case 0xF40:
  85. return 0;
  86. case 0xF60:
  87. return 0;
  88. case 0xF80:
  89. return 0;
  90. default:
  91. qemu_log_mask(LOG_GUEST_ERROR,
  92. "l2x0_priv_read: Bad offset %x\n", (int)offset);
  93. break;
  94. }
  95. return 0;
  96. }
  97. static void l2x0_priv_write(void *opaque, hwaddr offset,
  98. uint64_t value, unsigned size)
  99. {
  100. L2x0State *s = (L2x0State *)opaque;
  101. offset &= 0xfff;
  102. if (offset >= 0x730 && offset < 0x800) {
  103. /* ignore */
  104. return;
  105. }
  106. switch (offset) {
  107. case 0x100:
  108. s->ctrl = value & 1;
  109. break;
  110. case 0x104:
  111. s->aux_ctrl = value;
  112. break;
  113. case 0x108:
  114. s->tag_ctrl = value;
  115. break;
  116. case 0x10C:
  117. s->data_ctrl = value;
  118. break;
  119. case 0xC00:
  120. s->filter_start = value;
  121. break;
  122. case 0xC04:
  123. s->filter_end = value;
  124. break;
  125. case 0xF40:
  126. return;
  127. case 0xF60:
  128. return;
  129. case 0xF80:
  130. return;
  131. default:
  132. qemu_log_mask(LOG_GUEST_ERROR,
  133. "l2x0_priv_write: Bad offset %x\n", (int)offset);
  134. break;
  135. }
  136. }
  137. static void l2x0_priv_reset(DeviceState *dev)
  138. {
  139. L2x0State *s = ARM_L2X0(dev);
  140. s->ctrl = 0;
  141. s->aux_ctrl = 0x02020000;
  142. s->tag_ctrl = 0;
  143. s->data_ctrl = 0;
  144. s->filter_start = 0;
  145. s->filter_end = 0;
  146. }
  147. static const MemoryRegionOps l2x0_mem_ops = {
  148. .read = l2x0_priv_read,
  149. .write = l2x0_priv_write,
  150. .endianness = DEVICE_NATIVE_ENDIAN,
  151. };
  152. static void l2x0_priv_init(Object *obj)
  153. {
  154. L2x0State *s = ARM_L2X0(obj);
  155. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  156. memory_region_init_io(&s->iomem, obj, &l2x0_mem_ops, s,
  157. "l2x0_cc", 0x1000);
  158. sysbus_init_mmio(dev, &s->iomem);
  159. }
  160. static Property l2x0_properties[] = {
  161. DEFINE_PROP_UINT32("cache-type", L2x0State, cache_type, 0x1c100100),
  162. DEFINE_PROP_END_OF_LIST(),
  163. };
  164. static void l2x0_class_init(ObjectClass *klass, void *data)
  165. {
  166. DeviceClass *dc = DEVICE_CLASS(klass);
  167. dc->vmsd = &vmstate_l2x0;
  168. dc->props = l2x0_properties;
  169. dc->reset = l2x0_priv_reset;
  170. }
  171. static const TypeInfo l2x0_info = {
  172. .name = TYPE_ARM_L2X0,
  173. .parent = TYPE_SYS_BUS_DEVICE,
  174. .instance_size = sizeof(L2x0State),
  175. .instance_init = l2x0_priv_init,
  176. .class_init = l2x0_class_init,
  177. };
  178. static void l2x0_register_types(void)
  179. {
  180. type_register_static(&l2x0_info);
  181. }
  182. type_init(l2x0_register_types)