xref: /openbmc/qemu/hw/misc/iotkit-secctl.c (revision ba632924)
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         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         /* None of our registers are access-sensitive, so just pull the right
232          * byte out of the word read result.
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 
242 static 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 
258 static 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 
269 static 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 
275 static 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 
281 static 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 
288 static 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 
295 static 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 
304 static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
305 {
306     /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
307     bool level = s->secmscintstat & s->secmscinten;
308 
309     qemu_set_irq(s->msc_irq, level);
310 }
311 
312 static 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         /* Byte and halfword writes are ignored */
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 
433 static 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         /* None of our registers are access-sensitive, so just pull the right
485          * byte out of the word read result.
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 
495 static 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         /* Byte and halfword writes are ignored */
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 
559 static 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 
569 static 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 
579 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
580 {
581     ppc->ns = 0;
582     ppc->sp = 0;
583     ppc->nsp = 0;
584 }
585 
586 static 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 
599 static 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 
606 static 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 
613 static 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 
621 static 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 
630 static 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 
661 static 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 
710 static 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 
722 static 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 
732 static bool needed_always(void *opaque)
733 {
734     return true;
735 }
736 
737 static 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 
750 static 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 
775 static 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 
783 static 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 
791 static void iotkit_secctl_register_types(void)
792 {
793     type_register_static(&iotkit_secctl_info);
794 }
795 
796 type_init(iotkit_secctl_register_types);
797