1
2
3
4
5
6
7
8
9
10
11
12#include "qemu/osdep.h"
13#include "qemu/log.h"
14#include "qapi/error.h"
15#include "trace.h"
16#include "hw/sysbus.h"
17#include "hw/registerfields.h"
18#include "hw/misc/iotkit-secctl.h"
19
20
21REG32(SECRESPCFG, 0x10)
22REG32(NSCCFG, 0x14)
23REG32(SECMPCINTSTATUS, 0x1c)
24REG32(SECPPCINTSTAT, 0x20)
25REG32(SECPPCINTCLR, 0x24)
26REG32(SECPPCINTEN, 0x28)
27REG32(SECMSCINTSTAT, 0x30)
28REG32(SECMSCINTCLR, 0x34)
29REG32(SECMSCINTEN, 0x38)
30REG32(BRGINTSTAT, 0x40)
31REG32(BRGINTCLR, 0x44)
32REG32(BRGINTEN, 0x48)
33REG32(AHBNSPPC0, 0x50)
34REG32(AHBNSPPCEXP0, 0x60)
35REG32(AHBNSPPCEXP1, 0x64)
36REG32(AHBNSPPCEXP2, 0x68)
37REG32(AHBNSPPCEXP3, 0x6c)
38REG32(APBNSPPC0, 0x70)
39REG32(APBNSPPC1, 0x74)
40REG32(APBNSPPCEXP0, 0x80)
41REG32(APBNSPPCEXP1, 0x84)
42REG32(APBNSPPCEXP2, 0x88)
43REG32(APBNSPPCEXP3, 0x8c)
44REG32(AHBSPPPC0, 0x90)
45REG32(AHBSPPPCEXP0, 0xa0)
46REG32(AHBSPPPCEXP1, 0xa4)
47REG32(AHBSPPPCEXP2, 0xa8)
48REG32(AHBSPPPCEXP3, 0xac)
49REG32(APBSPPPC0, 0xb0)
50REG32(APBSPPPC1, 0xb4)
51REG32(APBSPPPCEXP0, 0xc0)
52REG32(APBSPPPCEXP1, 0xc4)
53REG32(APBSPPPCEXP2, 0xc8)
54REG32(APBSPPPCEXP3, 0xcc)
55REG32(NSMSCEXP, 0xd0)
56REG32(PID4, 0xfd0)
57REG32(PID5, 0xfd4)
58REG32(PID6, 0xfd8)
59REG32(PID7, 0xfdc)
60REG32(PID0, 0xfe0)
61REG32(PID1, 0xfe4)
62REG32(PID2, 0xfe8)
63REG32(PID3, 0xfec)
64REG32(CID0, 0xff0)
65REG32(CID1, 0xff4)
66REG32(CID2, 0xff8)
67REG32(CID3, 0xffc)
68
69
70REG32(AHBNSPPPC0, 0x90)
71REG32(AHBNSPPPCEXP0, 0xa0)
72REG32(AHBNSPPPCEXP1, 0xa4)
73REG32(AHBNSPPPCEXP2, 0xa8)
74REG32(AHBNSPPPCEXP3, 0xac)
75REG32(APBNSPPPC0, 0xb0)
76REG32(APBNSPPPC1, 0xb4)
77REG32(APBNSPPPCEXP0, 0xc0)
78REG32(APBNSPPPCEXP1, 0xc4)
79REG32(APBNSPPPCEXP2, 0xc8)
80REG32(APBNSPPPCEXP3, 0xcc)
81
82
83static const uint8_t iotkit_secctl_s_idregs[] = {
84 0x04, 0x00, 0x00, 0x00,
85 0x52, 0xb8, 0x0b, 0x00,
86 0x0d, 0xf0, 0x05, 0xb1,
87};
88
89static const uint8_t iotkit_secctl_ns_idregs[] = {
90 0x04, 0x00, 0x00, 0x00,
91 0x53, 0xb8, 0x0b, 0x00,
92 0x0d, 0xf0, 0x05, 0xb1,
93};
94
95
96
97
98
99
100
101static inline int offset_to_ppc_idx(uint32_t offset)
102{
103 return extract32(offset, 2, 2);
104}
105
106typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
107
108static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
109{
110 int i;
111
112 for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
113 fn(&s->apb[i]);
114 }
115 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
116 fn(&s->apbexp[i]);
117 }
118 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
119 fn(&s->ahbexp[i]);
120 }
121}
122
123static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
124 uint64_t *pdata,
125 unsigned size, MemTxAttrs attrs)
126{
127 uint64_t r;
128 uint32_t offset = addr & ~0x3;
129 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
130
131 switch (offset) {
132 case A_AHBNSPPC0:
133 case A_AHBSPPPC0:
134 r = 0;
135 break;
136 case A_SECRESPCFG:
137 r = s->secrespcfg;
138 break;
139 case A_NSCCFG:
140 r = s->nsccfg;
141 break;
142 case A_SECMPCINTSTATUS:
143 r = s->mpcintstatus;
144 break;
145 case A_SECPPCINTSTAT:
146 r = s->secppcintstat;
147 break;
148 case A_SECPPCINTEN:
149 r = s->secppcinten;
150 break;
151 case A_BRGINTSTAT:
152
153
154
155 r = 0;
156 break;
157 case A_BRGINTEN:
158 r = s->brginten;
159 break;
160 case A_AHBNSPPCEXP0:
161 case A_AHBNSPPCEXP1:
162 case A_AHBNSPPCEXP2:
163 case A_AHBNSPPCEXP3:
164 r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
165 break;
166 case A_APBNSPPC0:
167 case A_APBNSPPC1:
168 r = s->apb[offset_to_ppc_idx(offset)].ns;
169 break;
170 case A_APBNSPPCEXP0:
171 case A_APBNSPPCEXP1:
172 case A_APBNSPPCEXP2:
173 case A_APBNSPPCEXP3:
174 r = s->apbexp[offset_to_ppc_idx(offset)].ns;
175 break;
176 case A_AHBSPPPCEXP0:
177 case A_AHBSPPPCEXP1:
178 case A_AHBSPPPCEXP2:
179 case A_AHBSPPPCEXP3:
180 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
181 break;
182 case A_APBSPPPC0:
183 case A_APBSPPPC1:
184 r = s->apb[offset_to_ppc_idx(offset)].sp;
185 break;
186 case A_APBSPPPCEXP0:
187 case A_APBSPPPCEXP1:
188 case A_APBSPPPCEXP2:
189 case A_APBSPPPCEXP3:
190 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
191 break;
192 case A_SECMSCINTSTAT:
193 r = s->secmscintstat;
194 break;
195 case A_SECMSCINTEN:
196 r = s->secmscinten;
197 break;
198 case A_NSMSCEXP:
199 r = s->nsmscexp;
200 break;
201 case A_PID4:
202 case A_PID5:
203 case A_PID6:
204 case A_PID7:
205 case A_PID0:
206 case A_PID1:
207 case A_PID2:
208 case A_PID3:
209 case A_CID0:
210 case A_CID1:
211 case A_CID2:
212 case A_CID3:
213 r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
214 break;
215 case A_SECPPCINTCLR:
216 case A_SECMSCINTCLR:
217 case A_BRGINTCLR:
218 qemu_log_mask(LOG_GUEST_ERROR,
219 "IotKit SecCtl S block read: write-only offset 0x%x\n",
220 offset);
221 r = 0;
222 break;
223 default:
224 qemu_log_mask(LOG_GUEST_ERROR,
225 "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
226 r = 0;
227 break;
228 }
229
230 if (size != 4) {
231
232
233
234 r = extract32(r, (addr & 3) * 8, size * 8);
235 }
236
237 trace_iotkit_secctl_s_read(offset, r, size);
238 *pdata = r;
239 return MEMTX_OK;
240}
241
242static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
243{
244 int i;
245
246 for (i = 0; i < ppc->numports; i++) {
247 bool v;
248
249 if (extract32(ppc->ns, i, 1)) {
250 v = extract32(ppc->nsp, i, 1);
251 } else {
252 v = extract32(ppc->sp, i, 1);
253 }
254 qemu_set_irq(ppc->ap[i], v);
255 }
256}
257
258static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
259{
260 int i;
261
262 ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
263 for (i = 0; i < ppc->numports; i++) {
264 qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
265 }
266 iotkit_secctl_update_ppc_ap(ppc);
267}
268
269static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
270{
271 ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
272 iotkit_secctl_update_ppc_ap(ppc);
273}
274
275static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
276{
277 ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
278 iotkit_secctl_update_ppc_ap(ppc);
279}
280
281static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
282{
283 uint32_t value = ppc->parent->secppcintstat;
284
285 qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
286}
287
288static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
289{
290 uint32_t value = ppc->parent->secppcinten;
291
292 qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
293}
294
295static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
296{
297 int i;
298
299 for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
300 qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
301 }
302}
303
304static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
305{
306
307 bool level = s->secmscintstat & s->secmscinten;
308
309 qemu_set_irq(s->msc_irq, level);
310}
311
312static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
313 uint64_t value,
314 unsigned size, MemTxAttrs attrs)
315{
316 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
317 uint32_t offset = addr;
318 IoTKitSecCtlPPC *ppc;
319
320 trace_iotkit_secctl_s_write(offset, value, size);
321
322 if (size != 4) {
323
324 qemu_log_mask(LOG_GUEST_ERROR,
325 "IotKit SecCtl S block write: bad size, ignored\n");
326 return MEMTX_OK;
327 }
328
329 switch (offset) {
330 case A_NSCCFG:
331 s->nsccfg = value & 3;
332 qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
333 break;
334 case A_SECRESPCFG:
335 value &= 1;
336 s->secrespcfg = value;
337 qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
338 break;
339 case A_SECPPCINTCLR:
340 value &= 0x00f000f3;
341 foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
342 break;
343 case A_SECPPCINTEN:
344 s->secppcinten = value & 0x00f000f3;
345 foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
346 break;
347 case A_BRGINTCLR:
348 break;
349 case A_BRGINTEN:
350 s->brginten = value & 0xffff0000;
351 break;
352 case A_AHBNSPPCEXP0:
353 case A_AHBNSPPCEXP1:
354 case A_AHBNSPPCEXP2:
355 case A_AHBNSPPCEXP3:
356 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
357 iotkit_secctl_ppc_ns_write(ppc, value);
358 break;
359 case A_APBNSPPC0:
360 case A_APBNSPPC1:
361 ppc = &s->apb[offset_to_ppc_idx(offset)];
362 iotkit_secctl_ppc_ns_write(ppc, value);
363 break;
364 case A_APBNSPPCEXP0:
365 case A_APBNSPPCEXP1:
366 case A_APBNSPPCEXP2:
367 case A_APBNSPPCEXP3:
368 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
369 iotkit_secctl_ppc_ns_write(ppc, value);
370 break;
371 case A_AHBSPPPCEXP0:
372 case A_AHBSPPPCEXP1:
373 case A_AHBSPPPCEXP2:
374 case A_AHBSPPPCEXP3:
375 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
376 iotkit_secctl_ppc_sp_write(ppc, value);
377 break;
378 case A_APBSPPPC0:
379 case A_APBSPPPC1:
380 ppc = &s->apb[offset_to_ppc_idx(offset)];
381 iotkit_secctl_ppc_sp_write(ppc, value);
382 break;
383 case A_APBSPPPCEXP0:
384 case A_APBSPPPCEXP1:
385 case A_APBSPPPCEXP2:
386 case A_APBSPPPCEXP3:
387 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
388 iotkit_secctl_ppc_sp_write(ppc, value);
389 break;
390 case A_SECMSCINTCLR:
391 iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
392 break;
393 case A_SECMSCINTEN:
394 s->secmscinten = value;
395 iotkit_secctl_update_msc_irq(s);
396 break;
397 case A_NSMSCEXP:
398 s->nsmscexp = value;
399 iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
400 break;
401 case A_SECMPCINTSTATUS:
402 case A_SECPPCINTSTAT:
403 case A_SECMSCINTSTAT:
404 case A_BRGINTSTAT:
405 case A_AHBNSPPC0:
406 case A_AHBSPPPC0:
407 case A_PID4:
408 case A_PID5:
409 case A_PID6:
410 case A_PID7:
411 case A_PID0:
412 case A_PID1:
413 case A_PID2:
414 case A_PID3:
415 case A_CID0:
416 case A_CID1:
417 case A_CID2:
418 case A_CID3:
419 qemu_log_mask(LOG_GUEST_ERROR,
420 "IoTKit SecCtl S block write: "
421 "read-only offset 0x%x\n", offset);
422 break;
423 default:
424 qemu_log_mask(LOG_GUEST_ERROR,
425 "IotKit SecCtl S block write: bad offset 0x%x\n",
426 offset);
427 break;
428 }
429
430 return MEMTX_OK;
431}
432
433static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
434 uint64_t *pdata,
435 unsigned size, MemTxAttrs attrs)
436{
437 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
438 uint64_t r;
439 uint32_t offset = addr & ~0x3;
440
441 switch (offset) {
442 case A_AHBNSPPPC0:
443 r = 0;
444 break;
445 case A_AHBNSPPPCEXP0:
446 case A_AHBNSPPPCEXP1:
447 case A_AHBNSPPPCEXP2:
448 case A_AHBNSPPPCEXP3:
449 r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
450 break;
451 case A_APBNSPPPC0:
452 case A_APBNSPPPC1:
453 r = s->apb[offset_to_ppc_idx(offset)].nsp;
454 break;
455 case A_APBNSPPPCEXP0:
456 case A_APBNSPPPCEXP1:
457 case A_APBNSPPPCEXP2:
458 case A_APBNSPPPCEXP3:
459 r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
460 break;
461 case A_PID4:
462 case A_PID5:
463 case A_PID6:
464 case A_PID7:
465 case A_PID0:
466 case A_PID1:
467 case A_PID2:
468 case A_PID3:
469 case A_CID0:
470 case A_CID1:
471 case A_CID2:
472 case A_CID3:
473 r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
474 break;
475 default:
476 qemu_log_mask(LOG_GUEST_ERROR,
477 "IotKit SecCtl NS block write: bad offset 0x%x\n",
478 offset);
479 r = 0;
480 break;
481 }
482
483 if (size != 4) {
484
485
486
487 r = extract32(r, (addr & 3) * 8, size * 8);
488 }
489
490 trace_iotkit_secctl_ns_read(offset, r, size);
491 *pdata = r;
492 return MEMTX_OK;
493}
494
495static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
496 uint64_t value,
497 unsigned size, MemTxAttrs attrs)
498{
499 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
500 uint32_t offset = addr;
501 IoTKitSecCtlPPC *ppc;
502
503 trace_iotkit_secctl_ns_write(offset, value, size);
504
505 if (size != 4) {
506
507 qemu_log_mask(LOG_GUEST_ERROR,
508 "IotKit SecCtl NS block write: bad size, ignored\n");
509 return MEMTX_OK;
510 }
511
512 switch (offset) {
513 case A_AHBNSPPPCEXP0:
514 case A_AHBNSPPPCEXP1:
515 case A_AHBNSPPPCEXP2:
516 case A_AHBNSPPPCEXP3:
517 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
518 iotkit_secctl_ppc_nsp_write(ppc, value);
519 break;
520 case A_APBNSPPPC0:
521 case A_APBNSPPPC1:
522 ppc = &s->apb[offset_to_ppc_idx(offset)];
523 iotkit_secctl_ppc_nsp_write(ppc, value);
524 break;
525 case A_APBNSPPPCEXP0:
526 case A_APBNSPPPCEXP1:
527 case A_APBNSPPPCEXP2:
528 case A_APBNSPPPCEXP3:
529 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
530 iotkit_secctl_ppc_nsp_write(ppc, value);
531 break;
532 case A_AHBNSPPPC0:
533 case A_PID4:
534 case A_PID5:
535 case A_PID6:
536 case A_PID7:
537 case A_PID0:
538 case A_PID1:
539 case A_PID2:
540 case A_PID3:
541 case A_CID0:
542 case A_CID1:
543 case A_CID2:
544 case A_CID3:
545 qemu_log_mask(LOG_GUEST_ERROR,
546 "IoTKit SecCtl NS block write: "
547 "read-only offset 0x%x\n", offset);
548 break;
549 default:
550 qemu_log_mask(LOG_GUEST_ERROR,
551 "IotKit SecCtl NS block write: bad offset 0x%x\n",
552 offset);
553 break;
554 }
555
556 return MEMTX_OK;
557}
558
559static const MemoryRegionOps iotkit_secctl_s_ops = {
560 .read_with_attrs = iotkit_secctl_s_read,
561 .write_with_attrs = iotkit_secctl_s_write,
562 .endianness = DEVICE_LITTLE_ENDIAN,
563 .valid.min_access_size = 1,
564 .valid.max_access_size = 4,
565 .impl.min_access_size = 1,
566 .impl.max_access_size = 4,
567};
568
569static const MemoryRegionOps iotkit_secctl_ns_ops = {
570 .read_with_attrs = iotkit_secctl_ns_read,
571 .write_with_attrs = iotkit_secctl_ns_write,
572 .endianness = DEVICE_LITTLE_ENDIAN,
573 .valid.min_access_size = 1,
574 .valid.max_access_size = 4,
575 .impl.min_access_size = 1,
576 .impl.max_access_size = 4,
577};
578
579static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
580{
581 ppc->ns = 0;
582 ppc->sp = 0;
583 ppc->nsp = 0;
584}
585
586static void iotkit_secctl_reset(DeviceState *dev)
587{
588 IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
589
590 s->secppcintstat = 0;
591 s->secppcinten = 0;
592 s->secrespcfg = 0;
593 s->nsccfg = 0;
594 s->brginten = 0;
595
596 foreach_ppc(s, iotkit_secctl_reset_ppc);
597}
598
599static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
600{
601 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
602
603 s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
604}
605
606static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
607{
608 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
609
610 s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
611}
612
613static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
614{
615 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
616
617 s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
618 iotkit_secctl_update_msc_irq(s);
619}
620
621static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
622{
623 IoTKitSecCtlPPC *ppc = opaque;
624 IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
625 int irqbit = ppc->irq_bit_offset + n;
626
627 s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
628}
629
630static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
631 IoTKitSecCtlPPC *ppc,
632 const char *name,
633 int numports,
634 int irq_bit_offset)
635{
636 char *gpioname;
637 DeviceState *dev = DEVICE(s);
638
639 ppc->numports = numports;
640 ppc->irq_bit_offset = irq_bit_offset;
641 ppc->parent = s;
642
643 gpioname = g_strdup_printf("%s_nonsec", name);
644 qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
645 g_free(gpioname);
646 gpioname = g_strdup_printf("%s_ap", name);
647 qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
648 g_free(gpioname);
649 gpioname = g_strdup_printf("%s_irq_enable", name);
650 qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
651 g_free(gpioname);
652 gpioname = g_strdup_printf("%s_irq_clear", name);
653 qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
654 g_free(gpioname);
655 gpioname = g_strdup_printf("%s_irq_status", name);
656 qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
657 ppc, gpioname, 1);
658 g_free(gpioname);
659}
660
661static void iotkit_secctl_init(Object *obj)
662{
663 IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
664 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
665 DeviceState *dev = DEVICE(obj);
666 int i;
667
668 iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
669 IOTS_APB_PPC0_NUM_PORTS, 0);
670 iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
671 IOTS_APB_PPC1_NUM_PORTS, 1);
672
673 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
674 IoTKitSecCtlPPC *ppc = &s->apbexp[i];
675 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
676 iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
677 g_free(ppcname);
678 }
679 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
680 IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
681 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
682 iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
683 g_free(ppcname);
684 }
685
686 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
687 qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
688
689 qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
690 IOTS_NUM_MPC);
691 qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
692 "mpcexp_status", IOTS_NUM_EXP_MPC);
693
694 qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
695 "mscexp_status", IOTS_NUM_EXP_MSC);
696 qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
697 IOTS_NUM_EXP_MSC);
698 qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
699 IOTS_NUM_EXP_MSC);
700 qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
701
702 memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
703 s, "iotkit-secctl-s-regs", 0x1000);
704 memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
705 s, "iotkit-secctl-ns-regs", 0x1000);
706 sysbus_init_mmio(sbd, &s->s_regs);
707 sysbus_init_mmio(sbd, &s->ns_regs);
708}
709
710static const VMStateDescription iotkit_secctl_ppc_vmstate = {
711 .name = "iotkit-secctl-ppc",
712 .version_id = 1,
713 .minimum_version_id = 1,
714 .fields = (VMStateField[]) {
715 VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
716 VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
717 VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
718 VMSTATE_END_OF_LIST()
719 }
720};
721
722static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
723 .name = "iotkit-secctl-mpcintstatus",
724 .version_id = 1,
725 .minimum_version_id = 1,
726 .fields = (VMStateField[]) {
727 VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
728 VMSTATE_END_OF_LIST()
729 }
730};
731
732static bool needed_always(void *opaque)
733{
734 return true;
735}
736
737static const VMStateDescription iotkit_secctl_msc_vmstate = {
738 .name = "iotkit-secctl/msc",
739 .version_id = 1,
740 .minimum_version_id = 1,
741 .needed = needed_always,
742 .fields = (VMStateField[]) {
743 VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
744 VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
745 VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
746 VMSTATE_END_OF_LIST()
747 }
748};
749
750static const VMStateDescription iotkit_secctl_vmstate = {
751 .name = "iotkit-secctl",
752 .version_id = 1,
753 .minimum_version_id = 1,
754 .fields = (VMStateField[]) {
755 VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
756 VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
757 VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
758 VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
759 VMSTATE_UINT32(brginten, IoTKitSecCtl),
760 VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
761 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
762 VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
763 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
764 VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
765 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
766 VMSTATE_END_OF_LIST()
767 },
768 .subsections = (const VMStateDescription*[]) {
769 &iotkit_secctl_mpcintstatus_vmstate,
770 &iotkit_secctl_msc_vmstate,
771 NULL
772 },
773};
774
775static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
776{
777 DeviceClass *dc = DEVICE_CLASS(klass);
778
779 dc->vmsd = &iotkit_secctl_vmstate;
780 dc->reset = iotkit_secctl_reset;
781}
782
783static const TypeInfo iotkit_secctl_info = {
784 .name = TYPE_IOTKIT_SECCTL,
785 .parent = TYPE_SYS_BUS_DEVICE,
786 .instance_size = sizeof(IoTKitSecCtl),
787 .instance_init = iotkit_secctl_init,
788 .class_init = iotkit_secctl_class_init,
789};
790
791static void iotkit_secctl_register_types(void)
792{
793 type_register_static(&iotkit_secctl_info);
794}
795
796type_init(iotkit_secctl_register_types);
797