2 * Arm IoT Kit security controller
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
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.
12 #include "qemu/osdep.h"
14 #include "qemu/module.h"
15 #include "qapi/error.h"
17 #include "hw/sysbus.h"
18 #include "migration/vmstate.h"
19 #include "hw/registerfields.h"
21 #include "hw/misc/iotkit-secctl.h"
22 #include "hw/arm/armsse-version.h"
23 #include "hw/qdev-properties.h"
25 /* Registers in the secure privilege control block */
26 REG32(SECRESPCFG
, 0x10)
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)
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)
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 */
88 static const uint8_t iotkit_secctl_s_idregs
[] = {
89 0x04, 0x00, 0x00, 0x00,
90 0x52, 0xb8, 0x0b, 0x00,
91 0x0d, 0xf0, 0x05, 0xb1,
94 static const uint8_t iotkit_secctl_ns_idregs
[] = {
95 0x04, 0x00, 0x00, 0x00,
96 0x53, 0xb8, 0x0b, 0x00,
97 0x0d, 0xf0, 0x05, 0xb1,
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,
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,
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 an index into a PPC array easily.
119 static inline int offset_to_ppc_idx(uint32_t offset
)
121 return extract32(offset
, 2, 2);
124 typedef void PerPPCFunction(IoTKitSecCtlPPC
*ppc
);
126 static void foreach_ppc(IoTKitSecCtl
*s
, PerPPCFunction
*fn
)
130 for (i
= 0; i
< IOTS_NUM_APB_PPC
; i
++) {
133 for (i
= 0; i
< IOTS_NUM_APB_EXP_PPC
; i
++) {
136 for (i
= 0; i
< IOTS_NUM_AHB_EXP_PPC
; i
++) {
141 static MemTxResult
iotkit_secctl_s_read(void *opaque
, hwaddr addr
,
143 unsigned size
, MemTxAttrs attrs
)
146 uint32_t offset
= addr
& ~0x3;
147 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
160 case A_SECMPCINTSTATUS
:
163 case A_SECPPCINTSTAT
:
164 r
= s
->secppcintstat
;
170 /* QEMU's bus fabric can never report errors as it doesn't buffer
171 * writes, so we never report bridge interrupts.
182 r
= s
->ahbexp
[offset_to_ppc_idx(offset
)].ns
;
186 r
= s
->apb
[offset_to_ppc_idx(offset
)].ns
;
192 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].ns
;
198 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].sp
;
202 r
= s
->apb
[offset_to_ppc_idx(offset
)].sp
;
208 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].sp
;
210 case A_SECMSCINTSTAT
:
211 r
= s
->secmscintstat
;
231 switch (s
->sse_version
) {
233 r
= iotkit_secctl_s_sse300_idregs
[(offset
- A_PID4
) / 4];
236 r
= iotkit_secctl_s_idregs
[(offset
- A_PID4
) / 4];
243 qemu_log_mask(LOG_GUEST_ERROR
,
244 "IotKit SecCtl S block read: write-only offset 0x%x\n",
249 qemu_log_mask(LOG_GUEST_ERROR
,
250 "IotKit SecCtl S block read: bad offset 0x%x\n", offset
);
256 /* None of our registers are access-sensitive, so just pull the right
257 * byte out of the word read result.
259 r
= extract32(r
, (addr
& 3) * 8, size
* 8);
262 trace_iotkit_secctl_s_read(offset
, r
, size
);
267 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC
*ppc
)
271 for (i
= 0; i
< ppc
->numports
; i
++) {
274 if (extract32(ppc
->ns
, i
, 1)) {
275 v
= extract32(ppc
->nsp
, i
, 1);
277 v
= extract32(ppc
->sp
, i
, 1);
279 qemu_set_irq(ppc
->ap
[i
], v
);
283 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC
*ppc
, uint32_t value
)
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));
291 iotkit_secctl_update_ppc_ap(ppc
);
294 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC
*ppc
, uint32_t value
)
296 ppc
->sp
= value
& MAKE_64BIT_MASK(0, ppc
->numports
);
297 iotkit_secctl_update_ppc_ap(ppc
);
300 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC
*ppc
, uint32_t value
)
302 ppc
->nsp
= value
& MAKE_64BIT_MASK(0, ppc
->numports
);
303 iotkit_secctl_update_ppc_ap(ppc
);
306 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC
*ppc
)
308 uint32_t value
= ppc
->parent
->secppcintstat
;
310 qemu_set_irq(ppc
->irq_clear
, extract32(value
, ppc
->irq_bit_offset
, 1));
313 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC
*ppc
)
315 uint32_t value
= ppc
->parent
->secppcinten
;
317 qemu_set_irq(ppc
->irq_enable
, extract32(value
, ppc
->irq_bit_offset
, 1));
320 static void iotkit_secctl_update_mscexp_irqs(qemu_irq
*msc_irqs
, uint32_t value
)
324 for (i
= 0; i
< IOTS_NUM_EXP_MSC
; i
++) {
325 qemu_set_irq(msc_irqs
[i
], extract32(value
, i
+ 16, 1));
329 static void iotkit_secctl_update_msc_irq(IoTKitSecCtl
*s
)
331 /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
332 bool level
= s
->secmscintstat
& s
->secmscinten
;
334 qemu_set_irq(s
->msc_irq
, level
);
337 static MemTxResult
iotkit_secctl_s_write(void *opaque
, hwaddr addr
,
339 unsigned size
, MemTxAttrs attrs
)
341 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
342 uint32_t offset
= addr
;
343 IoTKitSecCtlPPC
*ppc
;
345 trace_iotkit_secctl_s_write(offset
, value
, size
);
348 /* Byte and halfword writes are ignored */
349 qemu_log_mask(LOG_GUEST_ERROR
,
350 "IotKit SecCtl S block write: bad size, ignored\n");
356 s
->nsccfg
= value
& 3;
357 qemu_set_irq(s
->nsc_cfg_irq
, s
->nsccfg
);
361 s
->secrespcfg
= value
;
362 qemu_set_irq(s
->sec_resp_cfg
, s
->secrespcfg
);
365 s
->secppcintstat
&= ~(value
& 0x00f000f3);
366 foreach_ppc(s
, iotkit_secctl_ppc_update_irq_clear
);
369 s
->secppcinten
= value
& 0x00f000f3;
370 foreach_ppc(s
, iotkit_secctl_ppc_update_irq_enable
);
375 s
->brginten
= value
& 0xffff0000;
381 ppc
= &s
->ahbexp
[offset_to_ppc_idx(offset
)];
382 iotkit_secctl_ppc_ns_write(ppc
, value
);
386 ppc
= &s
->apb
[offset_to_ppc_idx(offset
)];
387 iotkit_secctl_ppc_ns_write(ppc
, value
);
393 ppc
= &s
->apbexp
[offset_to_ppc_idx(offset
)];
394 iotkit_secctl_ppc_ns_write(ppc
, value
);
400 ppc
= &s
->ahbexp
[offset_to_ppc_idx(offset
)];
401 iotkit_secctl_ppc_sp_write(ppc
, value
);
405 ppc
= &s
->apb
[offset_to_ppc_idx(offset
)];
406 iotkit_secctl_ppc_sp_write(ppc
, value
);
412 ppc
= &s
->apbexp
[offset_to_ppc_idx(offset
)];
413 iotkit_secctl_ppc_sp_write(ppc
, value
);
416 iotkit_secctl_update_mscexp_irqs(s
->mscexp_clear
, value
);
419 s
->secmscinten
= value
;
420 iotkit_secctl_update_msc_irq(s
);
424 iotkit_secctl_update_mscexp_irqs(s
->mscexp_ns
, value
);
426 case A_SECMPCINTSTATUS
:
427 case A_SECPPCINTSTAT
:
428 case A_SECMSCINTSTAT
:
444 qemu_log_mask(LOG_GUEST_ERROR
,
445 "IoTKit SecCtl S block write: "
446 "read-only offset 0x%x\n", offset
);
449 qemu_log_mask(LOG_GUEST_ERROR
,
450 "IotKit SecCtl S block write: bad offset 0x%x\n",
458 static MemTxResult
iotkit_secctl_ns_read(void *opaque
, hwaddr addr
,
460 unsigned size
, MemTxAttrs attrs
)
462 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
464 uint32_t offset
= addr
& ~0x3;
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
;
478 r
= s
->apb
[offset_to_ppc_idx(offset
)].nsp
;
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
;
498 switch (s
->sse_version
) {
500 r
= iotkit_secctl_ns_sse300_idregs
[(offset
- A_PID4
) / 4];
503 r
= iotkit_secctl_ns_idregs
[(offset
- A_PID4
) / 4];
508 qemu_log_mask(LOG_GUEST_ERROR
,
509 "IotKit SecCtl NS block write: bad offset 0x%x\n",
516 /* None of our registers are access-sensitive, so just pull the right
517 * byte out of the word read result.
519 r
= extract32(r
, (addr
& 3) * 8, size
* 8);
522 trace_iotkit_secctl_ns_read(offset
, r
, size
);
527 static MemTxResult
iotkit_secctl_ns_write(void *opaque
, hwaddr addr
,
529 unsigned size
, MemTxAttrs attrs
)
531 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
532 uint32_t offset
= addr
;
533 IoTKitSecCtlPPC
*ppc
;
535 trace_iotkit_secctl_ns_write(offset
, value
, size
);
538 /* Byte and halfword writes are ignored */
539 qemu_log_mask(LOG_GUEST_ERROR
,
540 "IotKit SecCtl NS block write: bad size, ignored\n");
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
);
554 ppc
= &s
->apb
[offset_to_ppc_idx(offset
)];
555 iotkit_secctl_ppc_nsp_write(ppc
, value
);
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
);
577 qemu_log_mask(LOG_GUEST_ERROR
,
578 "IoTKit SecCtl NS block write: "
579 "read-only offset 0x%x\n", offset
);
582 qemu_log_mask(LOG_GUEST_ERROR
,
583 "IotKit SecCtl NS block write: bad offset 0x%x\n",
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,
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,
611 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC
*ppc
)
618 static void iotkit_secctl_reset(DeviceState
*dev
)
620 IoTKitSecCtl
*s
= IOTKIT_SECCTL(dev
);
622 s
->secppcintstat
= 0;
628 foreach_ppc(s
, iotkit_secctl_reset_ppc
);
631 static void iotkit_secctl_mpc_status(void *opaque
, int n
, int level
)
633 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
635 s
->mpcintstatus
= deposit32(s
->mpcintstatus
, n
, 1, !!level
);
638 static void iotkit_secctl_mpcexp_status(void *opaque
, int n
, int level
)
640 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
642 s
->mpcintstatus
= deposit32(s
->mpcintstatus
, n
+ 16, 1, !!level
);
645 static void iotkit_secctl_mscexp_status(void *opaque
, int n
, int level
)
647 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
649 s
->secmscintstat
= deposit32(s
->secmscintstat
, n
+ 16, 1, !!level
);
650 iotkit_secctl_update_msc_irq(s
);
653 static void iotkit_secctl_ppc_irqstatus(void *opaque
, int n
, int level
)
655 IoTKitSecCtlPPC
*ppc
= opaque
;
656 IoTKitSecCtl
*s
= IOTKIT_SECCTL(ppc
->parent
);
657 int irqbit
= ppc
->irq_bit_offset
+ n
;
659 s
->secppcintstat
= deposit32(s
->secppcintstat
, irqbit
, 1, level
);
662 static void iotkit_secctl_init_ppc(IoTKitSecCtl
*s
,
663 IoTKitSecCtlPPC
*ppc
,
669 DeviceState
*dev
= DEVICE(s
);
671 ppc
->numports
= numports
;
672 ppc
->irq_bit_offset
= irq_bit_offset
;
675 gpioname
= g_strdup_printf("%s_nonsec", name
);
676 qdev_init_gpio_out_named(dev
, ppc
->nonsec
, gpioname
, numports
);
678 gpioname
= g_strdup_printf("%s_ap", name
);
679 qdev_init_gpio_out_named(dev
, ppc
->ap
, gpioname
, numports
);
681 gpioname
= g_strdup_printf("%s_irq_enable", name
);
682 qdev_init_gpio_out_named(dev
, &ppc
->irq_enable
, gpioname
, 1);
684 gpioname
= g_strdup_printf("%s_irq_clear", name
);
685 qdev_init_gpio_out_named(dev
, &ppc
->irq_clear
, gpioname
, 1);
687 gpioname
= g_strdup_printf("%s_irq_status", name
);
688 qdev_init_gpio_in_named_with_opaque(dev
, iotkit_secctl_ppc_irqstatus
,
693 static void iotkit_secctl_init(Object
*obj
)
695 IoTKitSecCtl
*s
= IOTKIT_SECCTL(obj
);
696 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
697 DeviceState
*dev
= DEVICE(obj
);
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);
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
);
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
);
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);
721 qdev_init_gpio_in_named(dev
, iotkit_secctl_mpc_status
, "mpc_status",
723 qdev_init_gpio_in_named(dev
, iotkit_secctl_mpcexp_status
,
724 "mpcexp_status", IOTS_NUM_EXP_MPC
);
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",
730 qdev_init_gpio_out_named(dev
, s
->mscexp_ns
, "mscexp_ns",
732 qdev_init_gpio_out_named(dev
, &s
->msc_irq
, "msc_irq", 1);
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
);
742 static void iotkit_secctl_realize(DeviceState
*dev
, Error
**errp
)
744 IoTKitSecCtl
*s
= IOTKIT_SECCTL(dev
);
746 if (!armsse_version_valid(s
->sse_version
)) {
747 error_setg(errp
, "invalid sse-version value %d", s
->sse_version
);
752 static const VMStateDescription iotkit_secctl_ppc_vmstate
= {
753 .name
= "iotkit-secctl-ppc",
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()
764 static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate
= {
765 .name
= "iotkit-secctl-mpcintstatus",
767 .minimum_version_id
= 1,
768 .fields
= (VMStateField
[]) {
769 VMSTATE_UINT32(mpcintstatus
, IoTKitSecCtl
),
770 VMSTATE_END_OF_LIST()
774 static bool needed_always(void *opaque
)
779 static const VMStateDescription iotkit_secctl_msc_vmstate
= {
780 .name
= "iotkit-secctl/msc",
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()
792 static const VMStateDescription iotkit_secctl_vmstate
= {
793 .name
= "iotkit-secctl",
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()
810 .subsections
= (const VMStateDescription
*[]) {
811 &iotkit_secctl_mpcintstatus_vmstate
,
812 &iotkit_secctl_msc_vmstate
,
817 static Property iotkit_secctl_props
[] = {
818 DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl
, sse_version
, 0),
819 DEFINE_PROP_END_OF_LIST()
822 static void iotkit_secctl_class_init(ObjectClass
*klass
, void *data
)
824 DeviceClass
*dc
= DEVICE_CLASS(klass
);
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
);
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
,
840 static void iotkit_secctl_register_types(void)
842 type_register_static(&iotkit_secctl_info
);
845 type_init(iotkit_secctl_register_types
);