2
0

arm_l2x0.c 4.7 KB

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