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#include "qemu/osdep.h"
28#include "hw/sysbus.h"
29#include "hw/register-dep.h"
30#include "qemu/bitops.h"
31#include "qapi/qmp/qerror.h"
32#include "qapi/error.h"
33#include "qemu/log.h"
34#include "hw/intc/xlnx_scu_gic.h"
35#include "hw/fdt_generic_util.h"
36
37#ifndef XILINX_LPD_SLCR_ERR_DEBUG
38#define XILINX_LPD_SLCR_ERR_DEBUG 0
39#endif
40
41#define TYPE_XILINX_LPD_SLCR "xlnx.lpd-slcr"
42
43#define XILINX_LPD_SLCR(obj) \
44 OBJECT_CHECK(LPD_SLCR, (obj), TYPE_XILINX_LPD_SLCR)
45
46DEP_REG32(WPROT0, 0x0)
47 DEP_FIELD(WPROT0, ACTIVE, 1, 0)
48DEP_REG32(CTRL, 0x4)
49 DEP_FIELD(CTRL, SLVERR_ENABLE, 1, 0)
50DEP_REG32(ISR, 0x8)
51 DEP_FIELD(ISR, ADDR_DECODE_ERR, 1, 0)
52DEP_REG32(IMR, 0xc)
53 DEP_FIELD(IMR, ADDR_DECODE_ERR, 1, 0)
54DEP_REG32(IER, 0x10)
55 DEP_FIELD(IER, ADDR_DECODE_ERR, 1, 0)
56DEP_REG32(IDR, 0x14)
57 DEP_FIELD(IDR, ADDR_DECODE_ERR, 1, 0)
58DEP_REG32(ITR, 0x18)
59 DEP_FIELD(ITR, ADDR_DECODE_ERR, 1, 0)
60DEP_REG32(ECO, 0x1c)
61DEP_REG32(PERSISTENT0, 0x20)
62DEP_REG32(PERSISTENT1, 0x24)
63DEP_REG32(PERSISTENT2, 0x28)
64DEP_REG32(PERSISTENT3, 0x2c)
65DEP_REG32(PERSISTENT4, 0x30)
66DEP_REG32(PERSISTENT5, 0x34)
67DEP_REG32(PERSISTENT6, 0x38)
68DEP_REG32(PERSISTENT7, 0x3c)
69DEP_REG32(SAFETY_CHK0, 0x40)
70DEP_REG32(SAFETY_CHK1, 0x44)
71DEP_REG32(SAFETY_CHK2, 0x48)
72DEP_REG32(SAFETY_CHK3, 0x4c)
73DEP_REG32(CSUPMU_WDT_CLK_SEL, 0x00000050)
74DEP_REG32(ADMA_CFG, 0x0000200C)
75DEP_REG32(ADMA_RAM, 0x00002010)
76DEP_REG32(ERR_AIBAXI_ISR, 0x00003000)
77DEP_REG32(ERR_AIBAXI_IMR, 0x00003008)
78DEP_REG32(ERR_AIBAXI_IER, 0x00003010)
79DEP_REG32(ERR_AIBAXI_IDR, 0x00003018)
80DEP_REG32(ERR_AIBAPB_ISR, 0x00003020)
81DEP_REG32(ERR_AIBAPB_IMR, 0x00003024)
82DEP_REG32(ERR_AIBAPB_IER, 0x00003028)
83DEP_REG32(ERR_AIBAPB_IDR, 0x0000302C)
84DEP_REG32(ISO_AIBAXI_REQ, 0x00003030)
85DEP_REG32(ISO_AIBAXI_TYPE, 0x00003038)
86DEP_REG32(ISO_AIBAXI_ACK, 0x00003040)
87DEP_REG32(ISO_AIBAPB_REQ, 0x00003048)
88DEP_REG32(ISO_AIBAPB_TYPE, 0x0000304C)
89DEP_REG32(ISO_AIBAPB_ACK, 0x00003050)
90DEP_REG32(ERR_ATB_ISR, 0x00006000)
91DEP_REG32(ERR_ATB_IMR, 0x00006004)
92DEP_REG32(ERR_ATB_IER, 0x00006008)
93DEP_REG32(ERR_ATB_IDR, 0x0000600C)
94DEP_REG32(ATB_CMD_STORE_EN, 0x00006010)
95DEP_REG32(ATB_RESP_EN, 0x00006014)
96DEP_REG32(ATB_RESP_TYPE, 0x00006018)
97DEP_REG32(ATB_PRESCALE, 0x00006020)
98DEP_REG32(MUTEX0, 0x00007000)
99DEP_REG32(MUTEX1, 0x00007004)
100DEP_REG32(MUTEX2, 0x00007008)
101DEP_REG32(MUTEX3, 0x0000700C)
102DEP_REG32(GICP0_IRQ_STATUS, 0x00008000)
103DEP_REG32(GICP0_IRQ_MASK, 0x00008004)
104DEP_REG32(GICP0_IRQ_ENABLE, 0x00008008)
105DEP_REG32(GICP0_IRQ_DISABLE, 0x0000800C)
106DEP_REG32(GICP0_IRQ_TRIGGER, 0x00008010)
107DEP_REG32(GICP1_IRQ_STATUS, 0x00008014)
108DEP_REG32(GICP1_IRQ_MASK, 0x00008018)
109DEP_REG32(GICP1_IRQ_ENABLE, 0x0000801C)
110DEP_REG32(GICP1_IRQ_DISABLE, 0x00008020)
111DEP_REG32(GICP1_IRQ_TRIGGER, 0x00008024)
112DEP_REG32(GICP2_IRQ_STATUS, 0x00008028)
113DEP_REG32(GICP2_IRQ_MASK, 0x0000802C)
114DEP_REG32(GICP2_IRQ_ENABLE, 0x00008030)
115DEP_REG32(GICP2_IRQ_DISABLE, 0x00008034)
116DEP_REG32(GICP2_IRQ_TRIGGER, 0x00008038)
117DEP_REG32(GICP3_IRQ_STATUS, 0x0000803C)
118DEP_REG32(GICP3_IRQ_MASK, 0x00008040)
119DEP_REG32(GICP3_IRQ_ENABLE, 0x00008044)
120DEP_REG32(GICP3_IRQ_DISABLE, 0x00008048)
121DEP_REG32(GICP3_IRQ_TRIGGER, 0x0000804C)
122DEP_REG32(GICP4_IRQ_STATUS, 0x00008050)
123DEP_REG32(GICP4_IRQ_MASK, 0x00008054)
124DEP_REG32(GICP4_IRQ_ENABLE, 0x00008058)
125DEP_REG32(GICP4_IRQ_DISABLE, 0x0000805C)
126DEP_REG32(GICP4_IRQ_TRIGGER, 0x00008060)
127DEP_REG32(GICP_PMU_IRQ_STATUS, 0x000080A0)
128DEP_REG32(GICP_PMU_IRQ_MASK, 0x000080A4)
129DEP_REG32(GICP_PMU_IRQ_ENABLE, 0x000080A8)
130DEP_REG32(GICP_PMU_IRQ_DISABLE, 0x000080AC)
131DEP_REG32(GICP_PMU_IRQ_TRIGGER, 0x000080B0)
132DEP_REG32(AFI_FS, 0x00009000)
133DEP_REG32(LPD_CCI, 0x0000A000)
134DEP_REG32(LPD_CCI_ADDRMAP, 0x0000A004)
135DEP_REG32(LPD_CCI_QVNPREALLOC, 0x0000A008)
136DEP_REG32(LPD_SMMU, 0x0000A020)
137DEP_REG32(LPD_APU, 0x0000A040)
138
139#define R_MAX (R_LPD_APU + 1)
140
141#define OFFSET_TO_BANK(offset) (((offset >> 2) - R_GICP0_IRQ_STATUS) \
142 / (R_GICP1_IRQ_STATUS - R_GICP0_IRQ_STATUS))
143#define GIC_IRQ_STATUS(n) (R_GICP0_IRQ_STATUS + (0x14 >> 2) * (n))
144
145typedef struct LPD_SLCR {
146 SysBusDevice parent_obj;
147 MemoryRegion iomem;
148 qemu_irq irq_isr;
149
150
151 XlnxSCUGICState *rpu_gic;
152
153 XlnxSCUGICState *apu_gic;
154
155 uint32_t regs[R_MAX];
156 DepRegisterInfo regs_info[R_MAX];
157} LPD_SLCR;
158
159
160
161
162
163static uint64_t protection_prew(DepRegisterInfo *reg, uint64_t val64)
164{
165 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
166 bool w_dis = DEP_AF_EX32(s->regs, WPROT0, ACTIVE);
167
168 if (w_dis) {
169 val64 = s->regs[reg->access->decode.addr >> 2];
170 }
171
172 return val64;
173}
174
175static void isr_update_irq(LPD_SLCR *s)
176{
177 bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
178 qemu_set_irq(s->irq_isr, pending);
179}
180
181static void isr_postw(DepRegisterInfo *reg, uint64_t val64)
182{
183 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
184 isr_update_irq(s);
185}
186
187static uint64_t ier_prew(DepRegisterInfo *reg, uint64_t val64)
188{
189 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
190 uint32_t val = protection_prew(reg, val64);
191
192 s->regs[R_IMR] &= ~val;
193 isr_update_irq(s);
194 return 0;
195}
196
197static uint64_t idr_prew(DepRegisterInfo *reg, uint64_t val64)
198{
199 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
200 uint32_t val = protection_prew(reg, val64);
201
202 s->regs[R_IMR] |= val;
203 isr_update_irq(s);
204 return 0;
205}
206
207static uint64_t itr_prew(DepRegisterInfo *reg, uint64_t val64)
208{
209 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
210 uint32_t val = protection_prew(reg, val64);
211
212 s->regs[R_ISR] |= val;
213 isr_update_irq(s);
214 return 0;
215}
216
217static uint64_t mutex_prew(DepRegisterInfo *reg, uint64_t val64)
218{
219 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
220 uint32_t val = protection_prew(reg, val64);
221
222 if (!val) {
223 return 0;
224 } else if (!s->regs[reg->access->decode.addr >> 2]) {
225 return val;
226 } else {
227 return s->regs[reg->access->decode.addr >> 2];
228 }
229}
230
231
232static void lpd_slcr_peripheral_irq_update(LPD_SLCR *s, uint8_t bank)
233{
234 xlnx_scu_gic_set_intr(s->rpu_gic, bank, s->regs[GIC_IRQ_STATUS(bank)], 1);
235 xlnx_scu_gic_set_intr(s->apu_gic, bank, s->regs[GIC_IRQ_STATUS(bank)], 1);
236}
237
238static uint64_t lpd_slcr_ier_prew(DepRegisterInfo *reg, uint64_t val64)
239{
240 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
241 uint32_t val = protection_prew(reg, val64);
242 uint32_t mask_offset = (reg->access->decode.addr >> 2)
243 - (R_GICP0_IRQ_ENABLE - R_GICP0_IRQ_MASK);
244
245 s->regs[mask_offset] &= ~val;
246 return 0;
247}
248
249static uint64_t lpd_slcr_idr_prew(DepRegisterInfo *reg, uint64_t val64)
250{
251 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
252 uint32_t val = protection_prew(reg, val64);
253 uint32_t mask_offset = (reg->access->decode.addr >> 2)
254 - (R_GICP0_IRQ_DISABLE - R_GICP0_IRQ_MASK);
255
256 s->regs[mask_offset] |= val;
257 return 0;
258}
259
260static void lpd_slcr_inttrig_posw(DepRegisterInfo *reg, uint64_t val64)
261{
262 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
263 uint32_t val = val64;
264 uint32_t mask_offset = (reg->access->decode.addr >> 2)
265 - (R_GICP0_IRQ_TRIGGER - R_GICP0_IRQ_MASK);
266 uint32_t status_offset = (reg->access->decode.addr >> 2)
267 - (R_GICP0_IRQ_TRIGGER - R_GICP0_IRQ_STATUS);
268 uint32_t enable = ~(s->regs[mask_offset]) & val;
269 s->regs[status_offset] |= enable;
270
271 lpd_slcr_peripheral_irq_update(s, OFFSET_TO_BANK(reg->access->decode.addr));
272}
273
274static void lpd_slcr_intstatus_posw(DepRegisterInfo *reg, uint64_t val64)
275{
276 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
277
278 lpd_slcr_peripheral_irq_update(s, OFFSET_TO_BANK(reg->access->decode.addr));
279}
280
281static DepRegisterAccessInfo lpd_slcr_regs_info[] = {
282 { .name = "WPROT0", .decode.addr = A_WPROT0,
283 .reset = 0x1,
284 },{ .name = "CTRL", .decode.addr = A_CTRL,
285 },{ .name = "ISR", .decode.addr = A_ISR,
286 .w1c = 0x1,
287 .post_write = isr_postw,
288 .pre_write = protection_prew,
289 },{ .name = "IMR", .decode.addr = A_IMR,
290 .reset = 0x1,
291 .ro = 0x1,
292 .pre_write = protection_prew,
293 },{ .name = "IER", .decode.addr = A_IER,
294 .pre_write = ier_prew,
295 },{ .name = "IDR", .decode.addr = A_IDR,
296 .pre_write = idr_prew,
297 },{ .name = "ITR", .decode.addr = A_ITR,
298 .pre_write = itr_prew,
299 },{ .name = "ECO", .decode.addr = A_ECO,
300 .pre_write = protection_prew,
301 },{ .name = "PERSISTENT0", .decode.addr = A_PERSISTENT0,
302 .pre_write = protection_prew,
303 },{ .name = "PERSISTENT1", .decode.addr = A_PERSISTENT1,
304 .pre_write = protection_prew,
305 },{ .name = "PERSISTENT2", .decode.addr = A_PERSISTENT2,
306 .pre_write = protection_prew,
307 },{ .name = "PERSISTENT3", .decode.addr = A_PERSISTENT3,
308 .pre_write = protection_prew,
309 },{ .name = "PERSISTENT4", .decode.addr = A_PERSISTENT4,
310 .pre_write = protection_prew,
311 },{ .name = "PERSISTENT5", .decode.addr = A_PERSISTENT5,
312 .pre_write = protection_prew,
313 },{ .name = "PERSISTENT6", .decode.addr = A_PERSISTENT6,
314 .pre_write = protection_prew,
315 },{ .name = "PERSISTENT7", .decode.addr = A_PERSISTENT7,
316 .pre_write = protection_prew,
317 },{ .name = "SAFETY_CHK0", .decode.addr = A_SAFETY_CHK0,
318 .pre_write = protection_prew,
319 },{ .name = "SAFETY_CHK1", .decode.addr = A_SAFETY_CHK1,
320 .pre_write = protection_prew,
321 },{ .name = "SAFETY_CHK2", .decode.addr = A_SAFETY_CHK2,
322 .pre_write = protection_prew,
323 },{ .name = "SAFETY_CHK3", .decode.addr = A_SAFETY_CHK3,
324 .pre_write = protection_prew,
325 },{ .name = "CSUPMU_WDT_CLK_SEL", .decode.addr = A_CSUPMU_WDT_CLK_SEL,
326 .reset = 0,
327 .ro = 0xFFFFFFFE,
328 .pre_write = protection_prew,
329 },{ .name = "ADMA_CFG", .decode.addr = A_ADMA_CFG,
330 .reset = 0x00000028,
331 .ro = 0xFFFFFFFF,
332 .pre_write = protection_prew,
333 },{ .name = "ADMA_RAM", .decode.addr = A_ADMA_RAM,
334 .reset = 0x00003B3B,
335 .ro = 0xFFFFFF00,
336 .pre_write = protection_prew,
337 },{ .name = "ERR_AIBAXI_ISR", .decode.addr = A_ERR_AIBAXI_ISR,
338 .reset = 0,
339 .w1c = 0xFFFFFFFF,
340 },{ .name = "ERR_AIBAXI_IMR", .decode.addr = A_ERR_AIBAXI_IMR,
341 .reset = 0x1DCF000F,
342 .ro = 0xFFFFFFFF,
343 .pre_write = protection_prew,
344 },{ .name = "ERR_AIBAXI_IER", .decode.addr = A_ERR_AIBAXI_IER,
345 .reset = 0,
346 .pre_write = protection_prew,
347 },{ .name = "ERR_AIBAXI_IDR", .decode.addr = A_ERR_AIBAXI_IDR,
348 .reset = 0,
349 .pre_write = protection_prew,
350 },{ .name = "ERR_AIBAPB_ISR", .decode.addr = A_ERR_AIBAPB_ISR,
351 .reset = 0,
352 .w1c = 0xFFFFFFFF,
353 .pre_write = protection_prew,
354 },{ .name = "ERR_AIBAPB_IMR", .decode.addr = A_ERR_AIBAPB_IMR,
355 .reset = 0x00000001,
356 .ro = 0xFFFFFFFF,
357 .pre_write = protection_prew,
358 },{ .name = "ERR_AIBAPB_IER", .decode.addr = A_ERR_AIBAPB_IER,
359 .reset = 0,
360 .pre_write = protection_prew,
361 },{ .name = "ERR_AIBAPB_IDR", .decode.addr = A_ERR_AIBAPB_IDR,
362 .reset = 0,
363 .pre_write = protection_prew,
364 },{ .name = "ISO_AIBAXI_REQ", .decode.addr = A_ISO_AIBAXI_REQ,
365 .reset = 0,
366 .pre_write = protection_prew,
367 },{ .name = "ISO_AIBAXI_TYPE", .decode.addr = A_ISO_AIBAXI_TYPE,
368 .reset = 0x19CF000F,
369 .pre_write = protection_prew,
370 },{ .name = "ISO_AIBAXI_ACK", .decode.addr = A_ISO_AIBAXI_ACK,
371 .reset = 0,
372 .ro = 0xFFFFFFFF,
373 .pre_write = protection_prew,
374 },{ .name = "ISO_AIBAPB_REQ", .decode.addr = A_ISO_AIBAPB_REQ,
375 .reset = 0,
376 .pre_write = protection_prew,
377 },{ .name = "ISO_AIBAPB_TYPE", .decode.addr = A_ISO_AIBAPB_TYPE,
378 .reset = 0x00000001,
379 .pre_write = protection_prew,
380 },{ .name = "ISO_AIBAPB_ACK", .decode.addr = A_ISO_AIBAPB_ACK,
381 .reset = 0,
382 .ro = 0xFFFFFFFF,
383 .pre_write = protection_prew,
384 },{ .name = "ERR_ATB_ISR", .decode.addr = A_ERR_ATB_ISR,
385 .reset = 0,
386 .w1c = 0xFFFFFFFF,
387 .pre_write = protection_prew,
388 },{ .name = "ERR_ATB_IMR", .decode.addr = A_ERR_ATB_IMR,
389 .reset = 0x00000003,
390 .ro = 0xFFFFFFFF,
391 .pre_write = protection_prew,
392 },{ .name = "ERR_ATB_IER", .decode.addr = A_ERR_ATB_IER,
393 .reset = 0,
394 .pre_write = protection_prew,
395 },{ .name = "ERR_ATB_IDR", .decode.addr = A_ERR_ATB_IDR,
396 .reset = 0,
397 .pre_write = protection_prew,
398 },{ .name = "ATB_CMD_STORE_EN", .decode.addr = A_ATB_CMD_STORE_EN,
399 .reset = 0x00000003,
400 .pre_write = protection_prew,
401 },{ .name = "ATB_RESP_EN", .decode.addr = A_ATB_RESP_EN,
402 .reset = 0,
403 .pre_write = protection_prew,
404 },{ .name = "ATB_RESP_TYPE", .decode.addr = A_ATB_RESP_TYPE,
405 .reset = 0x00000003,
406 .pre_write = protection_prew,
407 },{ .name = "ATB_PRESCALE", .decode.addr = A_ATB_PRESCALE,
408 .reset = 0x0000FFFF,
409 .pre_write = protection_prew,
410 },{ .name = "MUTEX0", .decode.addr = A_MUTEX0,
411 .reset = 0,
412 .pre_write = mutex_prew,
413 },{ .name = "MUTEX1", .decode.addr = A_MUTEX1,
414 .reset = 0,
415 .pre_write = mutex_prew,
416 },{ .name = "MUTEX2", .decode.addr = A_MUTEX2,
417 .reset = 0,
418 .pre_write = mutex_prew,
419 },{ .name = "MUTEX3", .decode.addr = A_MUTEX3,
420 .reset = 0,
421 .pre_write = mutex_prew,
422 },{ .name = "GICP0_IRQ_STATUS", .decode.addr = A_GICP0_IRQ_STATUS,
423 .reset = 0,
424 .w1c = 0xFFFFFFFF,
425 .pre_write = protection_prew,
426 .post_write = lpd_slcr_intstatus_posw,
427 },{ .name = "GICP0_IRQ_MASK", .decode.addr = A_GICP0_IRQ_MASK,
428 .reset = 0xFFFFFFFF,
429 .ro = 0xFFFFFFFF,
430 .pre_write = protection_prew,
431 },{ .name = "GICP0_IRQ_ENABLE", .decode.addr = A_GICP0_IRQ_ENABLE,
432 .reset = 0,
433 .pre_write = lpd_slcr_ier_prew,
434 },{ .name = "GICP0_IRQ_DISABLE", .decode.addr = A_GICP0_IRQ_DISABLE,
435 .reset = 0,
436 .pre_write = lpd_slcr_idr_prew,
437 },{ .name = "GICP0_IRQ_TRIGGER", .decode.addr = A_GICP0_IRQ_TRIGGER,
438 .reset = 0,
439 .pre_write = protection_prew,
440 .post_write = lpd_slcr_inttrig_posw,
441 },{ .name = "GICP1_IRQ_STATUS", .decode.addr = A_GICP1_IRQ_STATUS,
442 .reset = 0,
443 .w1c = 0xFFFFFFFF,
444 .pre_write = protection_prew,
445 .post_write = lpd_slcr_intstatus_posw,
446 },{ .name = "GICP1_IRQ_MASK", .decode.addr = A_GICP1_IRQ_MASK,
447 .reset = 0xFFFFFFFF,
448 .ro = 0xFFFFFFFF,
449 .pre_write = protection_prew,
450 },{ .name = "GICP1_IRQ_ENABLE", .decode.addr = A_GICP1_IRQ_ENABLE,
451 .reset = 0,
452 .pre_write = lpd_slcr_ier_prew,
453 },{ .name = "GICP1_IRQ_DISABLE", .decode.addr = A_GICP1_IRQ_DISABLE,
454 .reset = 0,
455 .pre_write = lpd_slcr_idr_prew,
456 },{ .name = "GICP1_IRQ_TRIGGER", .decode.addr = A_GICP1_IRQ_TRIGGER,
457 .reset = 0,
458 .pre_write = protection_prew,
459 .post_write = lpd_slcr_inttrig_posw,
460 },{ .name = "GICP2_IRQ_STATUS", .decode.addr = A_GICP2_IRQ_STATUS,
461 .reset = 0,
462 .w1c = 0xFFFFFFFF,
463 .pre_write = protection_prew,
464 .post_write = lpd_slcr_intstatus_posw,
465 },{ .name = "GICP2_IRQ_MASK", .decode.addr = A_GICP2_IRQ_MASK,
466 .reset = 0xFFFFFFFF,
467 .ro = 0xFFFFFFFF,
468 .pre_write = protection_prew,
469 },{ .name = "GICP2_IRQ_ENABLE", .decode.addr = A_GICP2_IRQ_ENABLE,
470 .reset = 0,
471 .pre_write = lpd_slcr_ier_prew,
472 },{ .name = "GICP2_IRQ_DISABLE", .decode.addr = A_GICP2_IRQ_DISABLE,
473 .reset = 0,
474 .pre_write = lpd_slcr_idr_prew,
475 },{ .name = "GICP2_IRQ_TRIGGER", .decode.addr = A_GICP2_IRQ_TRIGGER,
476 .reset = 0,
477 .pre_write = protection_prew,
478 .post_write = lpd_slcr_inttrig_posw,
479 },{ .name = "GICP3_IRQ_STATUS", .decode.addr = A_GICP3_IRQ_STATUS,
480 .reset = 0,
481 .w1c = 0xFFFFFFFF,
482 .pre_write = protection_prew,
483 .post_write = lpd_slcr_intstatus_posw,
484 },{ .name = "GICP3_IRQ_MASK", .decode.addr = A_GICP3_IRQ_MASK,
485 .reset = 0xFFFFFFFF,
486 .ro = 0xFFFFFFFF,
487 .pre_write = protection_prew,
488 },{ .name = "GICP3_IRQ_ENABLE", .decode.addr = A_GICP3_IRQ_ENABLE,
489 .reset = 0,
490 .pre_write = lpd_slcr_ier_prew,
491 },{ .name = "GICP3_IRQ_DISABLE", .decode.addr = A_GICP3_IRQ_DISABLE,
492 .reset = 0,
493 .pre_write = lpd_slcr_idr_prew,
494 },{ .name = "GICP3_IRQ_TRIGGER", .decode.addr = A_GICP3_IRQ_TRIGGER,
495 .reset = 0,
496 .pre_write = protection_prew,
497 .post_write = lpd_slcr_inttrig_posw,
498 },{ .name = "GICP4_IRQ_STATUS", .decode.addr = A_GICP4_IRQ_STATUS,
499 .reset = 0,
500 .w1c = 0xFFFFFFFF,
501 .pre_write = protection_prew,
502 .post_write = lpd_slcr_intstatus_posw,
503 },{ .name = "GICP4_IRQ_MASK", .decode.addr = A_GICP4_IRQ_MASK,
504 .reset = 0xFFFFFFFF,
505 .ro = 0xFFFFFFFF,
506 .pre_write = protection_prew,
507 },{ .name = "GICP4_IRQ_ENABLE", .decode.addr = A_GICP4_IRQ_ENABLE,
508 .reset = 0,
509 .pre_write = lpd_slcr_ier_prew,
510 },{ .name = "GICP4_IRQ_DISABLE", .decode.addr = A_GICP4_IRQ_DISABLE,
511 .reset = 0,
512 .pre_write = lpd_slcr_idr_prew,
513 },{ .name = "GICP4_IRQ_TRIGGER", .decode.addr = A_GICP4_IRQ_TRIGGER,
514 .reset = 0,
515 .pre_write = protection_prew,
516 .post_write = lpd_slcr_inttrig_posw,
517 },{ .name = "GICP_PMU_IRQ_STATUS", .decode.addr = A_GICP_PMU_IRQ_STATUS,
518 .reset = 0,
519 .pre_write = protection_prew,
520 .w1c = 0xFFFFFFFF,
521 },{ .name = "GICP_PMU_IRQ_MASK", .decode.addr = A_GICP_PMU_IRQ_MASK,
522 .reset = 0x000000FF,
523 .ro = 0xFFFFFFFF,
524 .pre_write = protection_prew,
525 },{ .name = "GICP_PMU_IRQ_ENABLE", .decode.addr = A_GICP_PMU_IRQ_ENABLE,
526 .reset = 0,
527 .pre_write = protection_prew,
528 },{ .name = "GICP_PMU_IRQ_DISABLE", .decode.addr = A_GICP_PMU_IRQ_DISABLE,
529 .reset = 0,
530 .pre_write = protection_prew,
531 },{ .name = "GICP_PMU_IRQ_TRIGGER", .decode.addr = A_GICP_PMU_IRQ_TRIGGER,
532 .reset = 0,
533 .pre_write = protection_prew,
534 },{ .name = "AFI_FS", .decode.addr = A_AFI_FS,
535 .reset = 0x00000200,
536 .pre_write = protection_prew,
537 },{ .name = "LPD_CCI", .decode.addr = A_LPD_CCI,
538 .reset = 0x03801C07,
539 .pre_write = protection_prew,
540 },{ .name = "LPD_CCI_ADDRMAP", .decode.addr = A_LPD_CCI_ADDRMAP,
541 .reset = 0x00C000FF,
542 .pre_write = protection_prew,
543 },{ .name = "LPD_CCI_QVNPREALLOC", .decode.addr = A_LPD_CCI_QVNPREALLOC,
544 .reset = 0x00330330,
545 .ro = 0x0000F00F,
546 .pre_write = protection_prew,
547 },{ .name = "LPD_SMMU", .decode.addr = A_LPD_SMMU,
548 .reset = 0x0000003F,
549 .pre_write = protection_prew,
550 },{ .name = "LPD_APU", .decode.addr = A_LPD_APU,
551 .reset = 0x00000001,
552 .pre_write = protection_prew,
553 },
554};
555
556static void lpd_slcr_reset(DeviceState *dev)
557{
558 LPD_SLCR *s = XILINX_LPD_SLCR(dev);
559 unsigned int i;
560
561 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
562 dep_register_reset(&s->regs_info[i]);
563 }
564
565 isr_update_irq(s);
566}
567
568static uint64_t lpd_slcr_read(void *opaque, hwaddr addr, unsigned size)
569{
570 LPD_SLCR *s = XILINX_LPD_SLCR(opaque);
571 DepRegisterInfo *r = &s->regs_info[addr / 4];
572
573 if (!r->data) {
574 qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
575 object_get_canonical_path(OBJECT(s)),
576 addr);
577 return 0;
578 }
579 return dep_register_read(r);
580}
581
582static void lpd_slcr_write(void *opaque, hwaddr addr, uint64_t value,
583 unsigned size)
584{
585 LPD_SLCR *s = XILINX_LPD_SLCR(opaque);
586 DepRegisterInfo *r = &s->regs_info[addr / 4];
587
588 if (!r->data) {
589 qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
590 object_get_canonical_path(OBJECT(s)),
591 addr, value);
592 return;
593 }
594 dep_register_write(r, value, ~0);
595}
596
597static const MemoryRegionOps lpd_slcr_ops = {
598 .read = lpd_slcr_read,
599 .write = lpd_slcr_write,
600 .endianness = DEVICE_LITTLE_ENDIAN,
601 .valid = {
602 .min_access_size = 4,
603 .max_access_size = 4,
604 },
605};
606
607static void lpd_slcr_realize(DeviceState *dev, Error **errp)
608{
609 LPD_SLCR *s = XILINX_LPD_SLCR(dev);
610 const char *prefix = object_get_canonical_path(OBJECT(dev));
611 unsigned int i;
612
613 if (!s->rpu_gic) {
614 error_set(errp, ERROR_CLASS_GENERIC_ERROR, "gic-for-rpu");
615 return;
616 }
617
618 if (!s->apu_gic) {
619 error_set(errp, ERROR_CLASS_GENERIC_ERROR, "gic-for-apu");
620 return;
621 }
622
623 for (i = 0; i < ARRAY_SIZE(lpd_slcr_regs_info); ++i) {
624 DepRegisterInfo *r = &s->regs_info[lpd_slcr_regs_info[i].decode.addr/4];
625
626 *r = (DepRegisterInfo) {
627 .data = (uint8_t *)&s->regs[
628 lpd_slcr_regs_info[i].decode.addr/4],
629 .data_size = sizeof(uint32_t),
630 .access = &lpd_slcr_regs_info[i],
631 .debug = XILINX_LPD_SLCR_ERR_DEBUG,
632 .prefix = prefix,
633 .opaque = s,
634 };
635 }
636}
637
638static void lpd_slcr_init(Object *obj)
639{
640 LPD_SLCR *s = XILINX_LPD_SLCR(obj);
641 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
642
643 memory_region_init_io(&s->iomem, obj, &lpd_slcr_ops, s,
644 TYPE_XILINX_LPD_SLCR, R_MAX * 4);
645 sysbus_init_mmio(sbd, &s->iomem);
646 sysbus_init_irq(sbd, &s->irq_isr);
647
648
649
650 object_property_add_link(obj, "gic-for-rpu", TYPE_XLNX_SCU_GIC,
651 (Object **)&s->rpu_gic,
652 qdev_prop_allow_set_link_before_realize,
653 OBJ_PROP_LINK_UNREF_ON_RELEASE,
654 &error_abort);
655 object_property_add_link(obj, "gic-for-apu", TYPE_XLNX_SCU_GIC,
656 (Object **)&s->apu_gic,
657 qdev_prop_allow_set_link_before_realize,
658 OBJ_PROP_LINK_UNREF_ON_RELEASE,
659 &error_abort);
660}
661
662static const VMStateDescription vmstate_lpd_slcr = {
663 .name = TYPE_XILINX_LPD_SLCR,
664 .version_id = 1,
665 .minimum_version_id = 1,
666 .minimum_version_id_old = 1,
667 .fields = (VMStateField[]) {
668 VMSTATE_UINT32_ARRAY(regs, LPD_SLCR, R_MAX),
669 VMSTATE_END_OF_LIST(),
670 }
671};
672
673static void lpd_slcr_class_init(ObjectClass *klass, void *data)
674{
675 DeviceClass *dc = DEVICE_CLASS(klass);
676
677 dc->reset = lpd_slcr_reset;
678 dc->realize = lpd_slcr_realize;
679 dc->vmsd = &vmstate_lpd_slcr;
680}
681
682static const TypeInfo lpd_slcr_info = {
683 .name = TYPE_XILINX_LPD_SLCR,
684 .parent = TYPE_SYS_BUS_DEVICE,
685 .instance_size = sizeof(LPD_SLCR),
686 .class_init = lpd_slcr_class_init,
687 .instance_init = lpd_slcr_init,
688};
689
690static void lpd_slcr_register_types(void)
691{
692 type_register_static(&lpd_slcr_info);
693}
694
695type_init(lpd_slcr_register_types)
696