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