1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include "qemu/osdep.h"
29#include "hw/sysbus.h"
30#include "hw/register-dep.h"
31#include "qemu/bitops.h"
32#include "qemu/log.h"
33
34#ifndef XILINX_OCM_ERR_DEBUG
35#define XILINX_OCM_ERR_DEBUG 0
36#endif
37
38#define TYPE_XILINX_OCM "xlnx.zynqmp-ocmc"
39
40#define XILINX_OCM(obj) \
41 OBJECT_CHECK(OCMC, (obj), TYPE_XILINX_OCM)
42
43DEP_REG32(OCM_ERR_CTRL, 0x0)
44 DEP_FIELD(OCM_ERR_CTRL, UE_RES, 1, 3)
45 DEP_FIELD(OCM_ERR_CTRL, PWR_ERR_RES, 1, 2)
46 DEP_FIELD(OCM_ERR_CTRL, PZ_ERR_RES, 1, 1)
47 DEP_FIELD(OCM_ERR_CTRL, APB_ERR_RES, 1, 0)
48DEP_REG32(OCM_ISR, 0x4)
49 DEP_FIELD(OCM_ISR, UE_RMW, 1, 10)
50 DEP_FIELD(OCM_ISR, FIX_BURST_WR, 1, 9)
51 DEP_FIELD(OCM_ISR, FIX_BURST_RD, 1, 8)
52 DEP_FIELD(OCM_ISR, ECC_UE, 1, 7)
53 DEP_FIELD(OCM_ISR, ECC_CE, 1, 6)
54 DEP_FIELD(OCM_ISR, LOCK_ERR_WR, 1, 5)
55 DEP_FIELD(OCM_ISR, LOCK_ERR_RD, 1, 4)
56 DEP_FIELD(OCM_ISR, INV_OCM_WR, 1, 3)
57 DEP_FIELD(OCM_ISR, INV_OCM_RD, 1, 2)
58 DEP_FIELD(OCM_ISR, PWR_DWN, 1, 1)
59 DEP_FIELD(OCM_ISR, INV_APB, 1, 0)
60DEP_REG32(OCM_IMR, 0x8)
61 DEP_FIELD(OCM_IMR, UE_RMW, 1, 10)
62 DEP_FIELD(OCM_IMR, FIX_BURST_WR, 1, 9)
63 DEP_FIELD(OCM_IMR, FIX_BURST_RD, 1, 8)
64 DEP_FIELD(OCM_IMR, ECC_UE, 1, 7)
65 DEP_FIELD(OCM_IMR, ECC_CE, 1, 6)
66 DEP_FIELD(OCM_IMR, LOCK_ERR_WR, 1, 5)
67 DEP_FIELD(OCM_IMR, LOCK_ERR_RD, 1, 4)
68 DEP_FIELD(OCM_IMR, INV_OCM_WR, 1, 3)
69 DEP_FIELD(OCM_IMR, INV_OCM_RD, 1, 2)
70 DEP_FIELD(OCM_IMR, PWR_DWN, 1, 1)
71 DEP_FIELD(OCM_IMR, INV_APB, 1, 0)
72DEP_REG32(OCM_IEN, 0xc)
73 DEP_FIELD(OCM_IEN, UE_RMW, 1, 10)
74 DEP_FIELD(OCM_IEN, FIX_BURST_WR, 1, 9)
75 DEP_FIELD(OCM_IEN, FIX_BURST_RD, 1, 8)
76 DEP_FIELD(OCM_IEN, ECC_UE, 1, 7)
77 DEP_FIELD(OCM_IEN, ECC_CE, 1, 6)
78 DEP_FIELD(OCM_IEN, LOCK_ERR_WR, 1, 5)
79 DEP_FIELD(OCM_IEN, LOCK_ERR_RD, 1, 4)
80 DEP_FIELD(OCM_IEN, INV_OCM_WR, 1, 3)
81 DEP_FIELD(OCM_IEN, INV_OCM_RD, 1, 2)
82 DEP_FIELD(OCM_IEN, PWR_DWN, 1, 1)
83 DEP_FIELD(OCM_IEN, INV_APB, 1, 0)
84DEP_REG32(OCM_IDS, 0x10)
85 DEP_FIELD(OCM_IDS, UE_RMW, 1, 10)
86 DEP_FIELD(OCM_IDS, FIX_BURST_WR, 1, 9)
87 DEP_FIELD(OCM_IDS, FIX_BURST_RD, 1, 8)
88 DEP_FIELD(OCM_IDS, ECC_UE, 1, 7)
89 DEP_FIELD(OCM_IDS, ECC_CE, 1, 6)
90 DEP_FIELD(OCM_IDS, LOCK_ERR_WR, 1, 5)
91 DEP_FIELD(OCM_IDS, LOCK_ERR_RD, 1, 4)
92 DEP_FIELD(OCM_IDS, INV_OCM_WR, 1, 3)
93 DEP_FIELD(OCM_IDS, INV_OCM_RD, 1, 2)
94 DEP_FIELD(OCM_IDS, PWR_DWN, 1, 1)
95 DEP_FIELD(OCM_IDS, INV_APB, 1, 0)
96DEP_REG32(OCM_ECC_CNTL, 0x14)
97 DEP_FIELD(OCM_ECC_CNTL, FI_MODE, 1, 2)
98 DEP_FIELD(OCM_ECC_CNTL, DET_ONLY, 1, 1)
99 DEP_FIELD(OCM_ECC_CNTL, ECC_ON_OFF, 1, 0)
100DEP_REG32(OCM_CLR_EXE, 0x18)
101 DEP_FIELD(OCM_CLR_EXE, MON_7, 1, 7)
102 DEP_FIELD(OCM_CLR_EXE, MON_6, 1, 6)
103 DEP_FIELD(OCM_CLR_EXE, MON_5, 1, 5)
104 DEP_FIELD(OCM_CLR_EXE, MON_4, 1, 4)
105 DEP_FIELD(OCM_CLR_EXE, MON_3, 1, 3)
106 DEP_FIELD(OCM_CLR_EXE, MON_2, 1, 2)
107 DEP_FIELD(OCM_CLR_EXE, MON_1, 1, 1)
108 DEP_FIELD(OCM_CLR_EXE, MON_0, 1, 0)
109DEP_REG32(OCM_CE_FFA, 0x1c)
110 DEP_FIELD(OCM_CE_FFA, ADDR, 18, 0)
111DEP_REG32(OCM_CE_FFD0, 0x20)
112DEP_REG32(OCM_CE_FFD1, 0x24)
113DEP_REG32(OCM_CE_FFD2, 0x28)
114DEP_REG32(OCM_CE_FFD3, 0x2c)
115DEP_REG32(OCM_CE_FFE, 0x30)
116 DEP_FIELD(OCM_CE_FFE, SYNDROME, 16, 0)
117DEP_REG32(OCM_UE_FFA, 0x34)
118 DEP_FIELD(OCM_UE_FFA, ADDR, 18, 0)
119DEP_REG32(OCM_UE_FFD0, 0x38)
120DEP_REG32(OCM_UE_FFD1, 0x3c)
121DEP_REG32(OCM_UE_FFD2, 0x40)
122DEP_REG32(OCM_UE_FFD3, 0x44)
123DEP_REG32(OCM_UE_FFE, 0x48)
124 DEP_FIELD(OCM_UE_FFE, SYNDROME, 16, 0)
125DEP_REG32(OCM_FI_D0, 0x4c)
126DEP_REG32(OCM_FI_D1, 0x50)
127DEP_REG32(OCM_FI_D2, 0x54)
128DEP_REG32(OCM_FI_D3, 0x58)
129DEP_REG32(OCM_FI_SY, 0x5c)
130 DEP_FIELD(OCM_FI_SY, DATA, 16, 0)
131DEP_REG32(OCM_EMA, 0x60)
132 DEP_FIELD(OCM_EMA, BANK3, 3, 9)
133 DEP_FIELD(OCM_EMA, BANK2, 3, 6)
134 DEP_FIELD(OCM_EMA, BANK1, 3, 3)
135 DEP_FIELD(OCM_EMA, BANK0, 3, 0)
136DEP_REG32(OCM_EMAW, 0x64)
137 DEP_FIELD(OCM_EMAW, BANK3, 2, 6)
138 DEP_FIELD(OCM_EMAW, BANK2, 2, 4)
139 DEP_FIELD(OCM_EMAW, BANK1, 2, 2)
140 DEP_FIELD(OCM_EMAW, BANK0, 2, 0)
141DEP_REG32(OCM_EMAS, 0x68)
142 DEP_FIELD(OCM_EMAS, BANK3, 1, 3)
143 DEP_FIELD(OCM_EMAS, BANK2, 1, 2)
144 DEP_FIELD(OCM_EMAS, BANK1, 1, 1)
145 DEP_FIELD(OCM_EMAS, BANK0, 1, 0)
146DEP_REG32(OCM_CE_CNT, 0x6c)
147 DEP_FIELD(OCM_CE_CNT, COUNT, 16, 0)
148DEP_REG32(OCM_RMW_UE_FFA, 0x70)
149 DEP_FIELD(OCM_RMW_UE_FFA, ADDR, 18, 0)
150DEP_REG32(OCM_FI_CNTR, 0x74)
151 DEP_FIELD(OCM_FI_CNTR, COUNT, 24, 0)
152DEP_REG32(OCM_DBG_SYN_TOMEM, 0x78)
153DEP_REG32(OCM_DBG_SYN_FROMEM, 0x7c)
154DEP_REG32(OCM_IMP, 0x80)
155 DEP_FIELD(OCM_IMP, SIZE, 4, 0)
156DEP_REG32(OCM_ECO, 0xffc)
157
158#define R_MAX (R_OCM_ECO + 1)
159
160typedef struct OCMC {
161 SysBusDevice parent_obj;
162 MemoryRegion iomem;
163 qemu_irq irq;
164
165 struct {
166 uint64_t memsize;
167 } cfg;
168
169 uint32_t regs[R_MAX];
170 DepRegisterInfo regs_info[R_MAX];
171} OCMC;
172
173static const MemoryRegionOps ocm_ops = {
174 .read = dep_register_read_memory_le,
175 .write = dep_register_write_memory_le,
176 .endianness = DEVICE_LITTLE_ENDIAN,
177 .valid = {
178 .min_access_size = 4,
179 .max_access_size = 4,
180 },
181};
182
183static void ocm_update_irq(OCMC *s)
184{
185 bool pending = s->regs[R_OCM_ISR] & s->regs[R_OCM_IMR];
186 qemu_set_irq(s->irq, pending);
187}
188
189static void ocm_isr_postw(DepRegisterInfo *reg, uint64_t val64)
190{
191 OCMC *s = XILINX_OCM(reg->opaque);
192 ocm_update_irq(s);
193}
194
195static uint64_t ocm_ien_prew(DepRegisterInfo *reg, uint64_t val64)
196{
197 OCMC *s = XILINX_OCM(reg->opaque);
198 uint32_t val = val64;
199
200 s->regs[R_OCM_IMR] |= val;
201 ocm_update_irq(s);
202 return 0;
203}
204
205static uint64_t ocm_ids_prew(DepRegisterInfo *reg, uint64_t val64)
206{
207 OCMC *s = XILINX_OCM(reg->opaque);
208 uint32_t val = val64;
209
210 s->regs[R_OCM_IMR] &= ~val;
211 ocm_update_irq(s);
212 return 0;
213}
214
215static DepRegisterAccessInfo ocm_regs_info[] = {
216 { .name = "OCM_ERR_CTRL", .decode.addr = A_OCM_ERR_CTRL,
217 .rsvd = 0xfffffff0,
218 },{ .name = "OCM_ISR", .decode.addr = A_OCM_ISR,
219 .rsvd = 0xfffff800,
220 .w1c = 0x7ff,
221 .ro = ~0x7ffull,
222 .post_write = ocm_isr_postw,
223 },{ .name = "OCM_IMR", .decode.addr = A_OCM_IMR,
224 .reset = 0x7ff,
225 .rsvd = 0xfffff800,
226 .ro = 0x7ff,
227 },{ .name = "OCM_IEN", .decode.addr = A_OCM_IEN,
228 .rsvd = 0xfffff800,
229 .pre_write = ocm_ien_prew,
230 },{ .name = "OCM_IDS", .decode.addr = A_OCM_IDS,
231 .rsvd = 0xfffff800,
232 .pre_write = ocm_ids_prew,
233 },{ .name = "OCM_ECC_CNTL", .decode.addr = A_OCM_ECC_CNTL,
234 .rsvd = 0xfffffff8,
235 },{ .name = "OCM_CLR_EXE", .decode.addr = A_OCM_CLR_EXE,
236 .rsvd = 0xffffff00,
237 },{ .name = "OCM_CE_FFA", .decode.addr = A_OCM_CE_FFA,
238 .rsvd = 0xfffc0000,
239 .ro = 0x3ffff,
240 },{ .name = "OCM_CE_FFD0", .decode.addr = A_OCM_CE_FFD0,
241 .ro = 0xffffffff,
242 },{ .name = "OCM_CE_FFD1", .decode.addr = A_OCM_CE_FFD1,
243 .ro = 0xffffffff,
244 },{ .name = "OCM_CE_FFD2", .decode.addr = A_OCM_CE_FFD2,
245 .ro = 0xffffffff,
246 },{ .name = "OCM_CE_FFD3", .decode.addr = A_OCM_CE_FFD3,
247 .ro = 0xffffffff,
248 },{ .name = "OCM_CE_FFE", .decode.addr = A_OCM_CE_FFE,
249 .rsvd = 0xffff0000,
250 .ro = 0xffff,
251 },{ .name = "OCM_UE_FFA", .decode.addr = A_OCM_UE_FFA,
252 .rsvd = 0xfffc0000,
253 .ro = 0x3ffff,
254 },{ .name = "OCM_UE_FFD0", .decode.addr = A_OCM_UE_FFD0,
255 .ro = 0xffffffff,
256 },{ .name = "OCM_UE_FFD1", .decode.addr = A_OCM_UE_FFD1,
257 .ro = 0xffffffff,
258 },{ .name = "OCM_UE_FFD2", .decode.addr = A_OCM_UE_FFD2,
259 .ro = 0xffffffff,
260 },{ .name = "OCM_UE_FFD3", .decode.addr = A_OCM_UE_FFD3,
261 .ro = 0xffffffff,
262 },{ .name = "OCM_UE_FFE", .decode.addr = A_OCM_UE_FFE,
263 .rsvd = 0xffff0000,
264 .ro = 0xffff,
265 },{ .name = "OCM_FI_D0", .decode.addr = A_OCM_FI_D0,
266 },{ .name = "OCM_FI_D1", .decode.addr = A_OCM_FI_D1,
267 },{ .name = "OCM_FI_D2", .decode.addr = A_OCM_FI_D2,
268 },{ .name = "OCM_FI_D3", .decode.addr = A_OCM_FI_D3,
269 },{ .name = "OCM_FI_SY", .decode.addr = A_OCM_FI_SY,
270 .rsvd = 0xffff0000,
271 },{ .name = "OCM_EMA", .decode.addr = A_OCM_EMA,
272 .reset = 0x249,
273 .rsvd = 0xfffff000,
274 },{ .name = "OCM_EMAW", .decode.addr = A_OCM_EMAW,
275 .rsvd = 0xffffff00,
276 },{ .name = "OCM_EMAS", .decode.addr = A_OCM_EMAS,
277 .rsvd = 0xfffffff0,
278 },{ .name = "OCM_CE_CNT", .decode.addr = A_OCM_CE_CNT,
279 .w1c = 0xffff,
280 },{ .name = "OCM_RMW_UE_FFA", .decode.addr = A_OCM_RMW_UE_FFA,
281 .rsvd = 0xfffc0000,
282 .ro = 0x3ffff,
283 },{ .name = "OCM_FI_CNTR", .decode.addr = A_OCM_FI_CNTR,
284 .rsvd = 0xff000000,
285 },{ .name = "OCM_DBG_SYN_TOMEM", .decode.addr = A_OCM_DBG_SYN_TOMEM,
286 .ro = 0xffffffff,
287 },{ .name = "OCM_DBG_SYN_FROMEM", .decode.addr = A_OCM_DBG_SYN_FROMEM,
288 .ro = 0xffffffff,
289 },{ .name = "OCM_IMP", .decode.addr = A_OCM_IMP,
290 .reset = 0x2,
291 .ro = 0xf,
292 },{ .name = "OCM_ECO", .decode.addr = A_OCM_ECO,
293 }
294};
295
296static uint32_t ocmc_imp_encode_memsize(OCMC *s, uint64_t memsize)
297{
298 const char *prefix = object_get_canonical_path(OBJECT(s));
299 uint32_t r;
300
301 switch (memsize) {
302 case 64 * 1024:
303 r = 0;
304 break;
305 case 128 * 1024:
306 r = 1;
307 break;
308 case 256 * 1024:
309 r = 2;
310 break;
311
312 case 512 * 1024:
313 qemu_log("%s: WARN: Using an undefined OCM memory size.\n", prefix);
314 r = 3;
315 break;
316 default:
317 hw_error("%s: Invalid OCM memory size %" PRIu64 " bytes\n",
318 prefix, memsize);
319 break;
320 }
321 return r;
322}
323
324static void ocm_reset(DeviceState *dev)
325{
326 OCMC *s = XILINX_OCM(dev);
327 unsigned int i;
328
329 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
330 dep_register_reset(&s->regs_info[i]);
331 }
332
333 s->regs[R_OCM_IMP] = ocmc_imp_encode_memsize(s, s->cfg.memsize);
334 ocm_update_irq(s);
335}
336
337static void ocm_realize(DeviceState *dev, Error **errp)
338{
339 OCMC *s = XILINX_OCM(dev);
340 const char *prefix = object_get_canonical_path(OBJECT(dev));
341 unsigned int i;
342
343 for (i = 0; i < ARRAY_SIZE(ocm_regs_info); ++i) {
344 DepRegisterInfo *r = &s->regs_info[i];
345
346 *r = (DepRegisterInfo) {
347 .data = (uint8_t *)&s->regs[
348 ocm_regs_info[i].decode.addr/4],
349 .data_size = sizeof(uint32_t),
350 .access = &ocm_regs_info[i],
351 .debug = XILINX_OCM_ERR_DEBUG,
352 .prefix = prefix,
353 .opaque = s,
354 };
355 memory_region_init_io(&r->mem, OBJECT(dev), &ocm_ops, r,
356 r->access->name, 4);
357 memory_region_add_subregion(&s->iomem, r->access->decode.addr, &r->mem);
358 }
359}
360
361static void ocm_init(Object *obj)
362{
363 OCMC *s = XILINX_OCM(obj);
364 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
365
366 memory_region_init(&s->iomem, obj, TYPE_XILINX_OCM, R_MAX * 4);
367 sysbus_init_mmio(sbd, &s->iomem);
368 sysbus_init_irq(sbd, &s->irq);
369}
370
371static Property ocmc_properties[] = {
372 DEFINE_PROP_UINT64("memsize", OCMC, cfg.memsize, 0),
373 DEFINE_PROP_END_OF_LIST(),
374};
375
376static const VMStateDescription vmstate_ocm = {
377 .name = TYPE_XILINX_OCM,
378 .version_id = 1,
379 .minimum_version_id = 1,
380 .minimum_version_id_old = 1,
381 .fields = (VMStateField[]) {
382 VMSTATE_UINT32_ARRAY(regs, OCMC, R_MAX),
383 VMSTATE_END_OF_LIST(),
384 }
385};
386
387static void ocm_class_init(ObjectClass *klass, void *data)
388{
389 DeviceClass *dc = DEVICE_CLASS(klass);
390
391 dc->reset = ocm_reset;
392 dc->realize = ocm_realize;
393 dc->vmsd = &vmstate_ocm;
394 dc->props = ocmc_properties;
395}
396
397static const TypeInfo ocm_info = {
398 .name = TYPE_XILINX_OCM,
399 .parent = TYPE_SYS_BUS_DEVICE,
400 .instance_size = sizeof(OCMC),
401 .class_init = ocm_class_init,
402 .instance_init = ocm_init,
403};
404
405static void ocm_register_types(void)
406{
407 type_register_static(&ocm_info);
408}
409
410type_init(ocm_register_types)
411