1
2
3
4
5
6
7
8
9
10
11
12#include "qemu/osdep.h"
13#include "qemu/log.h"
14#include "qapi/error.h"
15#include "trace.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"
21
22
23
24
25static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
26 hwaddr base, hwaddr size, hwaddr orig)
27{
28 memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
29
30 memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
31}
32
33static void irq_status_forwarder(void *opaque, int n, int level)
34{
35 qemu_irq destirq = opaque;
36
37 qemu_set_irq(destirq, level);
38}
39
40static void nsccfg_handler(void *opaque, int n, int level)
41{
42 IoTKit *s = IOTKIT(opaque);
43
44 s->nsccfg = level;
45}
46
47static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
48{
49
50
51
52
53
54
55 SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
56 DeviceState *iotkitdev = DEVICE(s);
57 DeviceState *dev_secctl = DEVICE(&s->secctl);
58 DeviceState *dev_splitter = DEVICE(splitter);
59 char *name;
60
61 name = g_strdup_printf("%s_nonsec", ppcname);
62 qdev_pass_gpios(dev_secctl, iotkitdev, name);
63 g_free(name);
64 name = g_strdup_printf("%s_ap", ppcname);
65 qdev_pass_gpios(dev_secctl, iotkitdev, name);
66 g_free(name);
67 name = g_strdup_printf("%s_irq_enable", ppcname);
68 qdev_pass_gpios(dev_secctl, iotkitdev, name);
69 g_free(name);
70 name = g_strdup_printf("%s_irq_clear", ppcname);
71 qdev_pass_gpios(dev_secctl, iotkitdev, name);
72 g_free(name);
73
74
75
76
77
78
79
80 name = g_strdup_printf("%s_irq_status", ppcname);
81 qdev_connect_gpio_out(dev_splitter, 0,
82 qdev_get_gpio_in_named(dev_secctl,
83 name, 0));
84 qdev_connect_gpio_out(dev_splitter, 1,
85 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
86 s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
87 qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
88 s->irq_status_in[ppcnum], name, 1);
89 g_free(name);
90}
91
92static void iotkit_forward_sec_resp_cfg(IoTKit *s)
93{
94
95
96
97 DeviceState *dev = DEVICE(s);
98 DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
99
100 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
101 s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
102 s->sec_resp_cfg, 1);
103 qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
104}
105
106static void iotkit_init(Object *obj)
107{
108 IoTKit *s = IOTKIT(obj);
109 int i;
110
111 memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
112
113 sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
114 TYPE_ARMV7M);
115 qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
116 ARM_CPU_TYPE_NAME("cortex-m33"));
117
118 sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
119 TYPE_IOTKIT_SECCTL);
120 sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
121 TYPE_TZ_PPC);
122 sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
123 TYPE_TZ_PPC);
124 sysbus_init_child_obj(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
125 object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
126 sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
127 &error_abort, NULL);
128
129 for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
130 char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
131 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
132
133 object_initialize_child(obj, name, splitter, sizeof(*splitter),
134 TYPE_SPLIT_IRQ, &error_abort, NULL);
135 g_free(name);
136 }
137 sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0),
138 TYPE_CMSDK_APB_TIMER);
139 sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
140 TYPE_CMSDK_APB_TIMER);
141 sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
142 TYPE_UNIMPLEMENTED_DEVICE);
143 object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
144 sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
145 &error_abort, NULL);
146 object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter,
147 sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ,
148 &error_abort, NULL);
149 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
150 char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
151 SplitIRQ *splitter = &s->ppc_irq_splitter[i];
152
153 object_initialize_child(obj, name, splitter, sizeof(*splitter),
154 TYPE_SPLIT_IRQ, &error_abort, NULL);
155 g_free(name);
156 }
157 sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
158 TYPE_UNIMPLEMENTED_DEVICE);
159}
160
161static void iotkit_exp_irq(void *opaque, int n, int level)
162{
163 IoTKit *s = IOTKIT(opaque);
164
165 qemu_set_irq(s->exp_irqs[n], level);
166}
167
168static void iotkit_mpcexp_status(void *opaque, int n, int level)
169{
170 IoTKit *s = IOTKIT(opaque);
171 qemu_set_irq(s->mpcexp_status_in[n], level);
172}
173
174static void iotkit_realize(DeviceState *dev, Error **errp)
175{
176 IoTKit *s = IOTKIT(dev);
177 int i;
178 MemoryRegion *mr;
179 Error *err = NULL;
180 SysBusDevice *sbd_apb_ppc0;
181 SysBusDevice *sbd_secctl;
182 DeviceState *dev_apb_ppc0;
183 DeviceState *dev_apb_ppc1;
184 DeviceState *dev_secctl;
185 DeviceState *dev_splitter;
186
187 if (!s->board_memory) {
188 error_setg(errp, "memory property was not set");
189 return;
190 }
191
192 if (!s->mainclk_frq) {
193 error_setg(errp, "MAINCLK property was not set");
194 return;
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
234
235 qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
236
237
238
239
240
241
242 qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
243 object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
244 "memory", &err);
245 if (err) {
246 error_propagate(errp, err);
247 return;
248 }
249 object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
250 if (err) {
251 error_propagate(errp, err);
252 return;
253 }
254 object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
255 if (err) {
256 error_propagate(errp, err);
257 return;
258 }
259
260
261 s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
262 for (i = 0; i < s->exp_numirq; i++) {
263 s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
264 }
265 qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
266
267
268 make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
269 make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
270
271
272
273
274
275
276 make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
277
278
279
280 object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
281 if (err) {
282 error_propagate(errp, err);
283 return;
284 }
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);
289
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);
292
293
294
295
296
297 object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
298 "num-lines", &err);
299 if (err) {
300 error_propagate(errp, err);
301 return;
302 }
303 object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
304 "realized", &err);
305 if (err) {
306 error_propagate(errp, err);
307 return;
308 }
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));
312
313
314 memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
315 if (err) {
316 error_propagate(errp, err);
317 return;
318 }
319 object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
320 "downstream", &err);
321 if (err) {
322 error_propagate(errp, err);
323 return;
324 }
325 object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
326 if (err) {
327 error_propagate(errp, err);
328 return;
329 }
330
331 memory_region_add_subregion(&s->container, 0x20000000,
332 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
333 1));
334
335 memory_region_add_subregion(&s->container, 0x50083000,
336 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
337 0));
338
339
340 object_property_set_int(OBJECT(&s->mpc_irq_orgate),
341 IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
342 if (err) {
343 error_propagate(errp, err);
344 return;
345 }
346 object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
347 "realized", &err);
348 if (err) {
349 error_propagate(errp, err);
350 return;
351 }
352 qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
353 qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
354
355
356
357
358
359
360
361
362
363 qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
364 object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
365 if (err) {
366 error_propagate(errp, err);
367 return;
368 }
369 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
370 qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
371 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
372 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
373 if (err) {
374 error_propagate(errp, err);
375 return;
376 }
377
378 qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
379 object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
380 if (err) {
381 error_propagate(errp, err);
382 return;
383 }
384 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
385 qdev_get_gpio_in(DEVICE(&s->armv7m), 4));
386 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
387 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
388 if (err) {
389 error_propagate(errp, err);
390 return;
391 }
392
393 qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
394 qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
395 object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
396 if (err) {
397 error_propagate(errp, err);
398 return;
399 }
400 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
401 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
402 if (err) {
403 error_propagate(errp, err);
404 return;
405 }
406
407 object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
408 if (err) {
409 error_propagate(errp, err);
410 return;
411 }
412
413 sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
414 dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
415
416 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
417 memory_region_add_subregion(&s->container, 0x40000000, mr);
418 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
419 memory_region_add_subregion(&s->container, 0x40001000, mr);
420 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
421 memory_region_add_subregion(&s->container, 0x40002000, mr);
422 for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
423 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
424 qdev_get_gpio_in_named(dev_apb_ppc0,
425 "cfg_nonsec", i));
426 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
427 qdev_get_gpio_in_named(dev_apb_ppc0,
428 "cfg_ap", i));
429 }
430 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
431 qdev_get_gpio_in_named(dev_apb_ppc0,
432 "irq_enable", 0));
433 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
434 qdev_get_gpio_in_named(dev_apb_ppc0,
435 "irq_clear", 0));
436 qdev_connect_gpio_out(dev_splitter, 0,
437 qdev_get_gpio_in_named(dev_apb_ppc0,
438 "cfg_sec_resp", 0));
439
440
441
442
443
444 object_property_set_int(OBJECT(&s->ppc_irq_orgate),
445 NUM_PPCS, "num-lines", &err);
446 if (err) {
447 error_propagate(errp, err);
448 return;
449 }
450 object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
451 "realized", &err);
452 if (err) {
453 error_propagate(errp, err);
454 return;
455 }
456 qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
457 qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
458
459
460
461
462
463
464
465 qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
466 qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
467 object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
468 if (err) {
469 error_propagate(errp, err);
470 return;
471 }
472 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
473 object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
474 if (err) {
475 error_propagate(errp, err);
476 return;
477 }
478
479 object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
480 if (err) {
481 error_propagate(errp, err);
482 return;
483 }
484 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
485 memory_region_add_subregion(&s->container, 0x4002f000, mr);
486
487 dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
488 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
489 qdev_get_gpio_in_named(dev_apb_ppc1,
490 "cfg_nonsec", 0));
491 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
492 qdev_get_gpio_in_named(dev_apb_ppc1,
493 "cfg_ap", 0));
494 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
495 qdev_get_gpio_in_named(dev_apb_ppc1,
496 "irq_enable", 0));
497 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
498 qdev_get_gpio_in_named(dev_apb_ppc1,
499 "irq_clear", 0));
500 qdev_connect_gpio_out(dev_splitter, 1,
501 qdev_get_gpio_in_named(dev_apb_ppc1,
502 "cfg_sec_resp", 0));
503
504
505
506
507
508 create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
509
510 create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
511 create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
512
513
514
515 create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
516 create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
517
518 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
519 Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
520
521 object_property_set_int(splitter, 2, "num-lines", &err);
522 if (err) {
523 error_propagate(errp, err);
524 return;
525 }
526 object_property_set_bool(splitter, true, "realized", &err);
527 if (err) {
528 error_propagate(errp, err);
529 return;
530 }
531 }
532
533 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
534 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
535
536 iotkit_forward_ppc(s, ppcname, i);
537 g_free(ppcname);
538 }
539
540 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
541 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
542
543 iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
544 g_free(ppcname);
545 }
546
547 for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
548
549 DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
550 char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
551 i - NUM_EXTERNAL_PPCS);
552 TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
553
554 qdev_connect_gpio_out(devs, 0,
555 qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
556 qdev_connect_gpio_out(devs, 1,
557 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
558 qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
559 qdev_get_gpio_in(devs, 0));
560 g_free(gpioname);
561 }
562
563
564 for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
565 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
566 DeviceState *dev_splitter = DEVICE(splitter);
567
568 object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
569 if (err) {
570 error_propagate(errp, err);
571 return;
572 }
573 object_property_set_bool(OBJECT(splitter), true, "realized", &err);
574 if (err) {
575 error_propagate(errp, err);
576 return;
577 }
578
579 if (i < IOTS_NUM_EXP_MPC) {
580
581 s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
582 qdev_connect_gpio_out(dev_splitter, 0,
583 qdev_get_gpio_in_named(dev_secctl,
584 "mpcexp_status", i));
585 } else {
586
587 qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
588 qdev_get_gpio_in(dev_splitter, 0));
589 qdev_connect_gpio_out(dev_splitter, 0,
590 qdev_get_gpio_in_named(dev_secctl,
591 "mpc_status", 0));
592 }
593
594 qdev_connect_gpio_out(dev_splitter, 1,
595 qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
596 }
597
598
599
600 qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
601 IOTS_NUM_EXP_MPC);
602
603 iotkit_forward_sec_resp_cfg(s);
604
605 system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
606}
607
608static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
609 int *iregion, bool *exempt, bool *ns, bool *nsc)
610{
611
612
613
614
615 IoTKit *s = IOTKIT(ii);
616 int region = extract32(address, 28, 4);
617
618 *ns = !(region & 1);
619 *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
620
621 *exempt = (address & 0xeff00000) == 0xe0000000;
622 *iregion = region;
623}
624
625static const VMStateDescription iotkit_vmstate = {
626 .name = "iotkit",
627 .version_id = 1,
628 .minimum_version_id = 1,
629 .fields = (VMStateField[]) {
630 VMSTATE_UINT32(nsccfg, IoTKit),
631 VMSTATE_END_OF_LIST()
632 }
633};
634
635static Property iotkit_properties[] = {
636 DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
637 MemoryRegion *),
638 DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
639 DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
640 DEFINE_PROP_END_OF_LIST()
641};
642
643static void iotkit_reset(DeviceState *dev)
644{
645 IoTKit *s = IOTKIT(dev);
646
647 s->nsccfg = 0;
648}
649
650static void iotkit_class_init(ObjectClass *klass, void *data)
651{
652 DeviceClass *dc = DEVICE_CLASS(klass);
653 IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
654
655 dc->realize = iotkit_realize;
656 dc->vmsd = &iotkit_vmstate;
657 dc->props = iotkit_properties;
658 dc->reset = iotkit_reset;
659 iic->check = iotkit_idau_check;
660}
661
662static const TypeInfo iotkit_info = {
663 .name = TYPE_IOTKIT,
664 .parent = TYPE_SYS_BUS_DEVICE,
665 .instance_size = sizeof(IoTKit),
666 .instance_init = iotkit_init,
667 .class_init = iotkit_class_init,
668 .interfaces = (InterfaceInfo[]) {
669 { TYPE_IDAU_INTERFACE },
670 { }
671 }
672};
673
674static void iotkit_register_types(void)
675{
676 type_register_static(&iotkit_info);
677}
678
679type_init(iotkit_register_types);
680