1
2
3
4
5
6
7
8
9
10
11
12#include "qemu/osdep.h"
13#include "qemu/log.h"
14#include "qemu/bitops.h"
15#include "qapi/error.h"
16#include "trace.h"
17#include "hw/sysbus.h"
18#include "hw/registerfields.h"
19#include "hw/arm/armsse.h"
20#include "hw/arm/arm.h"
21
22
23typedef enum SysConfigFormat {
24 IoTKitFormat,
25 SSE200Format,
26} SysConfigFormat;
27
28struct ARMSSEInfo {
29 const char *name;
30 int sram_banks;
31 int num_cpus;
32 uint32_t sys_version;
33 uint32_t cpuwait_rst;
34 SysConfigFormat sys_config_format;
35 bool has_mhus;
36 bool has_ppus;
37 bool has_cachectrl;
38 bool has_cpusecctrl;
39 bool has_cpuid;
40};
41
42static const ARMSSEInfo armsse_variants[] = {
43 {
44 .name = TYPE_IOTKIT,
45 .sram_banks = 1,
46 .num_cpus = 1,
47 .sys_version = 0x41743,
48 .cpuwait_rst = 0,
49 .sys_config_format = IoTKitFormat,
50 .has_mhus = false,
51 .has_ppus = false,
52 .has_cachectrl = false,
53 .has_cpusecctrl = false,
54 .has_cpuid = false,
55 },
56 {
57 .name = TYPE_SSE200,
58 .sram_banks = 4,
59 .num_cpus = 2,
60 .sys_version = 0x22041743,
61 .cpuwait_rst = 2,
62 .sys_config_format = SSE200Format,
63 .has_mhus = true,
64 .has_ppus = true,
65 .has_cachectrl = true,
66 .has_cpusecctrl = true,
67 .has_cpuid = true,
68 },
69};
70
71static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
72{
73
74 uint32_t sys_config;
75
76 switch (info->sys_config_format) {
77 case IoTKitFormat:
78 sys_config = 0;
79 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
80 sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
81 break;
82 case SSE200Format:
83 sys_config = 0;
84 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
85 sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
86 sys_config = deposit32(sys_config, 24, 4, 2);
87 if (info->num_cpus > 1) {
88 sys_config = deposit32(sys_config, 10, 1, 1);
89 sys_config = deposit32(sys_config, 20, 4, info->sram_banks - 1);
90 sys_config = deposit32(sys_config, 28, 4, 2);
91 }
92 break;
93 default:
94 g_assert_not_reached();
95 }
96 return sys_config;
97}
98
99
100#define S32KCLK (32 * 1000)
101
102
103static bool irq_is_common[32] = {
104 [0 ... 5] = true,
105
106 [8 ... 12] = true,
107
108
109 [15 ... 20] = true,
110
111 [22 ... 26] = true,
112
113
114
115};
116
117
118
119
120
121static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
122 const char *name, hwaddr base, hwaddr size, hwaddr orig)
123{
124 memory_region_init_alias(mr, NULL, name, container, orig, size);
125
126 memory_region_add_subregion_overlap(container, base, mr, -1500);
127}
128
129static void irq_status_forwarder(void *opaque, int n, int level)
130{
131 qemu_irq destirq = opaque;
132
133 qemu_set_irq(destirq, level);
134}
135
136static void nsccfg_handler(void *opaque, int n, int level)
137{
138 ARMSSE *s = ARMSSE(opaque);
139
140 s->nsccfg = level;
141}
142
143static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
144{
145
146
147
148
149
150
151 SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
152 DeviceState *armssedev = DEVICE(s);
153 DeviceState *dev_secctl = DEVICE(&s->secctl);
154 DeviceState *dev_splitter = DEVICE(splitter);
155 char *name;
156
157 name = g_strdup_printf("%s_nonsec", ppcname);
158 qdev_pass_gpios(dev_secctl, armssedev, name);
159 g_free(name);
160 name = g_strdup_printf("%s_ap", ppcname);
161 qdev_pass_gpios(dev_secctl, armssedev, name);
162 g_free(name);
163 name = g_strdup_printf("%s_irq_enable", ppcname);
164 qdev_pass_gpios(dev_secctl, armssedev, name);
165 g_free(name);
166 name = g_strdup_printf("%s_irq_clear", ppcname);
167 qdev_pass_gpios(dev_secctl, armssedev, name);
168 g_free(name);
169
170
171
172
173
174
175
176 name = g_strdup_printf("%s_irq_status", ppcname);
177 qdev_connect_gpio_out(dev_splitter, 0,
178 qdev_get_gpio_in_named(dev_secctl,
179 name, 0));
180 qdev_connect_gpio_out(dev_splitter, 1,
181 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
182 s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
183 qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
184 s->irq_status_in[ppcnum], name, 1);
185 g_free(name);
186}
187
188static void armsse_forward_sec_resp_cfg(ARMSSE *s)
189{
190
191
192
193 DeviceState *dev = DEVICE(s);
194 DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
195
196 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
197 s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
198 s->sec_resp_cfg, 1);
199 qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
200}
201
202static void armsse_init(Object *obj)
203{
204 ARMSSE *s = ARMSSE(obj);
205 ARMSSEClass *asc = ARMSSE_GET_CLASS(obj);
206 const ARMSSEInfo *info = asc->info;
207 int i;
208
209 assert(info->sram_banks <= MAX_SRAM_BANKS);
210 assert(info->num_cpus <= SSE_MAX_CPUS);
211
212 memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
213
214 for (i = 0; i < info->num_cpus; i++) {
215
216
217
218
219 char *name;
220
221 name = g_strdup_printf("cluster%d", i);
222 object_initialize_child(obj, name, &s->cluster[i],
223 sizeof(s->cluster[i]), TYPE_CPU_CLUSTER,
224 &error_abort, NULL);
225 qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
226 g_free(name);
227
228 name = g_strdup_printf("armv7m%d", i);
229 sysbus_init_child_obj(OBJECT(&s->cluster[i]), name,
230 &s->armv7m[i], sizeof(s->armv7m), TYPE_ARMV7M);
231 qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
232 ARM_CPU_TYPE_NAME("cortex-m33"));
233 g_free(name);
234 name = g_strdup_printf("arm-sse-cpu-container%d", i);
235 memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
236 g_free(name);
237 if (i > 0) {
238 name = g_strdup_printf("arm-sse-container-alias%d", i);
239 memory_region_init_alias(&s->container_alias[i - 1], obj,
240 name, &s->container, 0, UINT64_MAX);
241 g_free(name);
242 }
243 }
244
245 sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
246 TYPE_IOTKIT_SECCTL);
247 sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
248 TYPE_TZ_PPC);
249 sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
250 TYPE_TZ_PPC);
251 for (i = 0; i < info->sram_banks; i++) {
252 char *name = g_strdup_printf("mpc%d", i);
253 sysbus_init_child_obj(obj, name, &s->mpc[i],
254 sizeof(s->mpc[i]), TYPE_TZ_MPC);
255 g_free(name);
256 }
257 object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
258 sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
259 &error_abort, NULL);
260
261 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
262 char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
263 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
264
265 object_initialize_child(obj, name, splitter, sizeof(*splitter),
266 TYPE_SPLIT_IRQ, &error_abort, NULL);
267 g_free(name);
268 }
269 sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0),
270 TYPE_CMSDK_APB_TIMER);
271 sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
272 TYPE_CMSDK_APB_TIMER);
273 sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
274 TYPE_CMSDK_APB_TIMER);
275 sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
276 TYPE_CMSDK_APB_DUALTIMER);
277 sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
278 sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG);
279 sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog,
280 sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
281 sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
282 sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
283 sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl,
284 sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
285 sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
286 sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
287 if (info->has_mhus) {
288 sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
289 TYPE_ARMSSE_MHU);
290 sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
291 TYPE_ARMSSE_MHU);
292 }
293 if (info->has_ppus) {
294 for (i = 0; i < info->num_cpus; i++) {
295 char *name = g_strdup_printf("CPU%dCORE_PPU", i);
296 int ppuidx = CPU0CORE_PPU + i;
297
298 sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
299 sizeof(s->ppu[ppuidx]),
300 TYPE_UNIMPLEMENTED_DEVICE);
301 g_free(name);
302 }
303 sysbus_init_child_obj(obj, "DBG_PPU", &s->ppu[DBG_PPU],
304 sizeof(s->ppu[DBG_PPU]),
305 TYPE_UNIMPLEMENTED_DEVICE);
306 for (i = 0; i < info->sram_banks; i++) {
307 char *name = g_strdup_printf("RAM%d_PPU", i);
308 int ppuidx = RAM0_PPU + i;
309
310 sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
311 sizeof(s->ppu[ppuidx]),
312 TYPE_UNIMPLEMENTED_DEVICE);
313 g_free(name);
314 }
315 }
316 if (info->has_cachectrl) {
317 for (i = 0; i < info->num_cpus; i++) {
318 char *name = g_strdup_printf("cachectrl%d", i);
319
320 sysbus_init_child_obj(obj, name, &s->cachectrl[i],
321 sizeof(s->cachectrl[i]),
322 TYPE_UNIMPLEMENTED_DEVICE);
323 g_free(name);
324 }
325 }
326 if (info->has_cpusecctrl) {
327 for (i = 0; i < info->num_cpus; i++) {
328 char *name = g_strdup_printf("cpusecctrl%d", i);
329
330 sysbus_init_child_obj(obj, name, &s->cpusecctrl[i],
331 sizeof(s->cpusecctrl[i]),
332 TYPE_UNIMPLEMENTED_DEVICE);
333 g_free(name);
334 }
335 }
336 if (info->has_cpuid) {
337 for (i = 0; i < info->num_cpus; i++) {
338 char *name = g_strdup_printf("cpuid%d", i);
339
340 sysbus_init_child_obj(obj, name, &s->cpuid[i],
341 sizeof(s->cpuid[i]),
342 TYPE_ARMSSE_CPUID);
343 g_free(name);
344 }
345 }
346 object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
347 sizeof(s->nmi_orgate), TYPE_OR_IRQ,
348 &error_abort, NULL);
349 object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
350 sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
351 &error_abort, NULL);
352 object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter,
353 sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ,
354 &error_abort, NULL);
355 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
356 char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
357 SplitIRQ *splitter = &s->ppc_irq_splitter[i];
358
359 object_initialize_child(obj, name, splitter, sizeof(*splitter),
360 TYPE_SPLIT_IRQ, &error_abort, NULL);
361 g_free(name);
362 }
363 if (info->num_cpus > 1) {
364 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
365 if (irq_is_common[i]) {
366 char *name = g_strdup_printf("cpu-irq-splitter%d", i);
367 SplitIRQ *splitter = &s->cpu_irq_splitter[i];
368
369 object_initialize_child(obj, name, splitter, sizeof(*splitter),
370 TYPE_SPLIT_IRQ, &error_abort, NULL);
371 g_free(name);
372 }
373 }
374 }
375}
376
377static void armsse_exp_irq(void *opaque, int n, int level)
378{
379 qemu_irq *irqarray = opaque;
380
381 qemu_set_irq(irqarray[n], level);
382}
383
384static void armsse_mpcexp_status(void *opaque, int n, int level)
385{
386 ARMSSE *s = ARMSSE(opaque);
387 qemu_set_irq(s->mpcexp_status_in[n], level);
388}
389
390static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
391{
392
393
394
395
396 ARMSSEClass *asc = ARMSSE_GET_CLASS(s);
397 const ARMSSEInfo *info = asc->info;
398
399 assert(irq_is_common[irqno]);
400
401 if (info->num_cpus == 1) {
402
403 return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
404 } else {
405
406 return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
407 }
408}
409
410static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
411{
412
413 DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
414
415 qdev_prop_set_string(dev, "name", name);
416 qdev_prop_set_uint64(dev, "size", 0x1000);
417 qdev_init_nofail(dev);
418 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
419}
420
421static void armsse_realize(DeviceState *dev, Error **errp)
422{
423 ARMSSE *s = ARMSSE(dev);
424 ARMSSEClass *asc = ARMSSE_GET_CLASS(dev);
425 const ARMSSEInfo *info = asc->info;
426 int i;
427 MemoryRegion *mr;
428 Error *err = NULL;
429 SysBusDevice *sbd_apb_ppc0;
430 SysBusDevice *sbd_secctl;
431 DeviceState *dev_apb_ppc0;
432 DeviceState *dev_apb_ppc1;
433 DeviceState *dev_secctl;
434 DeviceState *dev_splitter;
435 uint32_t addr_width_max;
436
437 if (!s->board_memory) {
438 error_setg(errp, "memory property was not set");
439 return;
440 }
441
442 if (!s->mainclk_frq) {
443 error_setg(errp, "MAINCLK property was not set");
444 return;
445 }
446
447
448 assert(is_power_of_2(info->sram_banks));
449 addr_width_max = 24 - ctz32(info->sram_banks);
450 if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
451 error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
452 addr_width_max);
453 return;
454 }
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
493
494 for (i = 0; i < info->num_cpus; i++) {
495 DeviceState *cpudev = DEVICE(&s->armv7m[i]);
496 Object *cpuobj = OBJECT(&s->armv7m[i]);
497 int j;
498 char *gpioname;
499
500 qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518 qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
519
520
521
522
523
524
525
526
527
528 if (extract32(info->cpuwait_rst, i, 1)) {
529 object_property_set_bool(cpuobj, true, "start-powered-off", &err);
530 if (err) {
531 error_propagate(errp, err);
532 return;
533 }
534 }
535
536 if (i > 0) {
537 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
538 &s->container_alias[i - 1], -1);
539 } else {
540 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
541 &s->container, -1);
542 }
543 object_property_set_link(cpuobj, OBJECT(&s->cpu_container[i]),
544 "memory", &err);
545 if (err) {
546 error_propagate(errp, err);
547 return;
548 }
549 object_property_set_link(cpuobj, OBJECT(s), "idau", &err);
550 if (err) {
551 error_propagate(errp, err);
552 return;
553 }
554 object_property_set_bool(cpuobj, true, "realized", &err);
555 if (err) {
556 error_propagate(errp, err);
557 return;
558 }
559
560
561
562
563
564
565 object_property_set_bool(OBJECT(&s->cluster[i]),
566 true, "realized", &err);
567 if (err) {
568 error_propagate(errp, err);
569 return;
570 }
571
572
573 s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
574 for (j = 0; j < s->exp_numirq; j++) {
575 s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + 32);
576 }
577 if (i == 0) {
578 gpioname = g_strdup("EXP_IRQ");
579 } else {
580 gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
581 }
582 qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
583 s->exp_irqs[i],
584 gpioname, s->exp_numirq);
585 g_free(gpioname);
586 }
587
588
589 if (info->num_cpus > 1) {
590 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
591 if (irq_is_common[i]) {
592 Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
593 DeviceState *devs = DEVICE(splitter);
594 int cpunum;
595
596 object_property_set_int(splitter, info->num_cpus,
597 "num-lines", &err);
598 if (err) {
599 error_propagate(errp, err);
600 return;
601 }
602 object_property_set_bool(splitter, true, "realized", &err);
603 if (err) {
604 error_propagate(errp, err);
605 return;
606 }
607 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
608 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
609
610 qdev_connect_gpio_out(devs, cpunum,
611 qdev_get_gpio_in(cpudev, i));
612 }
613 }
614 }
615 }
616
617
618 make_alias(s, &s->alias1, &s->container, "alias 1",
619 0x10000000, 0x10000000, 0x00000000);
620 make_alias(s, &s->alias2, &s->container,
621 "alias 2", 0x30000000, 0x10000000, 0x20000000);
622
623
624
625
626
627
628
629 for (i = 0; i < info->num_cpus; i++) {
630 make_alias(s, &s->alias3[i], &s->cpu_container[i],
631 "alias 3", 0x50000000, 0x10000000, 0x40000000);
632 }
633
634
635 object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
636 if (err) {
637 error_propagate(errp, err);
638 return;
639 }
640 sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
641 dev_secctl = DEVICE(&s->secctl);
642 sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
643 sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
644
645 s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
646 qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
647
648
649
650
651
652 object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
653 "num-lines", &err);
654 if (err) {
655 error_propagate(errp, err);
656 return;
657 }
658 object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
659 "realized", &err);
660 if (err) {
661 error_propagate(errp, err);
662 return;
663 }
664 dev_splitter = DEVICE(&s->sec_resp_splitter);
665 qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
666 qdev_get_gpio_in(dev_splitter, 0));
667
668
669 for (i = 0; i < info->sram_banks; i++) {
670 char *ramname = g_strdup_printf("armsse.sram%d", i);
671 SysBusDevice *sbd_mpc;
672 uint32_t sram_bank_size = 1 << s->sram_addr_width;
673
674 memory_region_init_ram(&s->sram[i], NULL, ramname,
675 sram_bank_size, &err);
676 g_free(ramname);
677 if (err) {
678 error_propagate(errp, err);
679 return;
680 }
681 object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]),
682 "downstream", &err);
683 if (err) {
684 error_propagate(errp, err);
685 return;
686 }
687 object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err);
688 if (err) {
689 error_propagate(errp, err);
690 return;
691 }
692
693 sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
694 memory_region_add_subregion(&s->container,
695 0x20000000 + i * sram_bank_size,
696 sysbus_mmio_get_region(sbd_mpc, 1));
697
698 memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
699 sysbus_mmio_get_region(sbd_mpc, 0));
700 }
701
702
703 object_property_set_int(OBJECT(&s->mpc_irq_orgate),
704 IOTS_NUM_EXP_MPC + info->sram_banks,
705 "num-lines", &err);
706 if (err) {
707 error_propagate(errp, err);
708 return;
709 }
710 object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
711 "realized", &err);
712 if (err) {
713 error_propagate(errp, err);
714 return;
715 }
716 qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
717 armsse_get_common_irq_in(s, 9));
718
719
720
721
722
723
724
725
726
727
728
729 qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
730 object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
731 if (err) {
732 error_propagate(errp, err);
733 return;
734 }
735 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
736 armsse_get_common_irq_in(s, 3));
737 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
738 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
739 if (err) {
740 error_propagate(errp, err);
741 return;
742 }
743
744 qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
745 object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
746 if (err) {
747 error_propagate(errp, err);
748 return;
749 }
750 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
751 armsse_get_common_irq_in(s, 4));
752 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
753 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
754 if (err) {
755 error_propagate(errp, err);
756 return;
757 }
758
759
760 qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
761 object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
762 if (err) {
763 error_propagate(errp, err);
764 return;
765 }
766 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
767 armsse_get_common_irq_in(s, 5));
768 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
769 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
770 if (err) {
771 error_propagate(errp, err);
772 return;
773 }
774
775 if (info->has_mhus) {
776
777
778
779
780
781
782
783 assert(info->num_cpus == ARRAY_SIZE(s->mhu));
784
785 for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
786 char *port;
787 int cpunum;
788 SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]);
789
790 object_property_set_bool(OBJECT(&s->mhu[i]), true,
791 "realized", &err);
792 if (err) {
793 error_propagate(errp, err);
794 return;
795 }
796 port = g_strdup_printf("port[%d]", i + 3);
797 mr = sysbus_mmio_get_region(mhu_sbd, 0);
798 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
799 port, &err);
800 g_free(port);
801 if (err) {
802 error_propagate(errp, err);
803 return;
804 }
805
806
807
808
809
810
811
812
813 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
814 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
815
816 sysbus_connect_irq(mhu_sbd, cpunum,
817 qdev_get_gpio_in(cpudev, 6 + i));
818 }
819 }
820 }
821
822 object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
823 if (err) {
824 error_propagate(errp, err);
825 return;
826 }
827
828 sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
829 dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
830
831 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
832 memory_region_add_subregion(&s->container, 0x40000000, mr);
833 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
834 memory_region_add_subregion(&s->container, 0x40001000, mr);
835 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
836 memory_region_add_subregion(&s->container, 0x40002000, mr);
837 if (info->has_mhus) {
838 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
839 memory_region_add_subregion(&s->container, 0x40003000, mr);
840 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
841 memory_region_add_subregion(&s->container, 0x40004000, mr);
842 }
843 for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
844 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
845 qdev_get_gpio_in_named(dev_apb_ppc0,
846 "cfg_nonsec", i));
847 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
848 qdev_get_gpio_in_named(dev_apb_ppc0,
849 "cfg_ap", i));
850 }
851 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
852 qdev_get_gpio_in_named(dev_apb_ppc0,
853 "irq_enable", 0));
854 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
855 qdev_get_gpio_in_named(dev_apb_ppc0,
856 "irq_clear", 0));
857 qdev_connect_gpio_out(dev_splitter, 0,
858 qdev_get_gpio_in_named(dev_apb_ppc0,
859 "cfg_sec_resp", 0));
860
861
862
863
864
865 object_property_set_int(OBJECT(&s->ppc_irq_orgate),
866 NUM_PPCS, "num-lines", &err);
867 if (err) {
868 error_propagate(errp, err);
869 return;
870 }
871 object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
872 "realized", &err);
873 if (err) {
874 error_propagate(errp, err);
875 return;
876 }
877 qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
878 armsse_get_common_irq_in(s, 10));
879
880
881
882
883
884
885
886
887 if (info->has_cachectrl) {
888 for (i = 0; i < info->num_cpus; i++) {
889 char *name = g_strdup_printf("cachectrl%d", i);
890 MemoryRegion *mr;
891
892 qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
893 g_free(name);
894 qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
895 object_property_set_bool(OBJECT(&s->cachectrl[i]), true,
896 "realized", &err);
897 if (err) {
898 error_propagate(errp, err);
899 return;
900 }
901
902 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
903 memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
904 }
905 }
906 if (info->has_cpusecctrl) {
907 for (i = 0; i < info->num_cpus; i++) {
908 char *name = g_strdup_printf("CPUSECCTRL%d", i);
909 MemoryRegion *mr;
910
911 qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
912 g_free(name);
913 qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
914 object_property_set_bool(OBJECT(&s->cpusecctrl[i]), true,
915 "realized", &err);
916 if (err) {
917 error_propagate(errp, err);
918 return;
919 }
920
921 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
922 memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
923 }
924 }
925 if (info->has_cpuid) {
926 for (i = 0; i < info->num_cpus; i++) {
927 MemoryRegion *mr;
928
929 qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
930 object_property_set_bool(OBJECT(&s->cpuid[i]), true,
931 "realized", &err);
932 if (err) {
933 error_propagate(errp, err);
934 return;
935 }
936
937 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
938 memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
939 }
940 }
941
942
943
944
945
946 qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
947 object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
948 if (err) {
949 error_propagate(errp, err);
950 return;
951 }
952 sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
953 armsse_get_common_irq_in(s, 2));
954 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
955 object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
956 if (err) {
957 error_propagate(errp, err);
958 return;
959 }
960
961 object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
962 if (err) {
963 error_propagate(errp, err);
964 return;
965 }
966 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
967 memory_region_add_subregion(&s->container, 0x4002f000, mr);
968
969 dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
970 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
971 qdev_get_gpio_in_named(dev_apb_ppc1,
972 "cfg_nonsec", 0));
973 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
974 qdev_get_gpio_in_named(dev_apb_ppc1,
975 "cfg_ap", 0));
976 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
977 qdev_get_gpio_in_named(dev_apb_ppc1,
978 "irq_enable", 0));
979 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
980 qdev_get_gpio_in_named(dev_apb_ppc1,
981 "irq_clear", 0));
982 qdev_connect_gpio_out(dev_splitter, 1,
983 qdev_get_gpio_in_named(dev_apb_ppc1,
984 "cfg_sec_resp", 0));
985
986 object_property_set_int(OBJECT(&s->sysinfo), info->sys_version,
987 "SYS_VERSION", &err);
988 if (err) {
989 error_propagate(errp, err);
990 return;
991 }
992 object_property_set_int(OBJECT(&s->sysinfo),
993 armsse_sys_config_value(s, info),
994 "SYS_CONFIG", &err);
995 if (err) {
996 error_propagate(errp, err);
997 return;
998 }
999 object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
1000 if (err) {
1001 error_propagate(errp, err);
1002 return;
1003 }
1004
1005 sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
1006
1007 object_property_set_int(OBJECT(&s->sysctl), info->sys_version,
1008 "SYS_VERSION", &err);
1009 object_property_set_int(OBJECT(&s->sysctl), info->cpuwait_rst,
1010 "CPUWAIT_RST", &err);
1011 object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
1012 "INITSVTOR0_RST", &err);
1013 object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
1014 "INITSVTOR1_RST", &err);
1015 object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
1016 if (err) {
1017 error_propagate(errp, err);
1018 return;
1019 }
1020 sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
1021
1022 if (info->has_ppus) {
1023
1024 for (i = 0; i < info->num_cpus; i++) {
1025 char *name = g_strdup_printf("CPU%dCORE_PPU", i);
1026
1027 map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
1028
1029
1030
1031
1032 g_free(name);
1033 }
1034 map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
1035
1036 for (i = 0; i < info->sram_banks; i++) {
1037 char *name = g_strdup_printf("RAM%d_PPU", i);
1038
1039 map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
1040 g_free(name);
1041 }
1042 }
1043
1044
1045 object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
1046 if (err) {
1047 error_propagate(errp, err);
1048 return;
1049 }
1050 object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err);
1051 if (err) {
1052 error_propagate(errp, err);
1053 return;
1054 }
1055 qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
1056 qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
1057
1058 qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
1059 object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err);
1060 if (err) {
1061 error_propagate(errp, err);
1062 return;
1063 }
1064 sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
1065 qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
1066 sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
1067
1068
1069
1070 qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
1071 object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
1072 if (err) {
1073 error_propagate(errp, err);
1074 return;
1075 }
1076 sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
1077 armsse_get_common_irq_in(s, 1));
1078 sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
1079
1080 qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
1081 object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err);
1082 if (err) {
1083 error_propagate(errp, err);
1084 return;
1085 }
1086 sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
1087 qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
1088 sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
1089
1090 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
1091 Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
1092
1093 object_property_set_int(splitter, 2, "num-lines", &err);
1094 if (err) {
1095 error_propagate(errp, err);
1096 return;
1097 }
1098 object_property_set_bool(splitter, true, "realized", &err);
1099 if (err) {
1100 error_propagate(errp, err);
1101 return;
1102 }
1103 }
1104
1105 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
1106 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
1107
1108 armsse_forward_ppc(s, ppcname, i);
1109 g_free(ppcname);
1110 }
1111
1112 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
1113 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
1114
1115 armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
1116 g_free(ppcname);
1117 }
1118
1119 for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
1120
1121 DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
1122 char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
1123 i - NUM_EXTERNAL_PPCS);
1124 TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
1125
1126 qdev_connect_gpio_out(devs, 0,
1127 qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
1128 qdev_connect_gpio_out(devs, 1,
1129 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
1130 qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
1131 qdev_get_gpio_in(devs, 0));
1132 g_free(gpioname);
1133 }
1134
1135
1136 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
1137 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
1138 DeviceState *dev_splitter = DEVICE(splitter);
1139
1140 object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
1141 if (err) {
1142 error_propagate(errp, err);
1143 return;
1144 }
1145 object_property_set_bool(OBJECT(splitter), true, "realized", &err);
1146 if (err) {
1147 error_propagate(errp, err);
1148 return;
1149 }
1150
1151 if (i < IOTS_NUM_EXP_MPC) {
1152
1153 s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
1154 qdev_connect_gpio_out(dev_splitter, 0,
1155 qdev_get_gpio_in_named(dev_secctl,
1156 "mpcexp_status", i));
1157 } else {
1158
1159 qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
1160 "irq", 0,
1161 qdev_get_gpio_in(dev_splitter, 0));
1162 qdev_connect_gpio_out(dev_splitter, 0,
1163 qdev_get_gpio_in_named(dev_secctl,
1164 "mpc_status", 0));
1165 }
1166
1167 qdev_connect_gpio_out(dev_splitter, 1,
1168 qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
1169 }
1170
1171
1172
1173 qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
1174 IOTS_NUM_EXP_MPC);
1175
1176 armsse_forward_sec_resp_cfg(s);
1177
1178
1179 qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
1180 qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
1181 qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
1182 qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
1183 armsse_get_common_irq_in(s, 11));
1184
1185
1186
1187
1188
1189
1190
1191 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
1192
1193 system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
1194}
1195
1196static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
1197 int *iregion, bool *exempt, bool *ns, bool *nsc)
1198{
1199
1200
1201
1202
1203
1204 ARMSSE *s = ARMSSE(ii);
1205 int region = extract32(address, 28, 4);
1206
1207 *ns = !(region & 1);
1208 *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
1209
1210 *exempt = (address & 0xeff00000) == 0xe0000000;
1211 *iregion = region;
1212}
1213
1214static const VMStateDescription armsse_vmstate = {
1215 .name = "iotkit",
1216 .version_id = 1,
1217 .minimum_version_id = 1,
1218 .fields = (VMStateField[]) {
1219 VMSTATE_UINT32(nsccfg, ARMSSE),
1220 VMSTATE_END_OF_LIST()
1221 }
1222};
1223
1224static Property armsse_properties[] = {
1225 DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
1226 MemoryRegion *),
1227 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
1228 DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
1229 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
1230 DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
1231 DEFINE_PROP_END_OF_LIST()
1232};
1233
1234static void armsse_reset(DeviceState *dev)
1235{
1236 ARMSSE *s = ARMSSE(dev);
1237
1238 s->nsccfg = 0;
1239}
1240
1241static void armsse_class_init(ObjectClass *klass, void *data)
1242{
1243 DeviceClass *dc = DEVICE_CLASS(klass);
1244 IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
1245 ARMSSEClass *asc = ARMSSE_CLASS(klass);
1246
1247 dc->realize = armsse_realize;
1248 dc->vmsd = &armsse_vmstate;
1249 dc->props = armsse_properties;
1250 dc->reset = armsse_reset;
1251 iic->check = armsse_idau_check;
1252 asc->info = data;
1253}
1254
1255static const TypeInfo armsse_info = {
1256 .name = TYPE_ARMSSE,
1257 .parent = TYPE_SYS_BUS_DEVICE,
1258 .instance_size = sizeof(ARMSSE),
1259 .instance_init = armsse_init,
1260 .abstract = true,
1261 .interfaces = (InterfaceInfo[]) {
1262 { TYPE_IDAU_INTERFACE },
1263 { }
1264 }
1265};
1266
1267static void armsse_register_types(void)
1268{
1269 int i;
1270
1271 type_register_static(&armsse_info);
1272
1273 for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
1274 TypeInfo ti = {
1275 .name = armsse_variants[i].name,
1276 .parent = TYPE_ARMSSE,
1277 .class_init = armsse_class_init,
1278 .class_data = (void *)&armsse_variants[i],
1279 };
1280 type_register(&ti);
1281 }
1282}
1283
1284type_init(armsse_register_types);
1285