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