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 "qapi/error.h"
16 #include "hw/sysbus.h"
17 #include "hw/registerfields.h"
18 #include "hw/arm/iotkit.h"
19 #include "hw/misc/unimp.h"
20 #include "hw/arm/arm.h"
22 /* Create an alias region of @size bytes starting at @base
23 * which mirrors the memory starting at @orig.
25 static void make_alias(IoTKit
*s
, MemoryRegion
*mr
, const char *name
,
26 hwaddr base
, hwaddr size
, hwaddr orig
)
28 memory_region_init_alias(mr
, NULL
, name
, &s
->container
, orig
, size
);
29 /* The alias is even lower priority than unimplemented_device regions */
30 memory_region_add_subregion_overlap(&s
->container
, base
, mr
, -1500);
33 static void init_sysbus_child(Object
*parent
, const char *childname
,
34 void *child
, size_t childsize
,
35 const char *childtype
)
37 object_initialize(child
, childsize
, childtype
);
38 object_property_add_child(parent
, childname
, OBJECT(child
), &error_abort
);
39 qdev_set_parent_bus(DEVICE(child
), sysbus_get_default());
42 static void irq_status_forwarder(void *opaque
, int n
, int level
)
44 qemu_irq destirq
= opaque
;
46 qemu_set_irq(destirq
, level
);
49 static void nsccfg_handler(void *opaque
, int n
, int level
)
51 IoTKit
*s
= IOTKIT(opaque
);
56 static void iotkit_forward_ppc(IoTKit
*s
, const char *ppcname
, int ppcnum
)
58 /* Each of the 4 AHB and 4 APB PPCs that might be present in a
59 * system using the IoTKit has a collection of control lines which
60 * are provided by the security controller and which we want to
61 * expose as control lines on the IoTKit device itself, so the
62 * code using the IoTKit can wire them up to the PPCs.
64 SplitIRQ
*splitter
= &s
->ppc_irq_splitter
[ppcnum
];
65 DeviceState
*iotkitdev
= DEVICE(s
);
66 DeviceState
*dev_secctl
= DEVICE(&s
->secctl
);
67 DeviceState
*dev_splitter
= DEVICE(splitter
);
70 name
= g_strdup_printf("%s_nonsec", ppcname
);
71 qdev_pass_gpios(dev_secctl
, iotkitdev
, name
);
73 name
= g_strdup_printf("%s_ap", ppcname
);
74 qdev_pass_gpios(dev_secctl
, iotkitdev
, name
);
76 name
= g_strdup_printf("%s_irq_enable", ppcname
);
77 qdev_pass_gpios(dev_secctl
, iotkitdev
, name
);
79 name
= g_strdup_printf("%s_irq_clear", ppcname
);
80 qdev_pass_gpios(dev_secctl
, iotkitdev
, name
);
83 /* irq_status is a little more tricky, because we need to
84 * split it so we can send it both to the security controller
85 * and to our OR gate for the NVIC interrupt line.
86 * Connect up the splitter's outputs, and create a GPIO input
87 * which will pass the line state to the input splitter.
89 name
= g_strdup_printf("%s_irq_status", ppcname
);
90 qdev_connect_gpio_out(dev_splitter
, 0,
91 qdev_get_gpio_in_named(dev_secctl
,
93 qdev_connect_gpio_out(dev_splitter
, 1,
94 qdev_get_gpio_in(DEVICE(&s
->ppc_irq_orgate
), ppcnum
));
95 s
->irq_status_in
[ppcnum
] = qdev_get_gpio_in(dev_splitter
, 0);
96 qdev_init_gpio_in_named_with_opaque(iotkitdev
, irq_status_forwarder
,
97 s
->irq_status_in
[ppcnum
], name
, 1);
101 static void iotkit_forward_sec_resp_cfg(IoTKit
*s
)
103 /* Forward the 3rd output from the splitter device as a
104 * named GPIO output of the iotkit object.
106 DeviceState
*dev
= DEVICE(s
);
107 DeviceState
*dev_splitter
= DEVICE(&s
->sec_resp_splitter
);
109 qdev_init_gpio_out_named(dev
, &s
->sec_resp_cfg
, "sec_resp_cfg", 1);
110 s
->sec_resp_cfg_in
= qemu_allocate_irq(irq_status_forwarder
,
112 qdev_connect_gpio_out(dev_splitter
, 2, s
->sec_resp_cfg_in
);
115 static void iotkit_init(Object
*obj
)
117 IoTKit
*s
= IOTKIT(obj
);
120 memory_region_init(&s
->container
, obj
, "iotkit-container", UINT64_MAX
);
122 init_sysbus_child(obj
, "armv7m", &s
->armv7m
, sizeof(s
->armv7m
),
124 qdev_prop_set_string(DEVICE(&s
->armv7m
), "cpu-type",
125 ARM_CPU_TYPE_NAME("cortex-m33"));
127 init_sysbus_child(obj
, "secctl", &s
->secctl
, sizeof(s
->secctl
),
129 init_sysbus_child(obj
, "apb-ppc0", &s
->apb_ppc0
, sizeof(s
->apb_ppc0
),
131 init_sysbus_child(obj
, "apb-ppc1", &s
->apb_ppc1
, sizeof(s
->apb_ppc1
),
133 init_sysbus_child(obj
, "timer0", &s
->timer0
, sizeof(s
->timer0
),
134 TYPE_CMSDK_APB_TIMER
);
135 init_sysbus_child(obj
, "timer1", &s
->timer1
, sizeof(s
->timer1
),
136 TYPE_CMSDK_APB_TIMER
);
137 init_sysbus_child(obj
, "dualtimer", &s
->dualtimer
, sizeof(s
->dualtimer
),
138 TYPE_UNIMPLEMENTED_DEVICE
);
139 object_initialize(&s
->ppc_irq_orgate
, sizeof(s
->ppc_irq_orgate
),
141 object_property_add_child(obj
, "ppc-irq-orgate",
142 OBJECT(&s
->ppc_irq_orgate
), &error_abort
);
143 object_initialize(&s
->sec_resp_splitter
, sizeof(s
->sec_resp_splitter
),
145 object_property_add_child(obj
, "sec-resp-splitter",
146 OBJECT(&s
->sec_resp_splitter
), &error_abort
);
147 for (i
= 0; i
< ARRAY_SIZE(s
->ppc_irq_splitter
); i
++) {
148 char *name
= g_strdup_printf("ppc-irq-splitter-%d", i
);
149 SplitIRQ
*splitter
= &s
->ppc_irq_splitter
[i
];
151 object_initialize(splitter
, sizeof(*splitter
), TYPE_SPLIT_IRQ
);
152 object_property_add_child(obj
, name
, OBJECT(splitter
), &error_abort
);
154 init_sysbus_child(obj
, "s32ktimer", &s
->s32ktimer
, sizeof(s
->s32ktimer
),
155 TYPE_UNIMPLEMENTED_DEVICE
);
158 static void iotkit_exp_irq(void *opaque
, int n
, int level
)
160 IoTKit
*s
= IOTKIT(opaque
);
162 qemu_set_irq(s
->exp_irqs
[n
], level
);
165 static void iotkit_realize(DeviceState
*dev
, Error
**errp
)
167 IoTKit
*s
= IOTKIT(dev
);
171 SysBusDevice
*sbd_apb_ppc0
;
172 SysBusDevice
*sbd_secctl
;
173 DeviceState
*dev_apb_ppc0
;
174 DeviceState
*dev_apb_ppc1
;
175 DeviceState
*dev_secctl
;
176 DeviceState
*dev_splitter
;
178 if (!s
->board_memory
) {
179 error_setg(errp
, "memory property was not set");
183 if (!s
->mainclk_frq
) {
184 error_setg(errp
, "MAINCLK property was not set");
188 /* Handling of which devices should be available only to secure
189 * code is usually done differently for M profile than for A profile.
190 * Instead of putting some devices only into the secure address space,
191 * devices exist in both address spaces but with hard-wired security
192 * permissions that will cause the CPU to fault for non-secure accesses.
194 * The IoTKit has an IDAU (Implementation Defined Access Unit),
195 * which specifies hard-wired security permissions for different
196 * areas of the physical address space. For the IoTKit IDAU, the
197 * top 4 bits of the physical address are the IDAU region ID, and
198 * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
199 * region, otherwise it is an S region.
201 * The various devices and RAMs are generally all mapped twice,
202 * once into a region that the IDAU defines as secure and once
203 * into a non-secure region. They sit behind either a Memory
204 * Protection Controller (for RAM) or a Peripheral Protection
205 * Controller (for devices), which allow a more fine grained
206 * configuration of whether non-secure accesses are permitted.
208 * (The other place that guest software can configure security
209 * permissions is in the architected SAU (Security Attribution
210 * Unit), which is entirely inside the CPU. The IDAU can upgrade
211 * the security attributes for a region to more restrictive than
212 * the SAU specifies, but cannot downgrade them.)
214 * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
215 * 0x20000000..0x2007ffff 32KB FPGA block RAM
216 * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
217 * 0x40000000..0x4000ffff base peripheral region 1
218 * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
219 * 0x40020000..0x4002ffff system control element peripherals
220 * 0x40080000..0x400fffff base peripheral region 2
221 * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
224 memory_region_add_subregion_overlap(&s
->container
, 0, s
->board_memory
, -1);
226 qdev_prop_set_uint32(DEVICE(&s
->armv7m
), "num-irq", s
->exp_numirq
+ 32);
227 /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
228 * register in the IoT Kit System Control Register block, and the
229 * initial value of that is in turn specifiable by the FPGA that
230 * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
231 * and simply set the CPU's init-svtor to the IoT Kit default value.
233 qdev_prop_set_uint32(DEVICE(&s
->armv7m
), "init-svtor", 0x10000000);
234 object_property_set_link(OBJECT(&s
->armv7m
), OBJECT(&s
->container
),
237 error_propagate(errp
, err
);
240 object_property_set_link(OBJECT(&s
->armv7m
), OBJECT(s
), "idau", &err
);
242 error_propagate(errp
, err
);
245 object_property_set_bool(OBJECT(&s
->armv7m
), true, "realized", &err
);
247 error_propagate(errp
, err
);
251 /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
252 s
->exp_irqs
= g_new(qemu_irq
, s
->exp_numirq
);
253 for (i
= 0; i
< s
->exp_numirq
; i
++) {
254 s
->exp_irqs
[i
] = qdev_get_gpio_in(DEVICE(&s
->armv7m
), i
+ 32);
256 qdev_init_gpio_in_named(dev
, iotkit_exp_irq
, "EXP_IRQ", s
->exp_numirq
);
258 /* Set up the big aliases first */
259 make_alias(s
, &s
->alias1
, "alias 1", 0x10000000, 0x10000000, 0x00000000);
260 make_alias(s
, &s
->alias2
, "alias 2", 0x30000000, 0x10000000, 0x20000000);
261 /* The 0x50000000..0x5fffffff region is not a pure alias: it has
262 * a few extra devices that only appear there (generally the
263 * control interfaces for the protection controllers).
264 * We implement this by mapping those devices over the top of this
265 * alias MR at a higher priority.
267 make_alias(s
, &s
->alias3
, "alias 3", 0x50000000, 0x10000000, 0x40000000);
269 /* This RAM should be behind a Memory Protection Controller, but we
270 * don't implement that yet.
272 memory_region_init_ram(&s
->sram0
, NULL
, "iotkit.sram0", 0x00008000, &err
);
274 error_propagate(errp
, err
);
277 memory_region_add_subregion(&s
->container
, 0x20000000, &s
->sram0
);
279 /* Security controller */
280 object_property_set_bool(OBJECT(&s
->secctl
), true, "realized", &err
);
282 error_propagate(errp
, err
);
285 sbd_secctl
= SYS_BUS_DEVICE(&s
->secctl
);
286 dev_secctl
= DEVICE(&s
->secctl
);
287 sysbus_mmio_map(sbd_secctl
, 0, 0x50080000);
288 sysbus_mmio_map(sbd_secctl
, 1, 0x40080000);
290 s
->nsc_cfg_in
= qemu_allocate_irq(nsccfg_handler
, s
, 1);
291 qdev_connect_gpio_out_named(dev_secctl
, "nsc_cfg", 0, s
->nsc_cfg_in
);
293 /* The sec_resp_cfg output from the security controller must be split into
294 * multiple lines, one for each of the PPCs within the IoTKit and one
295 * that will be an output from the IoTKit to the system.
297 object_property_set_int(OBJECT(&s
->sec_resp_splitter
), 3,
300 error_propagate(errp
, err
);
303 object_property_set_bool(OBJECT(&s
->sec_resp_splitter
), true,
306 error_propagate(errp
, err
);
309 dev_splitter
= DEVICE(&s
->sec_resp_splitter
);
310 qdev_connect_gpio_out_named(dev_secctl
, "sec_resp_cfg", 0,
311 qdev_get_gpio_in(dev_splitter
, 0));
313 /* Devices behind APB PPC0:
316 * 0x40002000: dual timer
317 * We must configure and realize each downstream device and connect
318 * it to the appropriate PPC port; then we can realize the PPC and
319 * map its upstream ends to the right place in the container.
321 qdev_prop_set_uint32(DEVICE(&s
->timer0
), "pclk-frq", s
->mainclk_frq
);
322 object_property_set_bool(OBJECT(&s
->timer0
), true, "realized", &err
);
324 error_propagate(errp
, err
);
327 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->timer0
), 0,
328 qdev_get_gpio_in(DEVICE(&s
->armv7m
), 3));
329 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->timer0
), 0);
330 object_property_set_link(OBJECT(&s
->apb_ppc0
), OBJECT(mr
), "port[0]", &err
);
332 error_propagate(errp
, err
);
336 qdev_prop_set_uint32(DEVICE(&s
->timer1
), "pclk-frq", s
->mainclk_frq
);
337 object_property_set_bool(OBJECT(&s
->timer1
), true, "realized", &err
);
339 error_propagate(errp
, err
);
342 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->timer1
), 0,
343 qdev_get_gpio_in(DEVICE(&s
->armv7m
), 3));
344 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->timer1
), 0);
345 object_property_set_link(OBJECT(&s
->apb_ppc0
), OBJECT(mr
), "port[1]", &err
);
347 error_propagate(errp
, err
);
351 qdev_prop_set_string(DEVICE(&s
->dualtimer
), "name", "Dual timer");
352 qdev_prop_set_uint64(DEVICE(&s
->dualtimer
), "size", 0x1000);
353 object_property_set_bool(OBJECT(&s
->dualtimer
), true, "realized", &err
);
355 error_propagate(errp
, err
);
358 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->dualtimer
), 0);
359 object_property_set_link(OBJECT(&s
->apb_ppc0
), OBJECT(mr
), "port[2]", &err
);
361 error_propagate(errp
, err
);
365 object_property_set_bool(OBJECT(&s
->apb_ppc0
), true, "realized", &err
);
367 error_propagate(errp
, err
);
371 sbd_apb_ppc0
= SYS_BUS_DEVICE(&s
->apb_ppc0
);
372 dev_apb_ppc0
= DEVICE(&s
->apb_ppc0
);
374 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 0);
375 memory_region_add_subregion(&s
->container
, 0x40000000, mr
);
376 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 1);
377 memory_region_add_subregion(&s
->container
, 0x40001000, mr
);
378 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 2);
379 memory_region_add_subregion(&s
->container
, 0x40002000, mr
);
380 for (i
= 0; i
< IOTS_APB_PPC0_NUM_PORTS
; i
++) {
381 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_nonsec", i
,
382 qdev_get_gpio_in_named(dev_apb_ppc0
,
384 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_ap", i
,
385 qdev_get_gpio_in_named(dev_apb_ppc0
,
388 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_irq_enable", 0,
389 qdev_get_gpio_in_named(dev_apb_ppc0
,
391 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_irq_clear", 0,
392 qdev_get_gpio_in_named(dev_apb_ppc0
,
394 qdev_connect_gpio_out(dev_splitter
, 0,
395 qdev_get_gpio_in_named(dev_apb_ppc0
,
398 /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
399 * ones) are sent individually to the security controller, and also
400 * ORed together to give a single combined PPC interrupt to the NVIC.
402 object_property_set_int(OBJECT(&s
->ppc_irq_orgate
),
403 NUM_PPCS
, "num-lines", &err
);
405 error_propagate(errp
, err
);
408 object_property_set_bool(OBJECT(&s
->ppc_irq_orgate
), true,
411 error_propagate(errp
, err
);
414 qdev_connect_gpio_out(DEVICE(&s
->ppc_irq_orgate
), 0,
415 qdev_get_gpio_in(DEVICE(&s
->armv7m
), 10));
417 /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
419 /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
420 /* Devices behind APB PPC1:
421 * 0x4002f000: S32K timer
423 qdev_prop_set_string(DEVICE(&s
->s32ktimer
), "name", "S32KTIMER");
424 qdev_prop_set_uint64(DEVICE(&s
->s32ktimer
), "size", 0x1000);
425 object_property_set_bool(OBJECT(&s
->s32ktimer
), true, "realized", &err
);
427 error_propagate(errp
, err
);
430 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->s32ktimer
), 0);
431 object_property_set_link(OBJECT(&s
->apb_ppc1
), OBJECT(mr
), "port[0]", &err
);
433 error_propagate(errp
, err
);
437 object_property_set_bool(OBJECT(&s
->apb_ppc1
), true, "realized", &err
);
439 error_propagate(errp
, err
);
442 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->apb_ppc1
), 0);
443 memory_region_add_subregion(&s
->container
, 0x4002f000, mr
);
445 dev_apb_ppc1
= DEVICE(&s
->apb_ppc1
);
446 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_nonsec", 0,
447 qdev_get_gpio_in_named(dev_apb_ppc1
,
449 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_ap", 0,
450 qdev_get_gpio_in_named(dev_apb_ppc1
,
452 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_irq_enable", 0,
453 qdev_get_gpio_in_named(dev_apb_ppc1
,
455 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_irq_clear", 0,
456 qdev_get_gpio_in_named(dev_apb_ppc1
,
458 qdev_connect_gpio_out(dev_splitter
, 1,
459 qdev_get_gpio_in_named(dev_apb_ppc1
,
462 /* Using create_unimplemented_device() maps the stub into the
463 * system address space rather than into our container, but the
464 * overall effect to the guest is the same.
466 create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
468 create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
469 create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
471 /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
473 create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
474 create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
476 create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
478 for (i
= 0; i
< ARRAY_SIZE(s
->ppc_irq_splitter
); i
++) {
479 Object
*splitter
= OBJECT(&s
->ppc_irq_splitter
[i
]);
481 object_property_set_int(splitter
, 2, "num-lines", &err
);
483 error_propagate(errp
, err
);
486 object_property_set_bool(splitter
, true, "realized", &err
);
488 error_propagate(errp
, err
);
493 for (i
= 0; i
< IOTS_NUM_AHB_EXP_PPC
; i
++) {
494 char *ppcname
= g_strdup_printf("ahb_ppcexp%d", i
);
496 iotkit_forward_ppc(s
, ppcname
, i
);
500 for (i
= 0; i
< IOTS_NUM_APB_EXP_PPC
; i
++) {
501 char *ppcname
= g_strdup_printf("apb_ppcexp%d", i
);
503 iotkit_forward_ppc(s
, ppcname
, i
+ IOTS_NUM_AHB_EXP_PPC
);
507 for (i
= NUM_EXTERNAL_PPCS
; i
< NUM_PPCS
; i
++) {
508 /* Wire up IRQ splitter for internal PPCs */
509 DeviceState
*devs
= DEVICE(&s
->ppc_irq_splitter
[i
]);
510 char *gpioname
= g_strdup_printf("apb_ppc%d_irq_status",
511 i
- NUM_EXTERNAL_PPCS
);
512 TZPPC
*ppc
= (i
== NUM_EXTERNAL_PPCS
) ? &s
->apb_ppc0
: &s
->apb_ppc1
;
514 qdev_connect_gpio_out(devs
, 0,
515 qdev_get_gpio_in_named(dev_secctl
, gpioname
, 0));
516 qdev_connect_gpio_out(devs
, 1,
517 qdev_get_gpio_in(DEVICE(&s
->ppc_irq_orgate
), i
));
518 qdev_connect_gpio_out_named(DEVICE(ppc
), "irq", 0,
519 qdev_get_gpio_in(devs
, 0));
522 iotkit_forward_sec_resp_cfg(s
);
524 system_clock_scale
= NANOSECONDS_PER_SECOND
/ s
->mainclk_frq
;
527 static void iotkit_idau_check(IDAUInterface
*ii
, uint32_t address
,
528 int *iregion
, bool *exempt
, bool *ns
, bool *nsc
)
530 /* For IoTKit systems the IDAU responses are simple logical functions
531 * of the address bits. The NSC attribute is guest-adjustable via the
532 * NSCCFG register in the security controller.
534 IoTKit
*s
= IOTKIT(ii
);
535 int region
= extract32(address
, 28, 4);
538 *nsc
= (region
== 1 && (s
->nsccfg
& 1)) || (region
== 3 && (s
->nsccfg
& 2));
539 /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
540 *exempt
= (address
& 0xeff00000) == 0xe0000000;
544 static const VMStateDescription iotkit_vmstate
= {
547 .minimum_version_id
= 1,
548 .fields
= (VMStateField
[]) {
549 VMSTATE_UINT32(nsccfg
, IoTKit
),
550 VMSTATE_END_OF_LIST()
554 static Property iotkit_properties
[] = {
555 DEFINE_PROP_LINK("memory", IoTKit
, board_memory
, TYPE_MEMORY_REGION
,
557 DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit
, exp_numirq
, 64),
558 DEFINE_PROP_UINT32("MAINCLK", IoTKit
, mainclk_frq
, 0),
559 DEFINE_PROP_END_OF_LIST()
562 static void iotkit_reset(DeviceState
*dev
)
564 IoTKit
*s
= IOTKIT(dev
);
569 static void iotkit_class_init(ObjectClass
*klass
, void *data
)
571 DeviceClass
*dc
= DEVICE_CLASS(klass
);
572 IDAUInterfaceClass
*iic
= IDAU_INTERFACE_CLASS(klass
);
574 dc
->realize
= iotkit_realize
;
575 dc
->vmsd
= &iotkit_vmstate
;
576 dc
->props
= iotkit_properties
;
577 dc
->reset
= iotkit_reset
;
578 iic
->check
= iotkit_idau_check
;
581 static const TypeInfo iotkit_info
= {
583 .parent
= TYPE_SYS_BUS_DEVICE
,
584 .instance_size
= sizeof(IoTKit
),
585 .instance_init
= iotkit_init
,
586 .class_init
= iotkit_class_init
,
587 .interfaces
= (InterfaceInfo
[]) {
588 { TYPE_IDAU_INTERFACE
},
593 static void iotkit_register_types(void)
595 type_register_static(&iotkit_info
);
598 type_init(iotkit_register_types
);