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