arm_l2x0.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 "hw/sysbus.h"
  21. /* L2C-310 r3p2 */
  22. #define CACHE_ID 0x410000c8
  23. #define TYPE_ARM_L2X0 "l2x0"
  24. #define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0)
  25. typedef struct L2x0State {
  26. SysBusDevice parent_obj;
  27. MemoryRegion iomem;
  28. uint32_t cache_type;
  29. uint32_t ctrl;
  30. uint32_t aux_ctrl;
  31. uint32_t data_ctrl;
  32. uint32_t tag_ctrl;
  33. uint32_t filter_start;
  34. uint32_t filter_end;
  35. } L2x0State;
  36. static const VMStateDescription vmstate_l2x0 = {
  37. .name = "l2x0",
  38. .version_id = 1,
  39. .minimum_version_id = 1,
  40. .fields = (VMStateField[]) {
  41. VMSTATE_UINT32(ctrl, L2x0State),
  42. VMSTATE_UINT32(aux_ctrl, L2x0State),
  43. VMSTATE_UINT32(data_ctrl, L2x0State),
  44. VMSTATE_UINT32(tag_ctrl, L2x0State),
  45. VMSTATE_UINT32(filter_start, L2x0State),
  46. VMSTATE_UINT32(filter_end, L2x0State),
  47. VMSTATE_END_OF_LIST()
  48. }
  49. };
  50. static uint64_t l2x0_priv_read(void *opaque, hwaddr offset,
  51. unsigned size)
  52. {
  53. uint32_t cache_data;
  54. L2x0State *s = (L2x0State *)opaque;
  55. offset &= 0xfff;
  56. if (offset >= 0x730 && offset < 0x800) {
  57. return 0; /* cache ops complete */
  58. }
  59. switch (offset) {
  60. case 0:
  61. return CACHE_ID;
  62. case 0x4:
  63. /* aux_ctrl values affect cache_type values */
  64. cache_data = (s->aux_ctrl & (7 << 17)) >> 15;
  65. cache_data |= (s->aux_ctrl & (1 << 16)) >> 16;
  66. return s->cache_type |= (cache_data << 18) | (cache_data << 6);
  67. case 0x100:
  68. return s->ctrl;
  69. case 0x104:
  70. return s->aux_ctrl;
  71. case 0x108:
  72. return s->tag_ctrl;
  73. case 0x10C:
  74. return s->data_ctrl;
  75. case 0xC00:
  76. return s->filter_start;
  77. case 0xC04:
  78. return s->filter_end;
  79. case 0xF40:
  80. return 0;
  81. case 0xF60:
  82. return 0;
  83. case 0xF80:
  84. return 0;
  85. default:
  86. qemu_log_mask(LOG_GUEST_ERROR,
  87. "l2x0_priv_read: Bad offset %x\n", (int)offset);
  88. break;
  89. }
  90. return 0;
  91. }
  92. static void l2x0_priv_write(void *opaque, hwaddr offset,
  93. uint64_t value, unsigned size)
  94. {
  95. L2x0State *s = (L2x0State *)opaque;
  96. offset &= 0xfff;
  97. if (offset >= 0x730 && offset < 0x800) {
  98. /* ignore */
  99. return;
  100. }
  101. switch (offset) {
  102. case 0x100:
  103. s->ctrl = value & 1;
  104. break;
  105. case 0x104:
  106. s->aux_ctrl = value;
  107. break;
  108. case 0x108:
  109. s->tag_ctrl = value;
  110. break;
  111. case 0x10C:
  112. s->data_ctrl = value;
  113. break;
  114. case 0xC00:
  115. s->filter_start = value;
  116. break;
  117. case 0xC04:
  118. s->filter_end = value;
  119. break;
  120. case 0xF40:
  121. return;
  122. case 0xF60:
  123. return;
  124. case 0xF80:
  125. return;
  126. default:
  127. qemu_log_mask(LOG_GUEST_ERROR,
  128. "l2x0_priv_write: Bad offset %x\n", (int)offset);
  129. break;
  130. }
  131. }
  132. static void l2x0_priv_reset(DeviceState *dev)
  133. {
  134. L2x0State *s = ARM_L2X0(dev);
  135. s->ctrl = 0;
  136. s->aux_ctrl = 0x02020000;
  137. s->tag_ctrl = 0;
  138. s->data_ctrl = 0;
  139. s->filter_start = 0;
  140. s->filter_end = 0;
  141. }
  142. static const MemoryRegionOps l2x0_mem_ops = {
  143. .read = l2x0_priv_read,
  144. .write = l2x0_priv_write,
  145. .endianness = DEVICE_NATIVE_ENDIAN,
  146. };
  147. static int l2x0_priv_init(SysBusDevice *dev)
  148. {
  149. L2x0State *s = ARM_L2X0(dev);
  150. memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s,
  151. "l2x0_cc", 0x1000);
  152. sysbus_init_mmio(dev, &s->iomem);
  153. return 0;
  154. }
  155. static Property l2x0_properties[] = {
  156. DEFINE_PROP_UINT32("cache-type", L2x0State, cache_type, 0x1c100100),
  157. DEFINE_PROP_END_OF_LIST(),
  158. };
  159. static void l2x0_class_init(ObjectClass *klass, void *data)
  160. {
  161. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  162. DeviceClass *dc = DEVICE_CLASS(klass);
  163. k->init = l2x0_priv_init;
  164. dc->vmsd = &vmstate_l2x0;
  165. dc->props = l2x0_properties;
  166. dc->reset = l2x0_priv_reset;
  167. }
  168. static const TypeInfo l2x0_info = {
  169. .name = TYPE_ARM_L2X0,
  170. .parent = TYPE_SYS_BUS_DEVICE,
  171. .instance_size = sizeof(L2x0State),
  172. .class_init = l2x0_class_init,
  173. };
  174. static void l2x0_register_types(void)
  175. {
  176. type_register_static(&l2x0_info);
  177. }
  178. type_init(l2x0_register_types)