xref: /qemu/hw/misc/iotkit-secctl.c (revision e7b3af81)
1 /*
2  * Arm IoT Kit security controller
3  *
4  * Copyright (c) 2018 Linaro Limited
5  * Written by Peter Maydell
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 or
9  * (at your option) any later version.
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 /* Registers in the secure privilege control block */
21 REG32(SECRESPCFG, 0x10)
22 REG32(NSCCFG, 0x14)
23 REG32(SECMPCINTSTATUS, 0x1c)
24 REG32(SECPPCINTSTAT, 0x20)
25 REG32(SECPPCINTCLR, 0x24)
26 REG32(SECPPCINTEN, 0x28)
27 REG32(SECMSCINTSTAT, 0x30)
28 REG32(SECMSCINTCLR, 0x34)
29 REG32(SECMSCINTEN, 0x38)
30 REG32(BRGINTSTAT, 0x40)
31 REG32(BRGINTCLR, 0x44)
32 REG32(BRGINTEN, 0x48)
33 REG32(AHBNSPPC0, 0x50)
34 REG32(AHBNSPPCEXP0, 0x60)
35 REG32(AHBNSPPCEXP1, 0x64)
36 REG32(AHBNSPPCEXP2, 0x68)
37 REG32(AHBNSPPCEXP3, 0x6c)
38 REG32(APBNSPPC0, 0x70)
39 REG32(APBNSPPC1, 0x74)
40 REG32(APBNSPPCEXP0, 0x80)
41 REG32(APBNSPPCEXP1, 0x84)
42 REG32(APBNSPPCEXP2, 0x88)
43 REG32(APBNSPPCEXP3, 0x8c)
44 REG32(AHBSPPPC0, 0x90)
45 REG32(AHBSPPPCEXP0, 0xa0)
46 REG32(AHBSPPPCEXP1, 0xa4)
47 REG32(AHBSPPPCEXP2, 0xa8)
48 REG32(AHBSPPPCEXP3, 0xac)
49 REG32(APBSPPPC0, 0xb0)
50 REG32(APBSPPPC1, 0xb4)
51 REG32(APBSPPPCEXP0, 0xc0)
52 REG32(APBSPPPCEXP1, 0xc4)
53 REG32(APBSPPPCEXP2, 0xc8)
54 REG32(APBSPPPCEXP3, 0xcc)
55 REG32(NSMSCEXP, 0xd0)
56 REG32(PID4, 0xfd0)
57 REG32(PID5, 0xfd4)
58 REG32(PID6, 0xfd8)
59 REG32(PID7, 0xfdc)
60 REG32(PID0, 0xfe0)
61 REG32(PID1, 0xfe4)
62 REG32(PID2, 0xfe8)
63 REG32(PID3, 0xfec)
64 REG32(CID0, 0xff0)
65 REG32(CID1, 0xff4)
66 REG32(CID2, 0xff8)
67 REG32(CID3, 0xffc)
68 
69 /* Registers in the non-secure privilege control block */
70 REG32(AHBNSPPPC0, 0x90)
71 REG32(AHBNSPPPCEXP0, 0xa0)
72 REG32(AHBNSPPPCEXP1, 0xa4)
73 REG32(AHBNSPPPCEXP2, 0xa8)
74 REG32(AHBNSPPPCEXP3, 0xac)
75 REG32(APBNSPPPC0, 0xb0)
76 REG32(APBNSPPPC1, 0xb4)
77 REG32(APBNSPPPCEXP0, 0xc0)
78 REG32(APBNSPPPCEXP1, 0xc4)
79 REG32(APBNSPPPCEXP2, 0xc8)
80 REG32(APBNSPPPCEXP3, 0xcc)
81 /* PID and CID registers are also present in the NS block */
82 
83 static const uint8_t iotkit_secctl_s_idregs[] = {
84     0x04, 0x00, 0x00, 0x00,
85     0x52, 0xb8, 0x0b, 0x00,
86     0x0d, 0xf0, 0x05, 0xb1,
87 };
88 
89 static 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 /* The register sets for the various PPCs (AHB internal, APB internal,
96  * AHB expansion, APB expansion) are all set up so that they are
97  * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
98  * 0, 1, 2, 3 of that type, so we can convert a register address offset
99  * into an an index into a PPC array easily.
100  */
101 static inline int offset_to_ppc_idx(uint32_t offset)
102 {
103     return extract32(offset, 2, 2);
104 }
105 
106 typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
107 
108 static 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 
123 static 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         /* QEMU's bus fabric can never report errors as it doesn't buffer
153          * writes, so we never report bridge interrupts.
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     case A_SECMSCINTEN:
194     case A_NSMSCEXP:
195         qemu_log_mask(LOG_UNIMP,
196                       "IoTKit SecCtl S block read: "
197                       "unimplemented offset 0x%x\n", offset);
198         r = 0;
199         break;
200     case A_PID4:
201     case A_PID5:
202     case A_PID6:
203     case A_PID7:
204     case A_PID0:
205     case A_PID1:
206     case A_PID2:
207     case A_PID3:
208     case A_CID0:
209     case A_CID1:
210     case A_CID2:
211     case A_CID3:
212         r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
213         break;
214     case A_SECPPCINTCLR:
215     case A_SECMSCINTCLR:
216     case A_BRGINTCLR:
217         qemu_log_mask(LOG_GUEST_ERROR,
218                       "IotKit SecCtl S block read: write-only offset 0x%x\n",
219                       offset);
220         r = 0;
221         break;
222     default:
223         qemu_log_mask(LOG_GUEST_ERROR,
224                       "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
225         r = 0;
226         break;
227     }
228 
229     if (size != 4) {
230         /* None of our registers are access-sensitive, so just pull the right
231          * byte out of the word read result.
232          */
233         r = extract32(r, (addr & 3) * 8, size * 8);
234     }
235 
236     trace_iotkit_secctl_s_read(offset, r, size);
237     *pdata = r;
238     return MEMTX_OK;
239 }
240 
241 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
242 {
243     int i;
244 
245     for (i = 0; i < ppc->numports; i++) {
246         bool v;
247 
248         if (extract32(ppc->ns, i, 1)) {
249             v = extract32(ppc->nsp, i, 1);
250         } else {
251             v = extract32(ppc->sp, i, 1);
252         }
253         qemu_set_irq(ppc->ap[i], v);
254     }
255 }
256 
257 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
258 {
259     int i;
260 
261     ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
262     for (i = 0; i < ppc->numports; i++) {
263         qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
264     }
265     iotkit_secctl_update_ppc_ap(ppc);
266 }
267 
268 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
269 {
270     ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
271     iotkit_secctl_update_ppc_ap(ppc);
272 }
273 
274 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
275 {
276     ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
277     iotkit_secctl_update_ppc_ap(ppc);
278 }
279 
280 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
281 {
282     uint32_t value = ppc->parent->secppcintstat;
283 
284     qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
285 }
286 
287 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
288 {
289     uint32_t value = ppc->parent->secppcinten;
290 
291     qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
292 }
293 
294 static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
295                                          uint64_t value,
296                                          unsigned size, MemTxAttrs attrs)
297 {
298     IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
299     uint32_t offset = addr;
300     IoTKitSecCtlPPC *ppc;
301 
302     trace_iotkit_secctl_s_write(offset, value, size);
303 
304     if (size != 4) {
305         /* Byte and halfword writes are ignored */
306         qemu_log_mask(LOG_GUEST_ERROR,
307                       "IotKit SecCtl S block write: bad size, ignored\n");
308         return MEMTX_OK;
309     }
310 
311     switch (offset) {
312     case A_NSCCFG:
313         s->nsccfg = value & 3;
314         qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
315         break;
316     case A_SECRESPCFG:
317         value &= 1;
318         s->secrespcfg = value;
319         qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
320         break;
321     case A_SECPPCINTCLR:
322         value &= 0x00f000f3;
323         foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
324         break;
325     case A_SECPPCINTEN:
326         s->secppcinten = value & 0x00f000f3;
327         foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
328         break;
329     case A_BRGINTCLR:
330         break;
331     case A_BRGINTEN:
332         s->brginten = value & 0xffff0000;
333         break;
334     case A_AHBNSPPCEXP0:
335     case A_AHBNSPPCEXP1:
336     case A_AHBNSPPCEXP2:
337     case A_AHBNSPPCEXP3:
338         ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
339         iotkit_secctl_ppc_ns_write(ppc, value);
340         break;
341     case A_APBNSPPC0:
342     case A_APBNSPPC1:
343         ppc = &s->apb[offset_to_ppc_idx(offset)];
344         iotkit_secctl_ppc_ns_write(ppc, value);
345         break;
346     case A_APBNSPPCEXP0:
347     case A_APBNSPPCEXP1:
348     case A_APBNSPPCEXP2:
349     case A_APBNSPPCEXP3:
350         ppc = &s->apbexp[offset_to_ppc_idx(offset)];
351         iotkit_secctl_ppc_ns_write(ppc, value);
352         break;
353     case A_AHBSPPPCEXP0:
354     case A_AHBSPPPCEXP1:
355     case A_AHBSPPPCEXP2:
356     case A_AHBSPPPCEXP3:
357         ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
358         iotkit_secctl_ppc_sp_write(ppc, value);
359         break;
360     case A_APBSPPPC0:
361     case A_APBSPPPC1:
362         ppc = &s->apb[offset_to_ppc_idx(offset)];
363         iotkit_secctl_ppc_sp_write(ppc, value);
364         break;
365     case A_APBSPPPCEXP0:
366     case A_APBSPPPCEXP1:
367     case A_APBSPPPCEXP2:
368     case A_APBSPPPCEXP3:
369         ppc = &s->apbexp[offset_to_ppc_idx(offset)];
370         iotkit_secctl_ppc_sp_write(ppc, value);
371         break;
372     case A_SECMSCINTCLR:
373     case A_SECMSCINTEN:
374         qemu_log_mask(LOG_UNIMP,
375                       "IoTKit SecCtl S block write: "
376                       "unimplemented offset 0x%x\n", offset);
377         break;
378     case A_SECMPCINTSTATUS:
379     case A_SECPPCINTSTAT:
380     case A_SECMSCINTSTAT:
381     case A_BRGINTSTAT:
382     case A_AHBNSPPC0:
383     case A_AHBSPPPC0:
384     case A_NSMSCEXP:
385     case A_PID4:
386     case A_PID5:
387     case A_PID6:
388     case A_PID7:
389     case A_PID0:
390     case A_PID1:
391     case A_PID2:
392     case A_PID3:
393     case A_CID0:
394     case A_CID1:
395     case A_CID2:
396     case A_CID3:
397         qemu_log_mask(LOG_GUEST_ERROR,
398                       "IoTKit SecCtl S block write: "
399                       "read-only offset 0x%x\n", offset);
400         break;
401     default:
402         qemu_log_mask(LOG_GUEST_ERROR,
403                       "IotKit SecCtl S block write: bad offset 0x%x\n",
404                       offset);
405         break;
406     }
407 
408     return MEMTX_OK;
409 }
410 
411 static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
412                                          uint64_t *pdata,
413                                          unsigned size, MemTxAttrs attrs)
414 {
415     IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
416     uint64_t r;
417     uint32_t offset = addr & ~0x3;
418 
419     switch (offset) {
420     case A_AHBNSPPPC0:
421         r = 0;
422         break;
423     case A_AHBNSPPPCEXP0:
424     case A_AHBNSPPPCEXP1:
425     case A_AHBNSPPPCEXP2:
426     case A_AHBNSPPPCEXP3:
427         r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
428         break;
429     case A_APBNSPPPC0:
430     case A_APBNSPPPC1:
431         r = s->apb[offset_to_ppc_idx(offset)].nsp;
432         break;
433     case A_APBNSPPPCEXP0:
434     case A_APBNSPPPCEXP1:
435     case A_APBNSPPPCEXP2:
436     case A_APBNSPPPCEXP3:
437         r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
438         break;
439     case A_PID4:
440     case A_PID5:
441     case A_PID6:
442     case A_PID7:
443     case A_PID0:
444     case A_PID1:
445     case A_PID2:
446     case A_PID3:
447     case A_CID0:
448     case A_CID1:
449     case A_CID2:
450     case A_CID3:
451         r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
452         break;
453     default:
454         qemu_log_mask(LOG_GUEST_ERROR,
455                       "IotKit SecCtl NS block write: bad offset 0x%x\n",
456                       offset);
457         r = 0;
458         break;
459     }
460 
461     if (size != 4) {
462         /* None of our registers are access-sensitive, so just pull the right
463          * byte out of the word read result.
464          */
465         r = extract32(r, (addr & 3) * 8, size * 8);
466     }
467 
468     trace_iotkit_secctl_ns_read(offset, r, size);
469     *pdata = r;
470     return MEMTX_OK;
471 }
472 
473 static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
474                                           uint64_t value,
475                                           unsigned size, MemTxAttrs attrs)
476 {
477     IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
478     uint32_t offset = addr;
479     IoTKitSecCtlPPC *ppc;
480 
481     trace_iotkit_secctl_ns_write(offset, value, size);
482 
483     if (size != 4) {
484         /* Byte and halfword writes are ignored */
485         qemu_log_mask(LOG_GUEST_ERROR,
486                       "IotKit SecCtl NS block write: bad size, ignored\n");
487         return MEMTX_OK;
488     }
489 
490     switch (offset) {
491     case A_AHBNSPPPCEXP0:
492     case A_AHBNSPPPCEXP1:
493     case A_AHBNSPPPCEXP2:
494     case A_AHBNSPPPCEXP3:
495         ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
496         iotkit_secctl_ppc_nsp_write(ppc, value);
497         break;
498     case A_APBNSPPPC0:
499     case A_APBNSPPPC1:
500         ppc = &s->apb[offset_to_ppc_idx(offset)];
501         iotkit_secctl_ppc_nsp_write(ppc, value);
502         break;
503     case A_APBNSPPPCEXP0:
504     case A_APBNSPPPCEXP1:
505     case A_APBNSPPPCEXP2:
506     case A_APBNSPPPCEXP3:
507         ppc = &s->apbexp[offset_to_ppc_idx(offset)];
508         iotkit_secctl_ppc_nsp_write(ppc, value);
509         break;
510     case A_AHBNSPPPC0:
511     case A_PID4:
512     case A_PID5:
513     case A_PID6:
514     case A_PID7:
515     case A_PID0:
516     case A_PID1:
517     case A_PID2:
518     case A_PID3:
519     case A_CID0:
520     case A_CID1:
521     case A_CID2:
522     case A_CID3:
523         qemu_log_mask(LOG_GUEST_ERROR,
524                       "IoTKit SecCtl NS block write: "
525                       "read-only offset 0x%x\n", offset);
526         break;
527     default:
528         qemu_log_mask(LOG_GUEST_ERROR,
529                       "IotKit SecCtl NS block write: bad offset 0x%x\n",
530                       offset);
531         break;
532     }
533 
534     return MEMTX_OK;
535 }
536 
537 static const MemoryRegionOps iotkit_secctl_s_ops = {
538     .read_with_attrs = iotkit_secctl_s_read,
539     .write_with_attrs = iotkit_secctl_s_write,
540     .endianness = DEVICE_LITTLE_ENDIAN,
541     .valid.min_access_size = 1,
542     .valid.max_access_size = 4,
543     .impl.min_access_size = 1,
544     .impl.max_access_size = 4,
545 };
546 
547 static const MemoryRegionOps iotkit_secctl_ns_ops = {
548     .read_with_attrs = iotkit_secctl_ns_read,
549     .write_with_attrs = iotkit_secctl_ns_write,
550     .endianness = DEVICE_LITTLE_ENDIAN,
551     .valid.min_access_size = 1,
552     .valid.max_access_size = 4,
553     .impl.min_access_size = 1,
554     .impl.max_access_size = 4,
555 };
556 
557 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
558 {
559     ppc->ns = 0;
560     ppc->sp = 0;
561     ppc->nsp = 0;
562 }
563 
564 static void iotkit_secctl_reset(DeviceState *dev)
565 {
566     IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
567 
568     s->secppcintstat = 0;
569     s->secppcinten = 0;
570     s->secrespcfg = 0;
571     s->nsccfg = 0;
572     s->brginten = 0;
573 
574     foreach_ppc(s, iotkit_secctl_reset_ppc);
575 }
576 
577 static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
578 {
579     IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
580 
581     s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
582 }
583 
584 static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
585 {
586     IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
587 
588     s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
589 }
590 
591 static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
592 {
593     IoTKitSecCtlPPC *ppc = opaque;
594     IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
595     int irqbit = ppc->irq_bit_offset + n;
596 
597     s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
598 }
599 
600 static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
601                                    IoTKitSecCtlPPC *ppc,
602                                    const char *name,
603                                    int numports,
604                                    int irq_bit_offset)
605 {
606     char *gpioname;
607     DeviceState *dev = DEVICE(s);
608 
609     ppc->numports = numports;
610     ppc->irq_bit_offset = irq_bit_offset;
611     ppc->parent = s;
612 
613     gpioname = g_strdup_printf("%s_nonsec", name);
614     qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
615     g_free(gpioname);
616     gpioname = g_strdup_printf("%s_ap", name);
617     qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
618     g_free(gpioname);
619     gpioname = g_strdup_printf("%s_irq_enable", name);
620     qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
621     g_free(gpioname);
622     gpioname = g_strdup_printf("%s_irq_clear", name);
623     qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
624     g_free(gpioname);
625     gpioname = g_strdup_printf("%s_irq_status", name);
626     qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
627                                         ppc, gpioname, 1);
628     g_free(gpioname);
629 }
630 
631 static void iotkit_secctl_init(Object *obj)
632 {
633     IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
634     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
635     DeviceState *dev = DEVICE(obj);
636     int i;
637 
638     iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
639                            IOTS_APB_PPC0_NUM_PORTS, 0);
640     iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
641                            IOTS_APB_PPC1_NUM_PORTS, 1);
642 
643     for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
644         IoTKitSecCtlPPC *ppc = &s->apbexp[i];
645         char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
646         iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
647         g_free(ppcname);
648     }
649     for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
650         IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
651         char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
652         iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
653         g_free(ppcname);
654     }
655 
656     qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
657     qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
658 
659     qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
660     qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
661                             "mpcexp_status", IOTS_NUM_EXP_MPC);
662 
663     memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
664                           s, "iotkit-secctl-s-regs", 0x1000);
665     memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
666                           s, "iotkit-secctl-ns-regs", 0x1000);
667     sysbus_init_mmio(sbd, &s->s_regs);
668     sysbus_init_mmio(sbd, &s->ns_regs);
669 }
670 
671 static const VMStateDescription iotkit_secctl_ppc_vmstate = {
672     .name = "iotkit-secctl-ppc",
673     .version_id = 1,
674     .minimum_version_id = 1,
675     .fields = (VMStateField[]) {
676         VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
677         VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
678         VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
679         VMSTATE_END_OF_LIST()
680     }
681 };
682 
683 static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
684     .name = "iotkit-secctl-mpcintstatus",
685     .version_id = 1,
686     .minimum_version_id = 1,
687     .fields = (VMStateField[]) {
688         VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
689         VMSTATE_END_OF_LIST()
690     }
691 };
692 
693 static const VMStateDescription iotkit_secctl_vmstate = {
694     .name = "iotkit-secctl",
695     .version_id = 1,
696     .minimum_version_id = 1,
697     .fields = (VMStateField[]) {
698         VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
699         VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
700         VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
701         VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
702         VMSTATE_UINT32(brginten, IoTKitSecCtl),
703         VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
704                              iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
705         VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
706                              iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
707         VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
708                              iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
709         VMSTATE_END_OF_LIST()
710     },
711     .subsections = (const VMStateDescription*[]) {
712         &iotkit_secctl_mpcintstatus_vmstate,
713         NULL
714     },
715 };
716 
717 static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
718 {
719     DeviceClass *dc = DEVICE_CLASS(klass);
720 
721     dc->vmsd = &iotkit_secctl_vmstate;
722     dc->reset = iotkit_secctl_reset;
723 }
724 
725 static const TypeInfo iotkit_secctl_info = {
726     .name = TYPE_IOTKIT_SECCTL,
727     .parent = TYPE_SYS_BUS_DEVICE,
728     .instance_size = sizeof(IoTKitSecCtl),
729     .instance_init = iotkit_secctl_init,
730     .class_init = iotkit_secctl_class_init,
731 };
732 
733 static void iotkit_secctl_register_types(void)
734 {
735     type_register_static(&iotkit_secctl_info);
736 }
737 
738 type_init(iotkit_secctl_register_types);
739