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.h"
31#include "qemu/bitops.h"
32#include "qemu/log.h"
33#include "migration/vmstate.h"
34#include "hw/qdev-properties.h"
35
36#include "hw/fdt_generic_util.h"
37
38#ifndef XILINX_PSM_LOCAL_REG_ERR_DEBUG
39#define XILINX_PSM_LOCAL_REG_ERR_DEBUG 0
40#endif
41
42#define TYPE_XILINX_PSM_LOCAL_REG "xlnx.psm-local-reg"
43
44#define XILINX_PSM_LOCAL_REG(obj) \
45 OBJECT_CHECK(PSM_LOCAL_REG, (obj), TYPE_XILINX_PSM_LOCAL_REG)
46
47REG32(ACPU0_PWR_CNTRL, 0x0)
48 FIELD(ACPU0_PWR_CNTRL, ISOLATION, 4, 1)
49 FIELD(ACPU0_PWR_CNTRL, PWR_GATES, 0, 4)
50REG32(ACPU0_PWR_STATUS, 0x4)
51 FIELD(ACPU0_PWR_STATUS, PWR_GATES, 0, 4)
52REG32(ACPU1_PWR_CNTRL, 0x10)
53 FIELD(ACPU1_PWR_CNTRL, ISOLATION, 4, 1)
54 FIELD(ACPU1_PWR_CNTRL, PWR_GATES, 0, 4)
55REG32(ACPU1_PWR_STATUS, 0x14)
56 FIELD(ACPU1_PWR_STATUS, PWR_GATES, 0, 4)
57REG32(RPU_PWR_CNTRL, 0x80)
58 FIELD(RPU_PWR_CNTRL, ISOLATION, 4, 1)
59 FIELD(RPU_PWR_CNTRL, PWR_GATES, 0, 4)
60REG32(RPU_PWR_STATUS, 0x84)
61 FIELD(RPU_PWR_STATUS, PWR_GATES, 0, 4)
62REG32(L2_PWR_CNTRL, 0xb0)
63 FIELD(L2_PWR_CNTRL, BANK0, 0, 1)
64REG32(L2_CE_CNTRL, 0xb8)
65 FIELD(L2_CE_CNTRL, BANK0, 0, 1)
66REG32(L2_PWR_STATUS, 0xbc)
67 FIELD(L2_PWR_STATUS, BANK0, 0, 1)
68REG32(OCM_PWR_CNTRL, 0xc0)
69 FIELD(OCM_PWR_CNTRL, BANK3, 24, 1)
70 FIELD(OCM_PWR_CNTRL, BANK2, 16, 1)
71 FIELD(OCM_PWR_CNTRL, BANK1, 8, 1)
72 FIELD(OCM_PWR_CNTRL, BANK0, 0, 1)
73REG32(OCM_CE_CNTRL, 0xc8)
74 FIELD(OCM_CE_CNTRL, BANK3, 3, 1)
75 FIELD(OCM_CE_CNTRL, BANK2, 2, 1)
76 FIELD(OCM_CE_CNTRL, BANK1, 1, 1)
77 FIELD(OCM_CE_CNTRL, BANK0, 0, 1)
78REG32(OCM_PWR_STATUS, 0xcc)
79 FIELD(OCM_PWR_STATUS, BANK3, 24, 1)
80 FIELD(OCM_PWR_STATUS, BANK2, 16, 1)
81 FIELD(OCM_PWR_STATUS, BANK1, 8, 1)
82 FIELD(OCM_PWR_STATUS, BANK0, 0, 1)
83REG32(TCM_PWR_CNTRL, 0xd0)
84 FIELD(TCM_PWR_CNTRL, TCMB1, 24, 1)
85 FIELD(TCM_PWR_CNTRL, TCMA1, 16, 1)
86 FIELD(TCM_PWR_CNTRL, TCMB0, 8, 1)
87 FIELD(TCM_PWR_CNTRL, TCMA0, 0, 1)
88REG32(TCM_CE_CNTRL, 0xd8)
89 FIELD(TCM_CE_CNTRL, TCMB1, 3, 1)
90 FIELD(TCM_CE_CNTRL, TCMA1, 2, 1)
91 FIELD(TCM_CE_CNTRL, TCMB0, 1, 1)
92 FIELD(TCM_CE_CNTRL, TCMA0, 0, 1)
93REG32(TCM_PWR_STATUS, 0xdc)
94 FIELD(TCM_PWR_STATUS, TCMB1, 24, 1)
95 FIELD(TCM_PWR_STATUS, TCMA1, 16, 1)
96 FIELD(TCM_PWR_STATUS, TCMB0, 8, 1)
97 FIELD(TCM_PWR_STATUS, TCMA0, 0, 1)
98REG32(GEM_PWR_CNTRL, 0xe0)
99 FIELD(GEM_PWR_CNTRL, GEM1, 8, 1)
100 FIELD(GEM_PWR_CNTRL, GEM0, 0, 1)
101REG32(GEM_CE_CNTRL, 0xe4)
102 FIELD(GEM_CE_CNTRL, GEM1, 1, 1)
103 FIELD(GEM_CE_CNTRL, GEM0, 0, 1)
104REG32(GEM_PWR_STATUS, 0xe8)
105 FIELD(GEM_PWR_STATUS, GEM1, 8, 1)
106 FIELD(GEM_PWR_STATUS, GEM0, 0, 1)
107REG32(DOMAIN_ISO_CNTRL, 0xf0)
108 FIELD(DOMAIN_ISO_CNTRL, LPD_OCM2_DFX, 3, 1)
109 FIELD(DOMAIN_ISO_CNTRL, LPD_OCM2, 2, 1)
110 FIELD(DOMAIN_ISO_CNTRL, LPD_FPD_DFX, 1, 1)
111 FIELD(DOMAIN_ISO_CNTRL, LPD_FPD, 0, 1)
112REG32(LOC_PWR_STATE, 0x100)
113 FIELD(LOC_PWR_STATE, FP, 22, 1)
114 FIELD(LOC_PWR_STATE, GEM0, 21, 1)
115 FIELD(LOC_PWR_STATE, GEM1, 20, 1)
116 FIELD(LOC_PWR_STATE, OCM_BANK3, 19, 1)
117 FIELD(LOC_PWR_STATE, OCM_BANK2, 18, 1)
118 FIELD(LOC_PWR_STATE, OCM_BANK1, 17, 1)
119 FIELD(LOC_PWR_STATE, OCM_BANK0, 16, 1)
120 FIELD(LOC_PWR_STATE, TCM1B, 15, 1)
121 FIELD(LOC_PWR_STATE, TCM1A, 14, 1)
122 FIELD(LOC_PWR_STATE, TCM0B, 13, 1)
123 FIELD(LOC_PWR_STATE, TCM0A, 12, 1)
124 FIELD(LOC_PWR_STATE, R5_1, 11, 1)
125 FIELD(LOC_PWR_STATE, R5_0, 10, 1)
126 FIELD(LOC_PWR_STATE, L2_BANK0, 7, 1)
127 FIELD(LOC_PWR_STATE, ACPU1, 1, 1)
128 FIELD(LOC_PWR_STATE, ACPU0, 0, 1)
129REG32(LOC_AUX_PWR_STATE, 0x104)
130 FIELD(LOC_AUX_PWR_STATE, ACPU1_EMUL, 29, 1)
131 FIELD(LOC_AUX_PWR_STATE, ACPU0_EMUL, 28, 1)
132 FIELD(LOC_AUX_PWR_STATE, RPU_EMUL, 27, 1)
133 FIELD(LOC_AUX_PWR_STATE, OCM_BANK3, 19, 1)
134 FIELD(LOC_AUX_PWR_STATE, OCM_BANK2, 18, 1)
135 FIELD(LOC_AUX_PWR_STATE, OCM_BANK1, 17, 1)
136 FIELD(LOC_AUX_PWR_STATE, OCM_BANK0, 16, 1)
137 FIELD(LOC_AUX_PWR_STATE, TCM1B, 15, 1)
138 FIELD(LOC_AUX_PWR_STATE, TCM1A, 14, 1)
139 FIELD(LOC_AUX_PWR_STATE, TCM0B, 13, 1)
140 FIELD(LOC_AUX_PWR_STATE, TCM0A, 12, 1)
141 FIELD(LOC_AUX_PWR_STATE, L2, 7, 1)
142REG32(LOCAL_GEN_STORAGE0, 0x300)
143REG32(LOCAL_GEN_STORAGE1, 0x304)
144REG32(LOCAL_GEN_STORAGE2, 0x308)
145REG32(LOCAL_GEN_STORAGE3, 0x30c)
146REG32(PERS_LOC_GEN_STORAGE0, 0x310)
147REG32(PERS_LOC_GEN_STORAGE1, 0x314)
148REG32(PERS_LOC_GEN_STORAGE2, 0x318)
149REG32(PERS_LOC_GEN_STORAGE3, 0x31c)
150REG32(ADDR_ERROR_STATUS, 0x320)
151 FIELD(ADDR_ERROR_STATUS, STATUS, 0, 1)
152REG32(ADDR_ERROR_INT_MASK, 0x324)
153 FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
154REG32(ADDR_ERROR_INT_EN, 0x328)
155 FIELD(ADDR_ERROR_INT_EN, EN, 0, 1)
156REG32(ADDR_ERROR_INT_DIS, 0x32c)
157 FIELD(ADDR_ERROR_INT_DIS, DIS, 0, 1)
158REG32(APU_WFI_STATUS, 0x418)
159 FIELD(APU_WFI_STATUS, L2_WFI, 16, 1)
160 FIELD(APU_WFI_STATUS, ACPU1_WFI, 1, 1)
161 FIELD(APU_WFI_STATUS, ACPU0_WFI, 0, 1)
162REG32(SCAN_CLEAR_CPU0, 0x500)
163 FIELD(SCAN_CLEAR_CPU0, PASS, 2, 1)
164 FIELD(SCAN_CLEAR_CPU0, DONE, 1, 1)
165 FIELD(SCAN_CLEAR_CPU0, TRIGGER, 0, 1)
166REG32(SCAN_CLEAR_CPU1, 0x504)
167 FIELD(SCAN_CLEAR_CPU1, PASS, 2, 1)
168 FIELD(SCAN_CLEAR_CPU1, DONE, 1, 1)
169 FIELD(SCAN_CLEAR_CPU1, TRIGGER, 0, 1)
170REG32(SCAN_CLEAR_APU, 0x508)
171 FIELD(SCAN_CLEAR_APU, PASS, 2, 1)
172 FIELD(SCAN_CLEAR_APU, DONE, 1, 1)
173 FIELD(SCAN_CLEAR_APU, TRIGGER, 0, 1)
174REG32(SCAN_CLEAR_FPD, 0x50c)
175 FIELD(SCAN_CLEAR_FPD, PASS, 2, 1)
176 FIELD(SCAN_CLEAR_FPD, DONE, 1, 1)
177 FIELD(SCAN_CLEAR_FPD, TRIGGER, 0, 1)
178REG32(MBISR_CNTRL, 0x510)
179 FIELD(MBISR_CNTRL, FPD_GROUP, 5, 1)
180 FIELD(MBISR_CNTRL, ENABLE, 0, 1)
181REG32(MBISR_STATUS, 0x514)
182 FIELD(MBISR_STATUS, PASS, 4, 1)
183 FIELD(MBISR_STATUS, DONE, 0, 1)
184REG32(MBIST_RST, 0x518)
185 FIELD(MBIST_RST, FPD, 1, 1)
186 FIELD(MBIST_RST, LPD, 0, 1)
187REG32(MBIST_PG_EN, 0x51c)
188 FIELD(MBIST_PG_EN, FPD, 1, 1)
189 FIELD(MBIST_PG_EN, LPD, 0, 1)
190REG32(MBIST_SETUP, 0x520)
191 FIELD(MBIST_SETUP, FPD, 1, 1)
192 FIELD(MBIST_SETUP, LPD, 0, 1)
193REG32(MBIST_DONE, 0x524)
194 FIELD(MBIST_DONE, FPD, 1, 1)
195 FIELD(MBIST_DONE, LPD, 0, 1)
196REG32(MBIST_GOOD, 0x528)
197 FIELD(MBIST_GOOD, FPD, 1, 1)
198 FIELD(MBIST_GOOD, LPD, 0, 1)
199REG32(PSM_GLOBAL_APB, 0x600)
200 FIELD(PSM_GLOBAL_APB, RST_N, 4, 1)
201 FIELD(PSM_GLOBAL_APB, POWER_IDLEREQ, 3, 1)
202 FIELD(PSM_GLOBAL_APB, POWER_IDLEACK, 2, 1)
203 FIELD(PSM_GLOBAL_APB, POWER_IDLE, 1, 1)
204 FIELD(PSM_GLOBAL_APB, MAINEXTEN, 0, 1)
205
206#define PSM_LOCAL_REG_R_MAX (R_PSM_GLOBAL_APB + 1)
207
208typedef struct PSM_LOCAL_REG {
209 SysBusDevice parent_obj;
210 MemoryRegion iomem;
211 qemu_irq irq_addr_error_int;
212
213 qemu_irq pwr_acpu0[4];
214 qemu_irq pwr_acpu1[4];
215 qemu_irq pwr_rpu[4];
216 qemu_irq pwr_l2;
217 qemu_irq pwr_ocm[4];
218 qemu_irq pwr_tcm_a[2];
219 qemu_irq pwr_tcm_b[2];
220 qemu_irq pwr_gem[2];
221
222 qemu_irq loc_pwr_state[32];
223 qemu_irq loc_aux_pwr_state[32];
224 qemu_irq apu_sleep[4];
225 qemu_irq apu_pwrdw_status[4];
226
227 bool has_por;
228 uint8_t apu_pwrdw_req;
229
230 uint32_t regs[PSM_LOCAL_REG_R_MAX];
231 RegisterInfo regs_info[PSM_LOCAL_REG_R_MAX];
232} PSM_LOCAL_REG;
233
234#define PROPAGATE_FIELD1(s, sreg, sf, dreg, df, irq) { \
235 unsigned int val = ARRAY_FIELD_EX32((s)->regs, sreg, sf); \
236 ARRAY_FIELD_DP32((s)->regs, dreg, df, val); \
237 qemu_set_irq(irq, val); \
238}
239
240#define PROPAGATE_FIELD(s, sreg, sf, dreg, df, irq) { \
241 unsigned int val = ARRAY_FIELD_EX32((s)->regs, sreg, sf); \
242 unsigned int i; \
243 \
244 ARRAY_FIELD_DP32((s)->regs, dreg, df, val); \
245 assert(ARRAY_SIZE(irq) == R_ ## sreg ## _ ## sf ## _LENGTH); \
246 for (i = 0; i < R_ ## sreg ## _ ## sf ## _LENGTH; i++) { \
247 qemu_set_irq(irq[i], (val >> i) & 1); \
248 } \
249}
250
251#define PROPAGATE_REG32(s, reg, irq) { \
252 unsigned int val = (s)->regs[R_ ## reg]; \
253 unsigned int i; \
254 \
255 assert(ARRAY_SIZE(irq) == sizeof((s)->regs[0]) * 8); \
256 for (i = 0; i < sizeof((s)->regs[0]) * 8; i++) { \
257 qemu_set_irq(irq[i], (val >> i) & 1); \
258 } \
259}
260
261static void update_pwr_status(PSM_LOCAL_REG *s)
262{
263 PROPAGATE_FIELD(s, ACPU0_PWR_CNTRL, PWR_GATES,
264 ACPU0_PWR_STATUS, PWR_GATES, s->pwr_acpu0);
265 PROPAGATE_FIELD(s, ACPU1_PWR_CNTRL, PWR_GATES,
266 ACPU1_PWR_STATUS, PWR_GATES, s->pwr_acpu1);
267 PROPAGATE_FIELD(s, RPU_PWR_CNTRL, PWR_GATES, RPU_PWR_STATUS, PWR_GATES,
268 s->pwr_rpu);
269
270 PROPAGATE_FIELD1(s, L2_PWR_CNTRL, BANK0, L2_PWR_STATUS, BANK0,
271 s->pwr_l2);
272
273 PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, BANK0, OCM_PWR_STATUS, BANK0,
274 s->pwr_ocm[0]);
275 PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, BANK1, OCM_PWR_STATUS, BANK1,
276 s->pwr_ocm[1]);
277 PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, BANK2, OCM_PWR_STATUS, BANK2,
278 s->pwr_ocm[2]);
279 PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, BANK3, OCM_PWR_STATUS, BANK3,
280 s->pwr_ocm[3]);
281
282 PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMA0, TCM_PWR_STATUS, TCMA0,
283 s->pwr_tcm_a[0]);
284 PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMB0, TCM_PWR_STATUS, TCMB0,
285 s->pwr_tcm_b[0]);
286 PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMA1, TCM_PWR_STATUS, TCMA1,
287 s->pwr_tcm_a[1]);
288 PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMB1, TCM_PWR_STATUS, TCMB1,
289 s->pwr_tcm_b[1]);
290 PROPAGATE_FIELD1(s, GEM_PWR_CNTRL, GEM0, GEM_PWR_STATUS, GEM0,
291 s->pwr_gem[0]);
292 PROPAGATE_FIELD1(s, GEM_PWR_CNTRL, GEM1, GEM_PWR_STATUS, GEM1,
293 s->pwr_gem[1]);
294}
295
296static void update_loc_pwr_state(PSM_LOCAL_REG *s)
297{
298 int i;
299 PROPAGATE_REG32(s, LOC_PWR_STATE, s->loc_pwr_state);
300 PROPAGATE_REG32(s, LOC_AUX_PWR_STATE, s->loc_aux_pwr_state);
301
302
303
304
305 for (i = 0; i < 4; i++) {
306 qemu_set_irq(s->apu_pwrdw_status[i],
307 !(s->regs[R_LOC_PWR_STATE] & (1 << i)));
308 }
309}
310
311static void addr_error_int_update_irq(PSM_LOCAL_REG *s)
312{
313 bool pending;
314
315 pending = s->regs[R_ADDR_ERROR_STATUS] & ~s->regs[R_ADDR_ERROR_INT_MASK];
316 qemu_set_irq(s->irq_addr_error_int, pending);
317}
318
319static void addr_error_status_postw(RegisterInfo *reg, uint64_t val64)
320{
321 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(reg->opaque);
322 addr_error_int_update_irq(s);
323}
324
325static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
326{
327 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(reg->opaque);
328 uint32_t val = val64;
329
330 s->regs[R_ADDR_ERROR_INT_MASK] &= ~val;
331 addr_error_int_update_irq(s);
332 return 0;
333}
334
335static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
336{
337 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(reg->opaque);
338 uint32_t val = val64;
339
340 s->regs[R_ADDR_ERROR_INT_MASK] |= val;
341 addr_error_int_update_irq(s);
342 return 0;
343}
344
345static void pwr_cntrl_postw(RegisterInfo *reg, uint64_t val64)
346{
347 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(reg->opaque);
348 update_pwr_status(s);
349}
350
351static void loc_pwr_state_postw(RegisterInfo *reg, uint64_t val64)
352{
353 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(reg->opaque);
354 update_loc_pwr_state(s);
355}
356
357static const RegisterAccessInfo psm_local_reg_regs_info[] = {
358 { .name = "ACPU0_PWR_CNTRL", .addr = A_ACPU0_PWR_CNTRL,
359 .reset = 0xf,
360 .rsvd = 0xffffffe0,
361 .ro = 0xffffffe0,
362 .post_write = pwr_cntrl_postw,
363 },{ .name = "ACPU0_PWR_STATUS", .addr = A_ACPU0_PWR_STATUS,
364 .reset = 0xf,
365 .rsvd = 0xfffffff0,
366 .ro = 0xffffffff,
367 },{ .name = "ACPU1_PWR_CNTRL", .addr = A_ACPU1_PWR_CNTRL,
368 .reset = 0xf,
369 .rsvd = 0xffffffe0,
370 .ro = 0xffffffe0,
371 .post_write = pwr_cntrl_postw,
372 },{ .name = "ACPU1_PWR_STATUS", .addr = A_ACPU1_PWR_STATUS,
373 .reset = 0xf,
374 .rsvd = 0xfffffff0,
375 .ro = 0xffffffff,
376 .post_write = pwr_cntrl_postw,
377 },{ .name = "RPU_PWR_CNTRL", .addr = A_RPU_PWR_CNTRL,
378 .reset = 0xf,
379 .rsvd = 0xffffffe0,
380 .ro = 0xffffffe0,
381 .post_write = pwr_cntrl_postw,
382 },{ .name = "RPU_PWR_STATUS", .addr = A_RPU_PWR_STATUS,
383 .reset = 0xf,
384 .rsvd = 0xfffffff0,
385 .ro = 0xffffffff,
386 },{ .name = "L2_PWR_CNTRL", .addr = A_L2_PWR_CNTRL,
387 .reset = 0x1,
388 .rsvd = 0xfffffffe,
389 .ro = 0xfffffffe,
390 .post_write = pwr_cntrl_postw,
391 },{ .name = "L2_CE_CNTRL", .addr = A_L2_CE_CNTRL,
392 .reset = 0x1,
393 .rsvd = 0xfffffffe,
394 .ro = 0xfffffffe,
395 },{ .name = "L2_PWR_STATUS", .addr = A_L2_PWR_STATUS,
396 .reset = 0x1,
397 .rsvd = 0xfffffffe,
398 .ro = 0xffffffff,
399 },{ .name = "OCM_PWR_CNTRL", .addr = A_OCM_PWR_CNTRL,
400 .reset = 0x1010101,
401 .rsvd = 0xfefefefe,
402 .ro = 0xfefefefe,
403 .post_write = pwr_cntrl_postw,
404 },{ .name = "OCM_CE_CNTRL", .addr = A_OCM_CE_CNTRL,
405 .reset = 0xf,
406 .rsvd = 0xfffffff0,
407 .ro = 0xfffffff0,
408 },{ .name = "OCM_PWR_STATUS", .addr = A_OCM_PWR_STATUS,
409 .reset = 0x1010101,
410 .rsvd = 0xfefefefe,
411 .ro = 0xffffffff,
412 },{ .name = "TCM_PWR_CNTRL", .addr = A_TCM_PWR_CNTRL,
413 .reset = 0x1010101,
414 .rsvd = 0xfefefefe,
415 .ro = 0xfefefefe,
416 .post_write = pwr_cntrl_postw,
417 },{ .name = "TCM_CE_CNTRL", .addr = A_TCM_CE_CNTRL,
418 .reset = 0xf,
419 .rsvd = 0xfffffff0,
420 .ro = 0xfffffff0,
421 },{ .name = "TCM_PWR_STATUS", .addr = A_TCM_PWR_STATUS,
422 .reset = 0x1010101,
423 .rsvd = 0xfefefefe,
424 .ro = 0xffffffff,
425 },{ .name = "GEM_PWR_CNTRL", .addr = A_GEM_PWR_CNTRL,
426 .reset = 0x101,
427 .rsvd = 0xfffffefe,
428 .ro = 0xfffffefe,
429 .post_write = pwr_cntrl_postw,
430 },{ .name = "GEM_CE_CNTRL", .addr = A_GEM_CE_CNTRL,
431 .reset = 0x3,
432 .rsvd = 0xfffffffc,
433 .ro = 0xfffffffc,
434 },{ .name = "GEM_PWR_STATUS", .addr = A_GEM_PWR_STATUS,
435 .reset = 0x101,
436 .rsvd = 0xfffffefe,
437 .ro = 0xffffffff,
438 },{ .name = "DOMAIN_ISO_CNTRL", .addr = A_DOMAIN_ISO_CNTRL,
439 .reset = 0x1f,
440 .rsvd = 0xfffffff0,
441 .ro = 0xfffffff0,
442 },{ .name = "LOC_PWR_STATE", .addr = A_LOC_PWR_STATE,
443 .reset = 0xfffd87,
444 .rsvd = 0xff80037c,
445 .post_write = loc_pwr_state_postw,
446 },{ .name = "LOC_AUX_PWR_STATE", .addr = A_LOC_AUX_PWR_STATE,
447 .reset = 0xff080,
448 .rsvd = 0xc7f00f7f,
449 .ro = 0xc7f00f7f,
450 .post_write = loc_pwr_state_postw,
451 },{ .name = "LOCAL_GEN_STORAGE0", .addr = A_LOCAL_GEN_STORAGE0,
452 },{ .name = "LOCAL_GEN_STORAGE1", .addr = A_LOCAL_GEN_STORAGE1,
453 },{ .name = "LOCAL_GEN_STORAGE2", .addr = A_LOCAL_GEN_STORAGE2,
454 },{ .name = "LOCAL_GEN_STORAGE3", .addr = A_LOCAL_GEN_STORAGE3,
455 },{ .name = "PERS_LOC_GEN_STORAGE0", .addr = A_PERS_LOC_GEN_STORAGE0,
456 },{ .name = "PERS_LOC_GEN_STORAGE1", .addr = A_PERS_LOC_GEN_STORAGE1,
457 },{ .name = "PERS_LOC_GEN_STORAGE2", .addr = A_PERS_LOC_GEN_STORAGE2,
458 },{ .name = "PERS_LOC_GEN_STORAGE3", .addr = A_PERS_LOC_GEN_STORAGE3,
459 },{ .name = "ADDR_ERROR_STATUS", .addr = A_ADDR_ERROR_STATUS,
460 .w1c = 0x1,
461 .post_write = addr_error_status_postw,
462 },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
463 .reset = 0x1,
464 .ro = 0x1,
465 },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
466 .pre_write = addr_error_int_en_prew,
467 },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
468 .pre_write = addr_error_int_dis_prew,
469 },{ .name = "APU_WFI_STATUS", .addr = A_APU_WFI_STATUS,
470 .reset = 0x10003,
471 .rsvd = 0xfffefffc,
472 .ro = 0xffffffff,
473 },{ .name = "SCAN_CLEAR_CPU0", .addr = A_SCAN_CLEAR_CPU0,
474 .rsvd = 0xfffffff8,
475 .ro = 0xfffffffe,
476 .reset = R_SCAN_CLEAR_CPU0_PASS_MASK | R_SCAN_CLEAR_CPU0_DONE_MASK,
477 },{ .name = "SCAN_CLEAR_CPU1", .addr = A_SCAN_CLEAR_CPU1,
478 .rsvd = 0xfffffff8,
479 .ro = 0xfffffffe,
480 .reset = R_SCAN_CLEAR_CPU1_PASS_MASK | R_SCAN_CLEAR_CPU1_DONE_MASK,
481 },{ .name = "SCAN_CLEAR_APU", .addr = A_SCAN_CLEAR_APU,
482 .rsvd = 0xfffffff8,
483 .ro = 0xfffffffe,
484 .reset = R_SCAN_CLEAR_APU_PASS_MASK | R_SCAN_CLEAR_APU_DONE_MASK,
485 },{ .name = "SCAN_CLEAR_FPD", .addr = A_SCAN_CLEAR_FPD,
486 .rsvd = 0xfffffff8,
487 .ro = 0xfffffffe,
488 .reset = R_SCAN_CLEAR_FPD_PASS_MASK | R_SCAN_CLEAR_FPD_DONE_MASK,
489 },{ .name = "MBISR_CNTRL", .addr = A_MBISR_CNTRL,
490 .rsvd = 0xffffffde,
491 .ro = 0xffffffde,
492 },{ .name = "MBISR_STATUS", .addr = A_MBISR_STATUS,
493 .rsvd = 0xffffffee,
494 .ro = 0xffffffff,
495 .reset = R_MBISR_STATUS_PASS_MASK | R_MBISR_STATUS_DONE_MASK,
496 },{ .name = "MBIST_RST", .addr = A_MBIST_RST,
497 },{ .name = "MBIST_PG_EN", .addr = A_MBIST_PG_EN,
498 },{ .name = "MBIST_SETUP", .addr = A_MBIST_SETUP,
499 },{ .name = "MBIST_DONE", .addr = A_MBIST_DONE,
500 .ro = 0x3,
501 },{ .name = "MBIST_GOOD", .addr = A_MBIST_GOOD,
502 .ro = 0x3,
503 },{ .name = "PSM_GLOBAL_APB", .addr = A_PSM_GLOBAL_APB,
504 .reset = 0x16,
505 .rsvd = 0xffffffe0,
506 .ro = 0x6,
507 }
508};
509
510static void psm_local_reg_reset(DeviceState *dev)
511{
512 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(dev);
513 unsigned int i;
514
515 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
516
517
518
519 switch (i) {
520 case R_LOCAL_GEN_STORAGE0...R_LOCAL_GEN_STORAGE3:
521 case R_ADDR_ERROR_STATUS...R_ADDR_ERROR_INT_DIS:
522 if (!s->has_por) {
523 register_reset(&s->regs_info[i]);
524 }
525 break;
526 default:
527 register_reset(&s->regs_info[i]);
528 break;
529 }
530 }
531
532 addr_error_int_update_irq(s);
533 update_pwr_status(s);
534 update_loc_pwr_state(s);
535
536 s->has_por = true;
537}
538
539static const MemoryRegionOps psm_local_reg_ops = {
540 .read = register_read_memory,
541 .write = register_write_memory,
542 .endianness = DEVICE_LITTLE_ENDIAN,
543 .valid = {
544 .min_access_size = 4,
545 .max_access_size = 4,
546 },
547};
548
549static void update_apu_sleep(PSM_LOCAL_REG *s)
550{
551 int i;
552
553 for (i = 0; i < 4; i++) {
554 if ((s->apu_pwrdw_req &
555 s->regs[R_APU_WFI_STATUS]) &
556 (1 << i)) {
557 qemu_irq_pulse(s->apu_sleep[i]);
558 }
559 }
560}
561
562static void apu_wfi_h(void *opaque, int n, int level)
563{
564 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(opaque);
565
566 switch (n) {
567 case 0:
568 ARRAY_FIELD_DP32(s->regs, APU_WFI_STATUS, ACPU0_WFI, !!level);
569 break;
570 case 1:
571 ARRAY_FIELD_DP32(s->regs, APU_WFI_STATUS, ACPU1_WFI, !!level);
572 break;
573 case 4:
574 ARRAY_FIELD_DP32(s->regs, APU_WFI_STATUS, L2_WFI, !!level);
575 break;
576 default:
577 g_assert_not_reached();
578 }
579
580 update_apu_sleep(s);
581}
582
583static void apu_pwrdw_h(void *opaque, int n, int level)
584{
585 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(opaque);
586
587 s->apu_pwrdw_req &= ~(1 << n);
588 s->apu_pwrdw_req |= (level << n);
589
590 update_apu_sleep(s);
591}
592
593static void psm_local_reg_init(Object *obj)
594{
595 PSM_LOCAL_REG *s = XILINX_PSM_LOCAL_REG(obj);
596 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
597 RegisterInfoArray *reg_array;
598
599 memory_region_init(&s->iomem, obj, TYPE_XILINX_PSM_LOCAL_REG,
600 PSM_LOCAL_REG_R_MAX * 4);
601 reg_array =
602 register_init_block32(DEVICE(obj), psm_local_reg_regs_info,
603 ARRAY_SIZE(psm_local_reg_regs_info),
604 s->regs_info, s->regs,
605 &psm_local_reg_ops,
606 XILINX_PSM_LOCAL_REG_ERR_DEBUG,
607 PSM_LOCAL_REG_R_MAX * 4);
608 memory_region_add_subregion(&s->iomem,
609 0x0,
610 ®_array->mem);
611 sysbus_init_mmio(sbd, &s->iomem);
612 sysbus_init_irq(sbd, &s->irq_addr_error_int);
613
614 qdev_init_gpio_out_named(DEVICE(obj), s->pwr_acpu0, "pwr-acpu0", 4);
615 qdev_init_gpio_out_named(DEVICE(obj), s->pwr_acpu1, "pwr-acpu1", 4);
616 qdev_init_gpio_out_named(DEVICE(obj), s->pwr_rpu, "pwr-rpu", 4);
617
618 qdev_init_gpio_out_named(DEVICE(obj), &s->pwr_l2, "pwr-l2", 1);
619 qdev_init_gpio_out_named(DEVICE(obj), s->pwr_ocm, "pwr-ocm", 4);
620
621 qdev_init_gpio_out_named(DEVICE(obj), &s->pwr_tcm_a[0], "pwr-tcm-a0", 1);
622 qdev_init_gpio_out_named(DEVICE(obj), &s->pwr_tcm_b[0], "pwr-tcm-b0", 1);
623 qdev_init_gpio_out_named(DEVICE(obj), &s->pwr_tcm_a[1], "pwr-tcm-a1", 1);
624 qdev_init_gpio_out_named(DEVICE(obj), &s->pwr_tcm_b[1], "pwr-tcm-b1", 1);
625
626 qdev_init_gpio_out_named(DEVICE(obj), s->pwr_gem, "pwr-gem", 2);
627
628 qdev_init_gpio_out_named(DEVICE(obj), s->loc_pwr_state,
629 "loc-pwr-state", 32);
630 qdev_init_gpio_out_named(DEVICE(obj), s->loc_aux_pwr_state,
631 "loc-aux-pwr-state", 32);
632
633 qdev_init_gpio_in_named(DEVICE(obj), apu_wfi_h, "apu-wfi", 5);
634 qdev_init_gpio_in_named(DEVICE(obj), apu_pwrdw_h, "apu-pwrdw", 4);
635 qdev_init_gpio_out_named(DEVICE(obj), s->apu_sleep, "apu-sleep", 4);
636 qdev_init_gpio_out_named(DEVICE(obj), s->apu_pwrdw_status,
637 "apu-pwrdw-status", 4);
638}
639
640static const VMStateDescription vmstate_psm_local_reg = {
641 .name = TYPE_XILINX_PSM_LOCAL_REG,
642 .version_id = 1,
643 .minimum_version_id = 1,
644 .fields = (VMStateField[]) {
645 VMSTATE_UINT32_ARRAY(regs, PSM_LOCAL_REG, PSM_LOCAL_REG_R_MAX),
646 VMSTATE_END_OF_LIST(),
647 }
648};
649
650static const FDTGenericGPIOSet psm_local_reg_gpios[] = {
651 {
652 .names = &fdt_generic_gpio_name_set_gpio,
653 .gpios = (FDTGenericGPIOConnection[]) {
654 { .name = "pwr-acpu0", .fdt_index = 0, .range = 4 },
655 { .name = "pwr-acpu1", .fdt_index = 4, .range = 4 },
656 { .name = "pwr-rpu", .fdt_index = 8, .range = 4 },
657 { .name = "pwr-l2", .fdt_index = 12, .range = 1 },
658 { .name = "pwr-ocm", .fdt_index = 13, .range = 4 },
659 { .name = "pwr-tcm-a0", .fdt_index = 17, .range = 1 },
660 { .name = "pwr-tcm-b0", .fdt_index = 18, .range = 1 },
661 { .name = "pwr-tcm-a1", .fdt_index = 19, .range = 1 },
662 { .name = "pwr-tcm-b1", .fdt_index = 20, .range = 1 },
663
664 { .name = "pwr-gem", .fdt_index = 21, .range = 2 },
665 { .name = "apu-wfi", .fdt_index = 24, .range = 5 },
666 { .name = "loc-pwr-state", .fdt_index = 32, .range = 32 },
667 { .name = "loc-aux-pwr-state", .fdt_index = 64, .range = 32 },
668 { .name = "apu-sleep", .fdt_index = 96, .range = 4 },
669 { .name = "apu-pwrdw-status", .fdt_index = 100, .range = 4 },
670 { },
671 },
672 },
673 { },
674};
675
676static const FDTGenericGPIOSet psm_local_reg_client_gpios[] = {
677 {
678 .names = &fdt_generic_gpio_name_set_gpio,
679 .gpios = (FDTGenericGPIOConnection[]) {
680 { .name = "apu-pwrdw", .fdt_index = 0, .range = 4 },
681 { },
682 },
683 },
684 { },
685};
686
687static void psm_local_reg_class_init(ObjectClass *klass, void *data)
688{
689 DeviceClass *dc = DEVICE_CLASS(klass);
690 FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
691
692 dc->reset = psm_local_reg_reset;
693 dc->vmsd = &vmstate_psm_local_reg;
694 fggc->controller_gpios = psm_local_reg_gpios;
695 fggc->client_gpios = psm_local_reg_client_gpios;
696}
697
698static const TypeInfo psm_local_reg_info = {
699 .name = TYPE_XILINX_PSM_LOCAL_REG,
700 .parent = TYPE_SYS_BUS_DEVICE,
701 .instance_size = sizeof(PSM_LOCAL_REG),
702 .class_init = psm_local_reg_class_init,
703 .instance_init = psm_local_reg_init,
704 .interfaces = (InterfaceInfo[]) {
705 { TYPE_FDT_GENERIC_GPIO },
706 { }
707 },
708};
709
710static void psm_local_reg_register_types(void)
711{
712 type_register_static(&psm_local_reg_info);
713}
714
715type_init(psm_local_reg_register_types)
716