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.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 "migration/vmstate.h"
36#include "hw/qdev-properties.h"
37#include "hw/fdt_generic_util.h"
38
39#ifndef XILINX_LPD_SLCR_ERR_DEBUG
40#define XILINX_LPD_SLCR_ERR_DEBUG 0
41#endif
42
43#define TYPE_XILINX_LPD_SLCR "xlnx.lpd-slcr"
44
45#define XILINX_LPD_SLCR(obj) \
46 OBJECT_CHECK(LPD_SLCR, (obj), TYPE_XILINX_LPD_SLCR)
47
48REG32(WPROT0, 0x0)
49 FIELD(WPROT0, ACTIVE, 0, 1)
50REG32(CTRL, 0x4)
51 FIELD(CTRL, SLVERR_ENABLE, 0, 1)
52REG32(ISR, 0x8)
53 FIELD(ISR, ADDR_DECODE_ERR, 0, 1)
54REG32(IMR, 0xc)
55 FIELD(IMR, ADDR_DECODE_ERR, 0, 1)
56REG32(IER, 0x10)
57 FIELD(IER, ADDR_DECODE_ERR, 0, 1)
58REG32(IDR, 0x14)
59 FIELD(IDR, ADDR_DECODE_ERR, 0, 1)
60REG32(ITR, 0x18)
61 FIELD(ITR, ADDR_DECODE_ERR, 0, 1)
62REG32(ECO, 0x1c)
63REG32(PERSISTENT0, 0x20)
64REG32(PERSISTENT1, 0x24)
65REG32(PERSISTENT2, 0x28)
66REG32(PERSISTENT3, 0x2c)
67REG32(PERSISTENT4, 0x30)
68REG32(PERSISTENT5, 0x34)
69REG32(PERSISTENT6, 0x38)
70REG32(PERSISTENT7, 0x3c)
71REG32(SAFETY_CHK0, 0x40)
72REG32(SAFETY_CHK1, 0x44)
73REG32(SAFETY_CHK2, 0x48)
74REG32(SAFETY_CHK3, 0x4c)
75REG32(CSUPMU_WDT_CLK_SEL, 0x50)
76 FIELD(CSUPMU_WDT_CLK_SEL, SELECT, 0, 1)
77REG32(ADMA_CFG, 0x0000200C)
78 FIELD(ADMA_CFG, BUS_WIDTH, 5, 2)
79 FIELD(ADMA_CFG, NUM_CH, 0, 5)
80REG32(ADMA_RAM, 0x00002010)
81 FIELD(ADMA_RAM, RAM1_EMAB, 12, 3)
82 FIELD(ADMA_RAM, RAM1_EMASA, 11, 1)
83 FIELD(ADMA_RAM, RAM1_EMAA, 8, 3)
84 FIELD(ADMA_RAM, RAM0_EMAB, 4, 3)
85 FIELD(ADMA_RAM, RAM0_EMASA, 3, 1)
86 FIELD(ADMA_RAM, RAM0_EMAA, 0, 3)
87REG32(ERR_AIBAXI_ISR, 0x00003000)
88 FIELD(ERR_AIBAXI_ISR, AFIFS2, 28, 1)
89 FIELD(ERR_AIBAXI_ISR, LPD_DDR, 27, 1)
90 FIELD(ERR_AIBAXI_ISR, OCMS, 26, 1)
91 FIELD(ERR_AIBAXI_ISR, FPD_MAIN, 24, 1)
92 FIELD(ERR_AIBAXI_ISR, USB1S, 23, 1)
93 FIELD(ERR_AIBAXI_ISR, USB0S, 22, 1)
94 FIELD(ERR_AIBAXI_ISR, RPUS1, 19, 1)
95 FIELD(ERR_AIBAXI_ISR, RPUS0, 18, 1)
96 FIELD(ERR_AIBAXI_ISR, RPUM1, 17, 1)
97 FIELD(ERR_AIBAXI_ISR, RPUM0, 16, 1)
98 FIELD(ERR_AIBAXI_ISR, FPD_OCM, 3, 1)
99 FIELD(ERR_AIBAXI_ISR, FPD_LPDIBS, 2, 1)
100 FIELD(ERR_AIBAXI_ISR, AFIFS1, 1, 1)
101 FIELD(ERR_AIBAXI_ISR, AFIFS0, 0, 1)
102REG32(ERR_AIBAXI_IMR, 0x00003008)
103 FIELD(ERR_AIBAXI_IMR, AFIFS2, 28, 1)
104 FIELD(ERR_AIBAXI_IMR, LPD_DDR, 27, 1)
105 FIELD(ERR_AIBAXI_IMR, OCMS, 26, 1)
106 FIELD(ERR_AIBAXI_IMR, FPD_MAIN, 24, 1)
107 FIELD(ERR_AIBAXI_IMR, USB1S, 23, 1)
108 FIELD(ERR_AIBAXI_IMR, USB0S, 22, 1)
109 FIELD(ERR_AIBAXI_IMR, RPUS1, 19, 1)
110 FIELD(ERR_AIBAXI_IMR, RPUS0, 18, 1)
111 FIELD(ERR_AIBAXI_IMR, RPUM1, 17, 1)
112 FIELD(ERR_AIBAXI_IMR, RPUM0, 16, 1)
113 FIELD(ERR_AIBAXI_IMR, FPD_OCM, 3, 1)
114 FIELD(ERR_AIBAXI_IMR, FPD_LPDIBS, 2, 1)
115 FIELD(ERR_AIBAXI_IMR, AFIFS1, 1, 1)
116 FIELD(ERR_AIBAXI_IMR, AFIFS0, 0, 1)
117REG32(ERR_AIBAXI_IER, 0x00003010)
118 FIELD(ERR_AIBAXI_IER, AFIFS2, 28, 1)
119 FIELD(ERR_AIBAXI_IER, LPD_DDR, 27, 1)
120 FIELD(ERR_AIBAXI_IER, OCMS, 26, 1)
121 FIELD(ERR_AIBAXI_IER, FPD_MAIN, 24, 1)
122 FIELD(ERR_AIBAXI_IER, USB1S, 23, 1)
123 FIELD(ERR_AIBAXI_IER, USB0S, 22, 1)
124 FIELD(ERR_AIBAXI_IER, RPUS1, 19, 1)
125 FIELD(ERR_AIBAXI_IER, RPUS0, 18, 1)
126 FIELD(ERR_AIBAXI_IER, RPUM1, 17, 1)
127 FIELD(ERR_AIBAXI_IER, RPUM0, 16, 1)
128 FIELD(ERR_AIBAXI_IER, FPD_OCM, 3, 1)
129 FIELD(ERR_AIBAXI_IER, FPD_LPDIBS, 2, 1)
130 FIELD(ERR_AIBAXI_IER, AFIFS1, 1, 1)
131 FIELD(ERR_AIBAXI_IER, AFIFS0, 0, 1)
132REG32(ERR_AIBAXI_IDR, 0x00003018)
133 FIELD(ERR_AIBAXI_IDR, AFIFS2, 28, 1)
134 FIELD(ERR_AIBAXI_IDR, LPD_DDR, 27, 1)
135 FIELD(ERR_AIBAXI_IDR, OCMS, 26, 1)
136 FIELD(ERR_AIBAXI_IDR, FPD_MAIN, 24, 1)
137 FIELD(ERR_AIBAXI_IDR, USB1S, 23, 1)
138 FIELD(ERR_AIBAXI_IDR, USB0S, 22, 1)
139 FIELD(ERR_AIBAXI_IDR, RPUS1, 19, 1)
140 FIELD(ERR_AIBAXI_IDR, RPUS0, 18, 1)
141 FIELD(ERR_AIBAXI_IDR, RPUM1, 17, 1)
142 FIELD(ERR_AIBAXI_IDR, RPUM0, 16, 1)
143 FIELD(ERR_AIBAXI_IDR, FPD_OCM, 3, 1)
144 FIELD(ERR_AIBAXI_IDR, FPD_LPDIBS, 2, 1)
145 FIELD(ERR_AIBAXI_IDR, AFIFS1, 1, 1)
146 FIELD(ERR_AIBAXI_IDR, AFIFS0, 0, 1)
147REG32(ERR_AIBAPB_ISR, 0x00003020)
148 FIELD(ERR_AIBAPB_ISR, GPU, 0, 1)
149REG32(ERR_AIBAPB_IMR, 0x00003024)
150 FIELD(ERR_AIBAPB_IMR, GPU, 0, 1)
151REG32(ERR_AIBAPB_IER, 0x00003028)
152 FIELD(ERR_AIBAPB_IER, GPU, 0, 1)
153REG32(ERR_AIBAPB_IDR, 0x0000302C)
154 FIELD(ERR_AIBAPB_IDR, GPU, 0, 1)
155REG32(ISO_AIBAXI_REQ, 0x00003030)
156 FIELD(ISO_AIBAXI_REQ, AFIFS2, 28, 1)
157 FIELD(ISO_AIBAXI_REQ, LPD_DDR, 27, 1)
158 FIELD(ISO_AIBAXI_REQ, OCMS, 26, 1)
159 FIELD(ISO_AIBAXI_REQ, FPD_MAIN, 24, 1)
160 FIELD(ISO_AIBAXI_REQ, USB1S, 23, 1)
161 FIELD(ISO_AIBAXI_REQ, USB0S, 22, 1)
162 FIELD(ISO_AIBAXI_REQ, RPUS1, 19, 1)
163 FIELD(ISO_AIBAXI_REQ, RPUS0, 18, 1)
164 FIELD(ISO_AIBAXI_REQ, RPUM1, 17, 1)
165 FIELD(ISO_AIBAXI_REQ, RPUM0, 16, 1)
166 FIELD(ISO_AIBAXI_REQ, FPD_OCM, 3, 1)
167 FIELD(ISO_AIBAXI_REQ, FPD_LPDIBS, 2, 1)
168 FIELD(ISO_AIBAXI_REQ, AFIFS1, 1, 1)
169 FIELD(ISO_AIBAXI_REQ, AFIFS0, 0, 1)
170REG32(ISO_AIBAXI_TYPE, 0x00003038)
171 FIELD(ISO_AIBAXI_TYPE, AFIFS2, 28, 1)
172 FIELD(ISO_AIBAXI_TYPE, LPD_DDR, 27, 1)
173 FIELD(ISO_AIBAXI_TYPE, OCMS, 26, 1)
174 FIELD(ISO_AIBAXI_TYPE, FPD_MAIN, 24, 1)
175 FIELD(ISO_AIBAXI_TYPE, USB1S, 23, 1)
176 FIELD(ISO_AIBAXI_TYPE, USB0S, 22, 1)
177 FIELD(ISO_AIBAXI_TYPE, RPUS1, 19, 1)
178 FIELD(ISO_AIBAXI_TYPE, RPUS0, 18, 1)
179 FIELD(ISO_AIBAXI_TYPE, RPUM1, 17, 1)
180 FIELD(ISO_AIBAXI_TYPE, RPUM0, 16, 1)
181 FIELD(ISO_AIBAXI_TYPE, FPD_OCM, 3, 1)
182 FIELD(ISO_AIBAXI_TYPE, FPD_LPDIBS, 2, 1)
183 FIELD(ISO_AIBAXI_TYPE, AFIFS1, 1, 1)
184 FIELD(ISO_AIBAXI_TYPE, AFIFS0, 0, 1)
185REG32(ISO_AIBAXI_ACK, 0x00003040)
186 FIELD(ISO_AIBAXI_ACK, AFIFS2, 28, 1)
187 FIELD(ISO_AIBAXI_ACK, LPD_DDR, 27, 1)
188 FIELD(ISO_AIBAXI_ACK, OCMS, 26, 1)
189 FIELD(ISO_AIBAXI_ACK, FPD_MAIN, 24, 1)
190 FIELD(ISO_AIBAXI_ACK, USB1S, 23, 1)
191 FIELD(ISO_AIBAXI_ACK, USB0S, 22, 1)
192 FIELD(ISO_AIBAXI_ACK, RPUS1, 19, 1)
193 FIELD(ISO_AIBAXI_ACK, RPUS0, 18, 1)
194 FIELD(ISO_AIBAXI_ACK, RPUM1, 17, 1)
195 FIELD(ISO_AIBAXI_ACK, RPUM0, 16, 1)
196 FIELD(ISO_AIBAXI_ACK, FPD_OCM, 3, 1)
197 FIELD(ISO_AIBAXI_ACK, FPD_LPDIBS, 2, 1)
198 FIELD(ISO_AIBAXI_ACK, AFIFS1, 1, 1)
199 FIELD(ISO_AIBAXI_ACK, AFIFS0, 0, 1)
200REG32(ISO_AIBAPB_REQ, 0x00003048)
201 FIELD(ISO_AIBAPB_REQ, GPU, 0, 1)
202REG32(ISO_AIBAPB_TYPE, 0x0000304C)
203 FIELD(ISO_AIBAPB_TYPE, GPU, 0, 1)
204REG32(ISO_AIBAPB_ACK, 0x00003050)
205 FIELD(ISO_AIBAPB_ACK, GPU, 0, 1)
206REG32(ERR_ATB_ISR, 0x00006000)
207 FIELD(ERR_ATB_ISR, AFIFS2, 1, 1)
208 FIELD(ERR_ATB_ISR, LPDM, 0, 1)
209REG32(ERR_ATB_IMR, 0x00006004)
210 FIELD(ERR_ATB_IMR, AFIFS2, 1, 1)
211 FIELD(ERR_ATB_IMR, LPDM, 0, 1)
212REG32(ERR_ATB_IER, 0x00006008)
213 FIELD(ERR_ATB_IER, AFIFS2, 1, 1)
214 FIELD(ERR_ATB_IER, LPDM, 0, 1)
215REG32(ERR_ATB_IDR, 0x0000600C)
216 FIELD(ERR_ATB_IDR, AFIFS2, 1, 1)
217 FIELD(ERR_ATB_IDR, LPDM, 0, 1)
218REG32(ATB_CMD_STORE_EN, 0x00006010)
219 FIELD(ATB_CMD_STORE_EN, AFIFS2, 1, 1)
220 FIELD(ATB_CMD_STORE_EN, LPDM, 0, 1)
221REG32(ATB_RESP_EN, 0x00006014)
222 FIELD(ATB_RESP_EN, AFIFS2, 1, 1)
223 FIELD(ATB_RESP_EN, LPDM, 0, 1)
224REG32(ATB_RESP_TYPE, 0x00006018)
225 FIELD(ATB_RESP_TYPE, AFIFS2, 1, 1)
226 FIELD(ATB_RESP_TYPE, LPDM, 0, 1)
227REG32(ATB_PRESCALE, 0x00006020)
228 FIELD(ATB_PRESCALE, ENABLE, 16, 1)
229 FIELD(ATB_PRESCALE, VALUE, 0, 16)
230REG32(MUTEX0, 0x00007000)
231REG32(MUTEX1, 0x00007004)
232REG32(MUTEX2, 0x00007008)
233REG32(MUTEX3, 0x0000700C)
234REG32(GICP0_IRQ_STATUS, 0x00008000)
235REG32(GICP0_IRQ_MASK, 0x00008004)
236REG32(GICP0_IRQ_ENABLE, 0x00008008)
237REG32(GICP0_IRQ_DISABLE, 0x0000800C)
238REG32(GICP0_IRQ_TRIGGER, 0x00008010)
239REG32(GICP1_IRQ_STATUS, 0x00008014)
240REG32(GICP1_IRQ_MASK, 0x00008018)
241REG32(GICP1_IRQ_ENABLE, 0x0000801C)
242REG32(GICP1_IRQ_DISABLE, 0x00008020)
243REG32(GICP1_IRQ_TRIGGER, 0x00008024)
244REG32(GICP2_IRQ_STATUS, 0x00008028)
245REG32(GICP2_IRQ_MASK, 0x0000802C)
246REG32(GICP2_IRQ_ENABLE, 0x00008030)
247REG32(GICP2_IRQ_DISABLE, 0x00008034)
248REG32(GICP2_IRQ_TRIGGER, 0x00008038)
249REG32(GICP3_IRQ_STATUS, 0x0000803C)
250REG32(GICP3_IRQ_MASK, 0x00008040)
251REG32(GICP3_IRQ_ENABLE, 0x00008044)
252REG32(GICP3_IRQ_DISABLE, 0x00008048)
253REG32(GICP3_IRQ_TRIGGER, 0x0000804C)
254REG32(GICP4_IRQ_STATUS, 0x00008050)
255REG32(GICP4_IRQ_MASK, 0x00008054)
256REG32(GICP4_IRQ_ENABLE, 0x00008058)
257REG32(GICP4_IRQ_DISABLE, 0x0000805C)
258REG32(GICP4_IRQ_TRIGGER, 0x00008060)
259REG32(GICP_PMU_IRQ_STATUS, 0x000080A0)
260REG32(GICP_PMU_IRQ_MASK, 0x000080A4)
261REG32(GICP_PMU_IRQ_ENABLE, 0x000080A8)
262REG32(GICP_PMU_IRQ_DISABLE, 0x000080AC)
263REG32(GICP_PMU_IRQ_TRIGGER, 0x000080B0)
264REG32(AFI_FS, 0x00009000)
265REG32(LPD_CCI, 0x0000A000)
266 FIELD(LPD_CCI, SPARE, 28, 4)
267 FIELD(LPD_CCI, QVNVNETS4, 27, 1)
268 FIELD(LPD_CCI, QVNVNETS3, 26, 1)
269 FIELD(LPD_CCI, QVNVNETS2, 25, 1)
270 FIELD(LPD_CCI, QVNVNETS1, 24, 1)
271 FIELD(LPD_CCI, QVNVNETS0, 23, 1)
272 FIELD(LPD_CCI, QOSOVERRIDE, 18, 5)
273 FIELD(LPD_CCI, QVNENABLE_M2, 17, 1)
274 FIELD(LPD_CCI, QVNENABLE_M1, 16, 1)
275 FIELD(LPD_CCI, STRIPING_GRANULE, 13, 3)
276 FIELD(LPD_CCI, ACCHANNELEN4, 12, 1)
277 FIELD(LPD_CCI, ACCHANNELEN3, 11, 1)
278 FIELD(LPD_CCI, ACCHANNELEN0, 10, 1)
279 FIELD(LPD_CCI, ECOREVNUM, 6, 4)
280 FIELD(LPD_CCI, ASA2, 5, 1)
281 FIELD(LPD_CCI, ASA1, 4, 1)
282 FIELD(LPD_CCI, ASA0, 3, 1)
283 FIELD(LPD_CCI, OWO2, 2, 1)
284 FIELD(LPD_CCI, OWO1, 1, 1)
285 FIELD(LPD_CCI, OWO0, 0, 1)
286REG32(LPD_CCI_ADDRMAP, 0x0000A004)
287 FIELD(LPD_CCI_ADDRMAP, 15, 30, 2)
288 FIELD(LPD_CCI_ADDRMAP, 14, 28, 2)
289 FIELD(LPD_CCI_ADDRMAP, 13, 26, 2)
290 FIELD(LPD_CCI_ADDRMAP, 12, 24, 2)
291 FIELD(LPD_CCI_ADDRMAP, 11, 22, 2)
292 FIELD(LPD_CCI_ADDRMAP, 10, 20, 2)
293 FIELD(LPD_CCI_ADDRMAP, 9, 18, 2)
294 FIELD(LPD_CCI_ADDRMAP, 8, 16, 2)
295 FIELD(LPD_CCI_ADDRMAP, 7, 14, 2)
296 FIELD(LPD_CCI_ADDRMAP, 6, 12, 2)
297 FIELD(LPD_CCI_ADDRMAP, 5, 10, 2)
298 FIELD(LPD_CCI_ADDRMAP, 4, 8, 2)
299 FIELD(LPD_CCI_ADDRMAP, 3, 6, 2)
300 FIELD(LPD_CCI_ADDRMAP, 2, 4, 2)
301 FIELD(LPD_CCI_ADDRMAP, 1, 2, 2)
302 FIELD(LPD_CCI_ADDRMAP, 0, 0, 2)
303REG32(LPD_CCI_QVNPREALLOC, 0x0000A008)
304 FIELD(LPD_CCI_QVNPREALLOC, WM2, 20, 4)
305 FIELD(LPD_CCI_QVNPREALLOC, WM1, 16, 4)
306 FIELD(LPD_CCI_QVNPREALLOC, RM2, 8, 4)
307 FIELD(LPD_CCI_QVNPREALLOC, RM1, 4, 4)
308REG32(LPD_SMMU, 0x0000A020)
309 FIELD(LPD_SMMU, INTEG_SEC_OVERRIDE, 7, 1)
310 FIELD(LPD_SMMU, CTTW, 6, 1)
311 FIELD(LPD_SMMU, SYSBARDISABLE_TBU5, 5, 1)
312 FIELD(LPD_SMMU, SYSBARDISABLE_TBU4, 4, 1)
313 FIELD(LPD_SMMU, SYSBARDISABLE_TBU3, 3, 1)
314 FIELD(LPD_SMMU, SYSBARDISABLE_TBU2, 2, 1)
315 FIELD(LPD_SMMU, SYSBARDISABLE_TBU1, 1, 1)
316 FIELD(LPD_SMMU, SYSBARDISABLE_TBU0, 0, 1)
317REG32(LPD_APU, 0x0000A040)
318 FIELD(LPD_APU, BRDC_BARRIER, 3, 1)
319 FIELD(LPD_APU, BRDC_CMNT, 2, 1)
320 FIELD(LPD_APU, BRDC_INNER, 1, 1)
321 FIELD(LPD_APU, BRDC_OUTER, 0, 1)
322
323#define R_MAX (R_LPD_APU + 1)
324
325#define OFFSET_TO_BANK(offset) (((offset >> 2) - R_GICP0_IRQ_STATUS) \
326 / (R_GICP1_IRQ_STATUS - R_GICP0_IRQ_STATUS))
327#define GIC_IRQ_STATUS(n) (R_GICP0_IRQ_STATUS + (0x14 >> 2) * (n))
328
329typedef struct LPD_SLCR {
330 SysBusDevice parent_obj;
331 MemoryRegion iomem;
332 qemu_irq irq_isr;
333
334
335 XlnxSCUGICState *rpu_gic;
336
337 XlnxSCUGICState *apu_gic;
338
339 uint32_t regs[R_MAX];
340 RegisterInfo regs_info[R_MAX];
341} LPD_SLCR;
342
343
344
345
346
347static uint64_t protection_prew(RegisterInfo *reg, uint64_t val64)
348{
349 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
350 bool w_dis = ARRAY_FIELD_EX32(s->regs, WPROT0, ACTIVE);
351
352 if (w_dis) {
353 val64 = s->regs[reg->access->addr >> 2];
354 }
355
356 return val64;
357}
358
359static void isr_update_irq(LPD_SLCR *s)
360{
361 bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
362 qemu_set_irq(s->irq_isr, pending);
363}
364
365static void isr_postw(RegisterInfo *reg, uint64_t val64)
366{
367 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
368 isr_update_irq(s);
369}
370
371static uint64_t ier_prew(RegisterInfo *reg, uint64_t val64)
372{
373 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
374 uint32_t val = protection_prew(reg, val64);
375
376 s->regs[R_IMR] &= ~val;
377 isr_update_irq(s);
378 return 0;
379}
380
381static uint64_t idr_prew(RegisterInfo *reg, uint64_t val64)
382{
383 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
384 uint32_t val = protection_prew(reg, val64);
385
386 s->regs[R_IMR] |= val;
387 isr_update_irq(s);
388 return 0;
389}
390
391static uint64_t itr_prew(RegisterInfo *reg, uint64_t val64)
392{
393 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
394 uint32_t val = protection_prew(reg, val64);
395
396 s->regs[R_ISR] |= val;
397 isr_update_irq(s);
398 return 0;
399}
400
401static uint64_t mutex_prew(RegisterInfo *reg, uint64_t val64)
402{
403 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
404 uint32_t val = protection_prew(reg, val64);
405
406 if (!val) {
407 return 0;
408 } else if (!s->regs[reg->access->addr >> 2]) {
409 return val;
410 } else {
411 return s->regs[reg->access->addr >> 2];
412 }
413}
414
415
416static void lpd_slcr_peripheral_irq_update(LPD_SLCR *s, uint8_t bank)
417{
418 xlnx_scu_gic_set_intr(s->rpu_gic, bank, s->regs[GIC_IRQ_STATUS(bank)], 1);
419 xlnx_scu_gic_set_intr(s->apu_gic, bank, s->regs[GIC_IRQ_STATUS(bank)], 1);
420}
421
422static uint64_t lpd_slcr_ier_prew(RegisterInfo *reg, uint64_t val64)
423{
424 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
425 uint32_t val = protection_prew(reg, val64);
426 uint32_t mask_offset = (reg->access->addr >> 2)
427 - (R_GICP0_IRQ_ENABLE - R_GICP0_IRQ_MASK);
428
429 s->regs[mask_offset] &= ~val;
430 return 0;
431}
432
433static uint64_t lpd_slcr_idr_prew(RegisterInfo *reg, uint64_t val64)
434{
435 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
436 uint32_t val = protection_prew(reg, val64);
437 uint32_t mask_offset = (reg->access->addr >> 2)
438 - (R_GICP0_IRQ_DISABLE - R_GICP0_IRQ_MASK);
439
440 s->regs[mask_offset] |= val;
441 return 0;
442}
443
444static void lpd_slcr_inttrig_posw(RegisterInfo *reg, uint64_t val64)
445{
446 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
447 uint32_t val = val64;
448 uint32_t mask_offset = (reg->access->addr >> 2)
449 - (R_GICP0_IRQ_TRIGGER - R_GICP0_IRQ_MASK);
450 uint32_t status_offset = (reg->access->addr >> 2)
451 - (R_GICP0_IRQ_TRIGGER - R_GICP0_IRQ_STATUS);
452 uint32_t enable = ~(s->regs[mask_offset]) & val;
453 s->regs[status_offset] |= enable;
454
455 lpd_slcr_peripheral_irq_update(s, OFFSET_TO_BANK(reg->access->addr));
456}
457
458static void lpd_slcr_intstatus_posw(RegisterInfo *reg, uint64_t val64)
459{
460 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
461
462 lpd_slcr_peripheral_irq_update(s, OFFSET_TO_BANK(reg->access->addr));
463}
464
465static void iso_aibaxi_req_postw(RegisterInfo *reg, uint64_t val64)
466{
467 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
468
469 bool w_dis = ARRAY_FIELD_EX32(s->regs, WPROT0, ACTIVE);
470
471 if (!w_dis) {
472 s->regs[R_ISO_AIBAXI_ACK] = val64;
473 }
474}
475
476static void iso_aibapb_req_postw(RegisterInfo *reg, uint64_t val64)
477{
478 LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
479
480 bool w_dis = ARRAY_FIELD_EX32(s->regs, WPROT0, ACTIVE);
481
482 if (!w_dis) {
483 s->regs[R_ISO_AIBAPB_ACK] = val64;
484 }
485}
486
487static RegisterAccessInfo lpd_slcr_regs_info[] = {
488 { .name = "WPROT0", .addr = A_WPROT0,
489 .reset = 0x1,
490 },{ .name = "CTRL", .addr = A_CTRL,
491 },{ .name = "ISR", .addr = A_ISR,
492 .w1c = 0x1,
493 .post_write = isr_postw,
494 .pre_write = protection_prew,
495 },{ .name = "IMR", .addr = A_IMR,
496 .reset = 0x1,
497 .ro = 0x1,
498 .pre_write = protection_prew,
499 },{ .name = "IER", .addr = A_IER,
500 .pre_write = ier_prew,
501 },{ .name = "IDR", .addr = A_IDR,
502 .pre_write = idr_prew,
503 },{ .name = "ITR", .addr = A_ITR,
504 .pre_write = itr_prew,
505 },{ .name = "ECO", .addr = A_ECO,
506 .pre_write = protection_prew,
507 },{ .name = "PERSISTENT0", .addr = A_PERSISTENT0,
508 .pre_write = protection_prew,
509 },{ .name = "PERSISTENT1", .addr = A_PERSISTENT1,
510 .pre_write = protection_prew,
511 },{ .name = "PERSISTENT2", .addr = A_PERSISTENT2,
512 .pre_write = protection_prew,
513 },{ .name = "PERSISTENT3", .addr = A_PERSISTENT3,
514 .pre_write = protection_prew,
515 },{ .name = "PERSISTENT4", .addr = A_PERSISTENT4,
516 .pre_write = protection_prew,
517 },{ .name = "PERSISTENT5", .addr = A_PERSISTENT5,
518 .pre_write = protection_prew,
519 },{ .name = "PERSISTENT6", .addr = A_PERSISTENT6,
520 .pre_write = protection_prew,
521 },{ .name = "PERSISTENT7", .addr = A_PERSISTENT7,
522 .pre_write = protection_prew,
523 },{ .name = "SAFETY_CHK0", .addr = A_SAFETY_CHK0,
524 .pre_write = protection_prew,
525 },{ .name = "SAFETY_CHK1", .addr = A_SAFETY_CHK1,
526 .pre_write = protection_prew,
527 },{ .name = "SAFETY_CHK2", .addr = A_SAFETY_CHK2,
528 .pre_write = protection_prew,
529 },{ .name = "SAFETY_CHK3", .addr = A_SAFETY_CHK3,
530 .pre_write = protection_prew,
531 },{ .name = "CSUPMU_WDT_CLK_SEL", .addr = A_CSUPMU_WDT_CLK_SEL,
532 .reset = 0,
533 .ro = 0xFFFFFFFE,
534 .pre_write = protection_prew,
535 },{ .name = "ADMA_CFG", .addr = A_ADMA_CFG,
536 .reset = 0x00000028,
537 .ro = 0xFFFFFFFF,
538 .pre_write = protection_prew,
539 },{ .name = "ADMA_RAM", .addr = A_ADMA_RAM,
540 .reset = 0x00003B3B,
541 .ro = 0xFFFFFF00,
542 .pre_write = protection_prew,
543 },{ .name = "ERR_AIBAXI_ISR", .addr = A_ERR_AIBAXI_ISR,
544 .reset = 0,
545 .w1c = 0xFFFFFFFF,
546 },{ .name = "ERR_AIBAXI_IMR", .addr = A_ERR_AIBAXI_IMR,
547 .reset = 0x1DCF000F,
548 .ro = 0xFFFFFFFF,
549 .pre_write = protection_prew,
550 },{ .name = "ERR_AIBAXI_IER", .addr = A_ERR_AIBAXI_IER,
551 .reset = 0,
552 .pre_write = protection_prew,
553 },{ .name = "ERR_AIBAXI_IDR", .addr = A_ERR_AIBAXI_IDR,
554 .reset = 0,
555 .pre_write = protection_prew,
556 },{ .name = "ERR_AIBAPB_ISR", .addr = A_ERR_AIBAPB_ISR,
557 .reset = 0,
558 .w1c = 0xFFFFFFFF,
559 .pre_write = protection_prew,
560 },{ .name = "ERR_AIBAPB_IMR", .addr = A_ERR_AIBAPB_IMR,
561 .reset = 0x00000001,
562 .ro = 0xFFFFFFFF,
563 .pre_write = protection_prew,
564 },{ .name = "ERR_AIBAPB_IER", .addr = A_ERR_AIBAPB_IER,
565 .reset = 0,
566 .pre_write = protection_prew,
567 },{ .name = "ERR_AIBAPB_IDR", .addr = A_ERR_AIBAPB_IDR,
568 .reset = 0,
569 .pre_write = protection_prew,
570 },{ .name = "ISO_AIBAXI_REQ", .addr = A_ISO_AIBAXI_REQ,
571 .reset = 0,
572 .pre_write = protection_prew,
573 .post_write = iso_aibaxi_req_postw,
574 },{ .name = "ISO_AIBAXI_TYPE", .addr = A_ISO_AIBAXI_TYPE,
575 .reset = 0x19CF000F,
576 .pre_write = protection_prew,
577 },{ .name = "ISO_AIBAXI_ACK", .addr = A_ISO_AIBAXI_ACK,
578 .reset = 0,
579 .ro = 0xFFFFFFFF,
580 .pre_write = protection_prew,
581 },{ .name = "ISO_AIBAPB_REQ", .addr = A_ISO_AIBAPB_REQ,
582 .reset = 0,
583 .pre_write = protection_prew,
584 .post_write = iso_aibapb_req_postw,
585 },{ .name = "ISO_AIBAPB_TYPE", .addr = A_ISO_AIBAPB_TYPE,
586 .reset = 0x00000001,
587 .pre_write = protection_prew,
588 },{ .name = "ISO_AIBAPB_ACK", .addr = A_ISO_AIBAPB_ACK,
589 .reset = 0,
590 .ro = 0xFFFFFFFF,
591 .pre_write = protection_prew,
592 },{ .name = "ERR_ATB_ISR", .addr = A_ERR_ATB_ISR,
593 .reset = 0,
594 .w1c = 0xFFFFFFFF,
595 .pre_write = protection_prew,
596 },{ .name = "ERR_ATB_IMR", .addr = A_ERR_ATB_IMR,
597 .reset = 0x00000003,
598 .ro = 0xFFFFFFFF,
599 .pre_write = protection_prew,
600 },{ .name = "ERR_ATB_IER", .addr = A_ERR_ATB_IER,
601 .reset = 0,
602 .pre_write = protection_prew,
603 },{ .name = "ERR_ATB_IDR", .addr = A_ERR_ATB_IDR,
604 .reset = 0,
605 .pre_write = protection_prew,
606 },{ .name = "ATB_CMD_STORE_EN", .addr = A_ATB_CMD_STORE_EN,
607 .reset = 0x00000003,
608 .pre_write = protection_prew,
609 },{ .name = "ATB_RESP_EN", .addr = A_ATB_RESP_EN,
610 .reset = 0,
611 .pre_write = protection_prew,
612 },{ .name = "ATB_RESP_TYPE", .addr = A_ATB_RESP_TYPE,
613 .reset = 0x00000003,
614 .pre_write = protection_prew,
615 },{ .name = "ATB_PRESCALE", .addr = A_ATB_PRESCALE,
616 .reset = 0x0000FFFF,
617 .pre_write = protection_prew,
618 },{ .name = "MUTEX0", .addr = A_MUTEX0,
619 .reset = 0,
620 .pre_write = mutex_prew,
621 },{ .name = "MUTEX1", .addr = A_MUTEX1,
622 .reset = 0,
623 .pre_write = mutex_prew,
624 },{ .name = "MUTEX2", .addr = A_MUTEX2,
625 .reset = 0,
626 .pre_write = mutex_prew,
627 },{ .name = "MUTEX3", .addr = A_MUTEX3,
628 .reset = 0,
629 .pre_write = mutex_prew,
630 },{ .name = "GICP0_IRQ_STATUS", .addr = A_GICP0_IRQ_STATUS,
631 .reset = 0,
632 .w1c = 0xFFFFFFFF,
633 .pre_write = protection_prew,
634 .post_write = lpd_slcr_intstatus_posw,
635 },{ .name = "GICP0_IRQ_MASK", .addr = A_GICP0_IRQ_MASK,
636 .reset = 0xFFFFFFFF,
637 .ro = 0xFFFFFFFF,
638 .pre_write = protection_prew,
639 },{ .name = "GICP0_IRQ_ENABLE", .addr = A_GICP0_IRQ_ENABLE,
640 .reset = 0,
641 .pre_write = lpd_slcr_ier_prew,
642 },{ .name = "GICP0_IRQ_DISABLE", .addr = A_GICP0_IRQ_DISABLE,
643 .reset = 0,
644 .pre_write = lpd_slcr_idr_prew,
645 },{ .name = "GICP0_IRQ_TRIGGER", .addr = A_GICP0_IRQ_TRIGGER,
646 .reset = 0,
647 .pre_write = protection_prew,
648 .post_write = lpd_slcr_inttrig_posw,
649 },{ .name = "GICP1_IRQ_STATUS", .addr = A_GICP1_IRQ_STATUS,
650 .reset = 0,
651 .w1c = 0xFFFFFFFF,
652 .pre_write = protection_prew,
653 .post_write = lpd_slcr_intstatus_posw,
654 },{ .name = "GICP1_IRQ_MASK", .addr = A_GICP1_IRQ_MASK,
655 .reset = 0xFFFFFFFF,
656 .ro = 0xFFFFFFFF,
657 .pre_write = protection_prew,
658 },{ .name = "GICP1_IRQ_ENABLE", .addr = A_GICP1_IRQ_ENABLE,
659 .reset = 0,
660 .pre_write = lpd_slcr_ier_prew,
661 },{ .name = "GICP1_IRQ_DISABLE", .addr = A_GICP1_IRQ_DISABLE,
662 .reset = 0,
663 .pre_write = lpd_slcr_idr_prew,
664 },{ .name = "GICP1_IRQ_TRIGGER", .addr = A_GICP1_IRQ_TRIGGER,
665 .reset = 0,
666 .pre_write = protection_prew,
667 .post_write = lpd_slcr_inttrig_posw,
668 },{ .name = "GICP2_IRQ_STATUS", .addr = A_GICP2_IRQ_STATUS,
669 .reset = 0,
670 .w1c = 0xFFFFFFFF,
671 .pre_write = protection_prew,
672 .post_write = lpd_slcr_intstatus_posw,
673 },{ .name = "GICP2_IRQ_MASK", .addr = A_GICP2_IRQ_MASK,
674 .reset = 0xFFFFFFFF,
675 .ro = 0xFFFFFFFF,
676 .pre_write = protection_prew,
677 },{ .name = "GICP2_IRQ_ENABLE", .addr = A_GICP2_IRQ_ENABLE,
678 .reset = 0,
679 .pre_write = lpd_slcr_ier_prew,
680 },{ .name = "GICP2_IRQ_DISABLE", .addr = A_GICP2_IRQ_DISABLE,
681 .reset = 0,
682 .pre_write = lpd_slcr_idr_prew,
683 },{ .name = "GICP2_IRQ_TRIGGER", .addr = A_GICP2_IRQ_TRIGGER,
684 .reset = 0,
685 .pre_write = protection_prew,
686 .post_write = lpd_slcr_inttrig_posw,
687 },{ .name = "GICP3_IRQ_STATUS", .addr = A_GICP3_IRQ_STATUS,
688 .reset = 0,
689 .w1c = 0xFFFFFFFF,
690 .pre_write = protection_prew,
691 .post_write = lpd_slcr_intstatus_posw,
692 },{ .name = "GICP3_IRQ_MASK", .addr = A_GICP3_IRQ_MASK,
693 .reset = 0xFFFFFFFF,
694 .ro = 0xFFFFFFFF,
695 .pre_write = protection_prew,
696 },{ .name = "GICP3_IRQ_ENABLE", .addr = A_GICP3_IRQ_ENABLE,
697 .reset = 0,
698 .pre_write = lpd_slcr_ier_prew,
699 },{ .name = "GICP3_IRQ_DISABLE", .addr = A_GICP3_IRQ_DISABLE,
700 .reset = 0,
701 .pre_write = lpd_slcr_idr_prew,
702 },{ .name = "GICP3_IRQ_TRIGGER", .addr = A_GICP3_IRQ_TRIGGER,
703 .reset = 0,
704 .pre_write = protection_prew,
705 .post_write = lpd_slcr_inttrig_posw,
706 },{ .name = "GICP4_IRQ_STATUS", .addr = A_GICP4_IRQ_STATUS,
707 .reset = 0,
708 .w1c = 0xFFFFFFFF,
709 .pre_write = protection_prew,
710 .post_write = lpd_slcr_intstatus_posw,
711 },{ .name = "GICP4_IRQ_MASK", .addr = A_GICP4_IRQ_MASK,
712 .reset = 0xFFFFFFFF,
713 .ro = 0xFFFFFFFF,
714 .pre_write = protection_prew,
715 },{ .name = "GICP4_IRQ_ENABLE", .addr = A_GICP4_IRQ_ENABLE,
716 .reset = 0,
717 .pre_write = lpd_slcr_ier_prew,
718 },{ .name = "GICP4_IRQ_DISABLE", .addr = A_GICP4_IRQ_DISABLE,
719 .reset = 0,
720 .pre_write = lpd_slcr_idr_prew,
721 },{ .name = "GICP4_IRQ_TRIGGER", .addr = A_GICP4_IRQ_TRIGGER,
722 .reset = 0,
723 .pre_write = protection_prew,
724 .post_write = lpd_slcr_inttrig_posw,
725 },{ .name = "GICP_PMU_IRQ_STATUS", .addr = A_GICP_PMU_IRQ_STATUS,
726 .reset = 0,
727 .pre_write = protection_prew,
728 .w1c = 0xFFFFFFFF,
729 },{ .name = "GICP_PMU_IRQ_MASK", .addr = A_GICP_PMU_IRQ_MASK,
730 .reset = 0x000000FF,
731 .ro = 0xFFFFFFFF,
732 .pre_write = protection_prew,
733 },{ .name = "GICP_PMU_IRQ_ENABLE", .addr = A_GICP_PMU_IRQ_ENABLE,
734 .reset = 0,
735 .pre_write = protection_prew,
736 },{ .name = "GICP_PMU_IRQ_DISABLE", .addr = A_GICP_PMU_IRQ_DISABLE,
737 .reset = 0,
738 .pre_write = protection_prew,
739 },{ .name = "GICP_PMU_IRQ_TRIGGER", .addr = A_GICP_PMU_IRQ_TRIGGER,
740 .reset = 0,
741 .pre_write = protection_prew,
742 },{ .name = "AFI_FS", .addr = A_AFI_FS,
743 .reset = 0x00000200,
744 .pre_write = protection_prew,
745 },{ .name = "LPD_CCI", .addr = A_LPD_CCI,
746 .reset = 0x03801C07,
747 .pre_write = protection_prew,
748 },{ .name = "LPD_CCI_ADDRMAP", .addr = A_LPD_CCI_ADDRMAP,
749 .reset = 0x00C000FF,
750 .pre_write = protection_prew,
751 },{ .name = "LPD_CCI_QVNPREALLOC", .addr = A_LPD_CCI_QVNPREALLOC,
752 .reset = 0x00330330,
753 .ro = 0x0000F00F,
754 .pre_write = protection_prew,
755 },{ .name = "LPD_SMMU", .addr = A_LPD_SMMU,
756 .reset = 0x0000003F,
757 .pre_write = protection_prew,
758 },{ .name = "LPD_APU", .addr = A_LPD_APU,
759 .reset = 0x00000001,
760 .pre_write = protection_prew,
761 },
762};
763
764static void lpd_slcr_reset(DeviceState *dev)
765{
766 LPD_SLCR *s = XILINX_LPD_SLCR(dev);
767 unsigned int i;
768
769 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
770 register_reset(&s->regs_info[i]);
771 }
772
773 isr_update_irq(s);
774}
775
776static const MemoryRegionOps lpd_slcr_ops = {
777 .read = register_read_memory,
778 .write = register_write_memory,
779 .endianness = DEVICE_LITTLE_ENDIAN,
780 .valid = {
781 .min_access_size = 4,
782 .max_access_size = 4,
783 },
784};
785
786static void lpd_slcr_realize(DeviceState *dev, Error **errp)
787{
788 LPD_SLCR *s = XILINX_LPD_SLCR(dev);
789
790 if (!s->rpu_gic) {
791 error_set(errp, ERROR_CLASS_GENERIC_ERROR, "gic-for-rpu");
792 return;
793 }
794
795 if (!s->apu_gic) {
796 error_set(errp, ERROR_CLASS_GENERIC_ERROR, "gic-for-apu");
797 return;
798 }
799}
800
801static void lpd_slcr_init(Object *obj)
802{
803 LPD_SLCR *s = XILINX_LPD_SLCR(obj);
804 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
805
806 RegisterInfoArray *reg_array;
807
808 memory_region_init(&s->iomem, obj, TYPE_XILINX_LPD_SLCR, R_MAX * 4);
809
810 reg_array =
811 register_init_block32(DEVICE(obj), lpd_slcr_regs_info,
812 ARRAY_SIZE(lpd_slcr_regs_info),
813 s->regs_info, s->regs,
814 &lpd_slcr_ops,
815 XILINX_LPD_SLCR_ERR_DEBUG,
816 R_MAX * 4);
817 memory_region_add_subregion(&s->iomem, 0x0, ®_array->mem);
818 sysbus_init_mmio(sbd, &s->iomem);
819 sysbus_init_irq(sbd, &s->irq_isr);
820
821
822
823 object_property_add_link(obj, "gic-for-rpu", TYPE_XLNX_SCU_GIC,
824 (Object **)&s->rpu_gic,
825 qdev_prop_allow_set_link_before_realize,
826 OBJ_PROP_LINK_STRONG);
827 object_property_add_link(obj, "gic-for-apu", TYPE_XLNX_SCU_GIC,
828 (Object **)&s->apu_gic,
829 qdev_prop_allow_set_link_before_realize,
830 OBJ_PROP_LINK_STRONG);
831}
832
833static const VMStateDescription vmstate_lpd_slcr = {
834 .name = TYPE_XILINX_LPD_SLCR,
835 .version_id = 1,
836 .minimum_version_id = 1,
837 .minimum_version_id_old = 1,
838 .fields = (VMStateField[]) {
839 VMSTATE_UINT32_ARRAY(regs, LPD_SLCR, R_MAX),
840 VMSTATE_END_OF_LIST(),
841 }
842};
843
844static void lpd_slcr_class_init(ObjectClass *klass, void *data)
845{
846 DeviceClass *dc = DEVICE_CLASS(klass);
847
848 dc->reset = lpd_slcr_reset;
849 dc->realize = lpd_slcr_realize;
850 dc->vmsd = &vmstate_lpd_slcr;
851}
852
853static const TypeInfo lpd_slcr_info = {
854 .name = TYPE_XILINX_LPD_SLCR,
855 .parent = TYPE_SYS_BUS_DEVICE,
856 .instance_size = sizeof(LPD_SLCR),
857 .class_init = lpd_slcr_class_init,
858 .instance_init = lpd_slcr_init,
859};
860
861static void lpd_slcr_register_types(void)
862{
863 type_register_static(&lpd_slcr_info);
864}
865
866type_init(lpd_slcr_register_types)
867