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