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