1
2
3
4
5
6
7
8
9
10
11
12#include "qemu/osdep.h"
13#include "qemu/log.h"
14#include "qemu/module.h"
15#include "qemu/bitops.h"
16#include "qemu/units.h"
17#include "qapi/error.h"
18#include "trace.h"
19#include "hw/sysbus.h"
20#include "migration/vmstate.h"
21#include "hw/registerfields.h"
22#include "hw/arm/armsse.h"
23#include "hw/arm/armsse-version.h"
24#include "hw/arm/boot.h"
25#include "hw/irq.h"
26#include "hw/qdev-clock.h"
27
28
29
30
31
32
33
34
35
36#define NO_IRQ -1
37#define NO_PPC -1
38
39
40
41
42
43#define NMI_0 10000
44#define NMI_1 10001
45
46typedef struct ARMSSEDeviceInfo {
47 const char *name;
48 const char *type;
49 unsigned int index;
50 hwaddr addr;
51 hwaddr size;
52 int ppc;
53 int ppc_port;
54 int irq;
55 bool slowclk;
56} ARMSSEDeviceInfo;
57
58struct ARMSSEInfo {
59 const char *name;
60 const char *cpu_type;
61 uint32_t sse_version;
62 int sram_banks;
63 uint32_t sram_bank_base;
64 int num_cpus;
65 uint32_t sys_version;
66 uint32_t iidr;
67 uint32_t cpuwait_rst;
68 bool has_mhus;
69 bool has_cachectrl;
70 bool has_cpusecctrl;
71 bool has_cpuid;
72 bool has_cpu_pwrctrl;
73 bool has_sse_counter;
74 bool has_tcms;
75 Property *props;
76 const ARMSSEDeviceInfo *devinfo;
77 const bool *irq_is_common;
78};
79
80static Property iotkit_properties[] = {
81 DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
82 MemoryRegion *),
83 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
84 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
85 DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
86 DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
87 DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
88 DEFINE_PROP_END_OF_LIST()
89};
90
91static Property sse200_properties[] = {
92 DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
93 MemoryRegion *),
94 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
95 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
96 DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
97 DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
98 DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], false),
99 DEFINE_PROP_BOOL("CPU1_FPU", ARMSSE, cpu_fpu[1], true),
100 DEFINE_PROP_BOOL("CPU1_DSP", ARMSSE, cpu_dsp[1], true),
101 DEFINE_PROP_END_OF_LIST()
102};
103
104static Property sse300_properties[] = {
105 DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
106 MemoryRegion *),
107 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
108 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 18),
109 DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
110 DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
111 DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
112 DEFINE_PROP_END_OF_LIST()
113};
114
115static const ARMSSEDeviceInfo iotkit_devices[] = {
116 {
117 .name = "timer0",
118 .type = TYPE_CMSDK_APB_TIMER,
119 .index = 0,
120 .addr = 0x40000000,
121 .ppc = 0,
122 .ppc_port = 0,
123 .irq = 3,
124 },
125 {
126 .name = "timer1",
127 .type = TYPE_CMSDK_APB_TIMER,
128 .index = 1,
129 .addr = 0x40001000,
130 .ppc = 0,
131 .ppc_port = 1,
132 .irq = 4,
133 },
134 {
135 .name = "s32ktimer",
136 .type = TYPE_CMSDK_APB_TIMER,
137 .index = 2,
138 .addr = 0x4002f000,
139 .ppc = 1,
140 .ppc_port = 0,
141 .irq = 2,
142 .slowclk = true,
143 },
144 {
145 .name = "dualtimer",
146 .type = TYPE_CMSDK_APB_DUALTIMER,
147 .index = 0,
148 .addr = 0x40002000,
149 .ppc = 0,
150 .ppc_port = 2,
151 .irq = 5,
152 },
153 {
154 .name = "s32kwatchdog",
155 .type = TYPE_CMSDK_APB_WATCHDOG,
156 .index = 0,
157 .addr = 0x5002e000,
158 .ppc = NO_PPC,
159 .irq = NMI_0,
160 .slowclk = true,
161 },
162 {
163 .name = "nswatchdog",
164 .type = TYPE_CMSDK_APB_WATCHDOG,
165 .index = 1,
166 .addr = 0x40081000,
167 .ppc = NO_PPC,
168 .irq = 1,
169 },
170 {
171 .name = "swatchdog",
172 .type = TYPE_CMSDK_APB_WATCHDOG,
173 .index = 2,
174 .addr = 0x50081000,
175 .ppc = NO_PPC,
176 .irq = NMI_1,
177 },
178 {
179 .name = "armsse-sysinfo",
180 .type = TYPE_IOTKIT_SYSINFO,
181 .index = 0,
182 .addr = 0x40020000,
183 .ppc = NO_PPC,
184 .irq = NO_IRQ,
185 },
186 {
187 .name = "armsse-sysctl",
188 .type = TYPE_IOTKIT_SYSCTL,
189 .index = 0,
190 .addr = 0x50021000,
191 .ppc = NO_PPC,
192 .irq = NO_IRQ,
193 },
194 {
195 .name = NULL,
196 }
197};
198
199static const ARMSSEDeviceInfo sse200_devices[] = {
200 {
201 .name = "timer0",
202 .type = TYPE_CMSDK_APB_TIMER,
203 .index = 0,
204 .addr = 0x40000000,
205 .ppc = 0,
206 .ppc_port = 0,
207 .irq = 3,
208 },
209 {
210 .name = "timer1",
211 .type = TYPE_CMSDK_APB_TIMER,
212 .index = 1,
213 .addr = 0x40001000,
214 .ppc = 0,
215 .ppc_port = 1,
216 .irq = 4,
217 },
218 {
219 .name = "s32ktimer",
220 .type = TYPE_CMSDK_APB_TIMER,
221 .index = 2,
222 .addr = 0x4002f000,
223 .ppc = 1,
224 .ppc_port = 0,
225 .irq = 2,
226 .slowclk = true,
227 },
228 {
229 .name = "dualtimer",
230 .type = TYPE_CMSDK_APB_DUALTIMER,
231 .index = 0,
232 .addr = 0x40002000,
233 .ppc = 0,
234 .ppc_port = 2,
235 .irq = 5,
236 },
237 {
238 .name = "s32kwatchdog",
239 .type = TYPE_CMSDK_APB_WATCHDOG,
240 .index = 0,
241 .addr = 0x5002e000,
242 .ppc = NO_PPC,
243 .irq = NMI_0,
244 .slowclk = true,
245 },
246 {
247 .name = "nswatchdog",
248 .type = TYPE_CMSDK_APB_WATCHDOG,
249 .index = 1,
250 .addr = 0x40081000,
251 .ppc = NO_PPC,
252 .irq = 1,
253 },
254 {
255 .name = "swatchdog",
256 .type = TYPE_CMSDK_APB_WATCHDOG,
257 .index = 2,
258 .addr = 0x50081000,
259 .ppc = NO_PPC,
260 .irq = NMI_1,
261 },
262 {
263 .name = "armsse-sysinfo",
264 .type = TYPE_IOTKIT_SYSINFO,
265 .index = 0,
266 .addr = 0x40020000,
267 .ppc = NO_PPC,
268 .irq = NO_IRQ,
269 },
270 {
271 .name = "armsse-sysctl",
272 .type = TYPE_IOTKIT_SYSCTL,
273 .index = 0,
274 .addr = 0x50021000,
275 .ppc = NO_PPC,
276 .irq = NO_IRQ,
277 },
278 {
279 .name = "CPU0CORE_PPU",
280 .type = TYPE_UNIMPLEMENTED_DEVICE,
281 .index = 0,
282 .addr = 0x50023000,
283 .size = 0x1000,
284 .ppc = NO_PPC,
285 .irq = NO_IRQ,
286 },
287 {
288 .name = "CPU1CORE_PPU",
289 .type = TYPE_UNIMPLEMENTED_DEVICE,
290 .index = 1,
291 .addr = 0x50025000,
292 .size = 0x1000,
293 .ppc = NO_PPC,
294 .irq = NO_IRQ,
295 },
296 {
297 .name = "DBG_PPU",
298 .type = TYPE_UNIMPLEMENTED_DEVICE,
299 .index = 2,
300 .addr = 0x50029000,
301 .size = 0x1000,
302 .ppc = NO_PPC,
303 .irq = NO_IRQ,
304 },
305 {
306 .name = "RAM0_PPU",
307 .type = TYPE_UNIMPLEMENTED_DEVICE,
308 .index = 3,
309 .addr = 0x5002a000,
310 .size = 0x1000,
311 .ppc = NO_PPC,
312 .irq = NO_IRQ,
313 },
314 {
315 .name = "RAM1_PPU",
316 .type = TYPE_UNIMPLEMENTED_DEVICE,
317 .index = 4,
318 .addr = 0x5002b000,
319 .size = 0x1000,
320 .ppc = NO_PPC,
321 .irq = NO_IRQ,
322 },
323 {
324 .name = "RAM2_PPU",
325 .type = TYPE_UNIMPLEMENTED_DEVICE,
326 .index = 5,
327 .addr = 0x5002c000,
328 .size = 0x1000,
329 .ppc = NO_PPC,
330 .irq = NO_IRQ,
331 },
332 {
333 .name = "RAM3_PPU",
334 .type = TYPE_UNIMPLEMENTED_DEVICE,
335 .index = 6,
336 .addr = 0x5002d000,
337 .size = 0x1000,
338 .ppc = NO_PPC,
339 .irq = NO_IRQ,
340 },
341 {
342 .name = "SYS_PPU",
343 .type = TYPE_UNIMPLEMENTED_DEVICE,
344 .index = 7,
345 .addr = 0x50022000,
346 .size = 0x1000,
347 .ppc = NO_PPC,
348 .irq = NO_IRQ,
349 },
350 {
351 .name = NULL,
352 }
353};
354
355static const ARMSSEDeviceInfo sse300_devices[] = {
356 {
357 .name = "timer0",
358 .type = TYPE_SSE_TIMER,
359 .index = 0,
360 .addr = 0x48000000,
361 .ppc = 0,
362 .ppc_port = 0,
363 .irq = 3,
364 },
365 {
366 .name = "timer1",
367 .type = TYPE_SSE_TIMER,
368 .index = 1,
369 .addr = 0x48001000,
370 .ppc = 0,
371 .ppc_port = 1,
372 .irq = 4,
373 },
374 {
375 .name = "timer2",
376 .type = TYPE_SSE_TIMER,
377 .index = 2,
378 .addr = 0x48002000,
379 .ppc = 0,
380 .ppc_port = 2,
381 .irq = 5,
382 },
383 {
384 .name = "timer3",
385 .type = TYPE_SSE_TIMER,
386 .index = 3,
387 .addr = 0x48003000,
388 .ppc = 0,
389 .ppc_port = 5,
390 .irq = 27,
391 },
392 {
393 .name = "s32ktimer",
394 .type = TYPE_CMSDK_APB_TIMER,
395 .index = 0,
396 .addr = 0x4802f000,
397 .ppc = 1,
398 .ppc_port = 0,
399 .irq = 2,
400 .slowclk = true,
401 },
402 {
403 .name = "s32kwatchdog",
404 .type = TYPE_CMSDK_APB_WATCHDOG,
405 .index = 0,
406 .addr = 0x4802e000,
407 .ppc = NO_PPC,
408 .irq = NMI_0,
409 .slowclk = true,
410 },
411 {
412 .name = "watchdog",
413 .type = TYPE_UNIMPLEMENTED_DEVICE,
414 .index = 0,
415 .addr = 0x48040000,
416 .size = 0x2000,
417 .ppc = NO_PPC,
418 .irq = NO_IRQ,
419 },
420 {
421 .name = "armsse-sysinfo",
422 .type = TYPE_IOTKIT_SYSINFO,
423 .index = 0,
424 .addr = 0x48020000,
425 .ppc = NO_PPC,
426 .irq = NO_IRQ,
427 },
428 {
429 .name = "armsse-sysctl",
430 .type = TYPE_IOTKIT_SYSCTL,
431 .index = 0,
432 .addr = 0x58021000,
433 .ppc = NO_PPC,
434 .irq = NO_IRQ,
435 },
436 {
437 .name = "SYS_PPU",
438 .type = TYPE_UNIMPLEMENTED_DEVICE,
439 .index = 1,
440 .addr = 0x58022000,
441 .size = 0x1000,
442 .ppc = NO_PPC,
443 .irq = NO_IRQ,
444 },
445 {
446 .name = "CPU0CORE_PPU",
447 .type = TYPE_UNIMPLEMENTED_DEVICE,
448 .index = 2,
449 .addr = 0x50023000,
450 .size = 0x1000,
451 .ppc = NO_PPC,
452 .irq = NO_IRQ,
453 },
454 {
455 .name = "MGMT_PPU",
456 .type = TYPE_UNIMPLEMENTED_DEVICE,
457 .index = 3,
458 .addr = 0x50028000,
459 .size = 0x1000,
460 .ppc = NO_PPC,
461 .irq = NO_IRQ,
462 },
463 {
464 .name = "DEBUG_PPU",
465 .type = TYPE_UNIMPLEMENTED_DEVICE,
466 .index = 4,
467 .addr = 0x50029000,
468 .size = 0x1000,
469 .ppc = NO_PPC,
470 .irq = NO_IRQ,
471 },
472 {
473 .name = NULL,
474 }
475};
476
477
478static const bool sse200_irq_is_common[32] = {
479 [0 ... 5] = true,
480
481 [8 ... 12] = true,
482
483
484 [15 ... 20] = true,
485
486 [22 ... 26] = true,
487
488
489
490};
491
492static const bool sse300_irq_is_common[32] = {
493 [0 ... 5] = true,
494
495 [8 ... 12] = true,
496
497 [14 ... 16] = true,
498
499 [26 ... 27] = true,
500
501
502};
503
504static const ARMSSEInfo armsse_variants[] = {
505 {
506 .name = TYPE_IOTKIT,
507 .sse_version = ARMSSE_IOTKIT,
508 .cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"),
509 .sram_banks = 1,
510 .sram_bank_base = 0x20000000,
511 .num_cpus = 1,
512 .sys_version = 0x41743,
513 .iidr = 0,
514 .cpuwait_rst = 0,
515 .has_mhus = false,
516 .has_cachectrl = false,
517 .has_cpusecctrl = false,
518 .has_cpuid = false,
519 .has_cpu_pwrctrl = false,
520 .has_sse_counter = false,
521 .has_tcms = false,
522 .props = iotkit_properties,
523 .devinfo = iotkit_devices,
524 .irq_is_common = sse200_irq_is_common,
525 },
526 {
527 .name = TYPE_SSE200,
528 .sse_version = ARMSSE_SSE200,
529 .cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"),
530 .sram_banks = 4,
531 .sram_bank_base = 0x20000000,
532 .num_cpus = 2,
533 .sys_version = 0x22041743,
534 .iidr = 0,
535 .cpuwait_rst = 2,
536 .has_mhus = true,
537 .has_cachectrl = true,
538 .has_cpusecctrl = true,
539 .has_cpuid = true,
540 .has_cpu_pwrctrl = false,
541 .has_sse_counter = false,
542 .has_tcms = false,
543 .props = sse200_properties,
544 .devinfo = sse200_devices,
545 .irq_is_common = sse200_irq_is_common,
546 },
547 {
548 .name = TYPE_SSE300,
549 .sse_version = ARMSSE_SSE300,
550 .cpu_type = ARM_CPU_TYPE_NAME("cortex-m55"),
551 .sram_banks = 2,
552 .sram_bank_base = 0x21000000,
553 .num_cpus = 1,
554 .sys_version = 0x7e00043b,
555 .iidr = 0x74a0043b,
556 .cpuwait_rst = 0,
557 .has_mhus = false,
558 .has_cachectrl = false,
559 .has_cpusecctrl = true,
560 .has_cpuid = true,
561 .has_cpu_pwrctrl = true,
562 .has_sse_counter = true,
563 .has_tcms = true,
564 .props = sse300_properties,
565 .devinfo = sse300_devices,
566 .irq_is_common = sse300_irq_is_common,
567 },
568};
569
570static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
571{
572
573 uint32_t sys_config;
574
575 switch (info->sse_version) {
576 case ARMSSE_IOTKIT:
577 sys_config = 0;
578 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
579 sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
580 break;
581 case ARMSSE_SSE200:
582 sys_config = 0;
583 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
584 sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
585 sys_config = deposit32(sys_config, 24, 4, 2);
586 if (info->num_cpus > 1) {
587 sys_config = deposit32(sys_config, 10, 1, 1);
588 sys_config = deposit32(sys_config, 20, 4, info->sram_banks - 1);
589 sys_config = deposit32(sys_config, 28, 4, 2);
590 }
591 break;
592 case ARMSSE_SSE300:
593 sys_config = 0;
594 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
595 sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
596 sys_config = deposit32(sys_config, 16, 3, 3);
597 break;
598 default:
599 g_assert_not_reached();
600 }
601 return sys_config;
602}
603
604
605#define S32KCLK (32 * 1000)
606
607
608
609
610
611static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
612 const char *name, hwaddr base, hwaddr size, hwaddr orig)
613{
614 memory_region_init_alias(mr, NULL, name, container, orig, size);
615
616 memory_region_add_subregion_overlap(container, base, mr, -1500);
617}
618
619static void irq_status_forwarder(void *opaque, int n, int level)
620{
621 qemu_irq destirq = opaque;
622
623 qemu_set_irq(destirq, level);
624}
625
626static void nsccfg_handler(void *opaque, int n, int level)
627{
628 ARMSSE *s = ARM_SSE(opaque);
629
630 s->nsccfg = level;
631}
632
633static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
634{
635
636
637
638
639
640
641 SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
642 DeviceState *armssedev = DEVICE(s);
643 DeviceState *dev_secctl = DEVICE(&s->secctl);
644 DeviceState *dev_splitter = DEVICE(splitter);
645 char *name;
646
647 name = g_strdup_printf("%s_nonsec", ppcname);
648 qdev_pass_gpios(dev_secctl, armssedev, name);
649 g_free(name);
650 name = g_strdup_printf("%s_ap", ppcname);
651 qdev_pass_gpios(dev_secctl, armssedev, name);
652 g_free(name);
653 name = g_strdup_printf("%s_irq_enable", ppcname);
654 qdev_pass_gpios(dev_secctl, armssedev, name);
655 g_free(name);
656 name = g_strdup_printf("%s_irq_clear", ppcname);
657 qdev_pass_gpios(dev_secctl, armssedev, name);
658 g_free(name);
659
660
661
662
663
664
665
666 name = g_strdup_printf("%s_irq_status", ppcname);
667 qdev_connect_gpio_out(dev_splitter, 0,
668 qdev_get_gpio_in_named(dev_secctl,
669 name, 0));
670 qdev_connect_gpio_out(dev_splitter, 1,
671 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
672 s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
673 qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
674 s->irq_status_in[ppcnum], name, 1);
675 g_free(name);
676}
677
678static void armsse_forward_sec_resp_cfg(ARMSSE *s)
679{
680
681
682
683 DeviceState *dev = DEVICE(s);
684 DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
685
686 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
687 s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
688 s->sec_resp_cfg, 1);
689 qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
690}
691
692static void armsse_init(Object *obj)
693{
694 ARMSSE *s = ARM_SSE(obj);
695 ARMSSEClass *asc = ARM_SSE_GET_CLASS(obj);
696 const ARMSSEInfo *info = asc->info;
697 const ARMSSEDeviceInfo *devinfo;
698 int i;
699
700 assert(info->sram_banks <= MAX_SRAM_BANKS);
701 assert(info->num_cpus <= SSE_MAX_CPUS);
702
703 s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL, 0);
704 s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
705
706 memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
707
708 for (i = 0; i < info->num_cpus; i++) {
709
710
711
712
713 char *name;
714
715 name = g_strdup_printf("cluster%d", i);
716 object_initialize_child(obj, name, &s->cluster[i], TYPE_CPU_CLUSTER);
717 qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
718 g_free(name);
719
720 name = g_strdup_printf("armv7m%d", i);
721 object_initialize_child(OBJECT(&s->cluster[i]), name, &s->armv7m[i],
722 TYPE_ARMV7M);
723 qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type", info->cpu_type);
724 g_free(name);
725 name = g_strdup_printf("arm-sse-cpu-container%d", i);
726 memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
727 g_free(name);
728 if (i > 0) {
729 name = g_strdup_printf("arm-sse-container-alias%d", i);
730 memory_region_init_alias(&s->container_alias[i - 1], obj,
731 name, &s->container, 0, UINT64_MAX);
732 g_free(name);
733 }
734 }
735
736 for (devinfo = info->devinfo; devinfo->name; devinfo++) {
737 assert(devinfo->ppc == NO_PPC || devinfo->ppc < ARRAY_SIZE(s->apb_ppc));
738 if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
739 assert(devinfo->index < ARRAY_SIZE(s->timer));
740 object_initialize_child(obj, devinfo->name,
741 &s->timer[devinfo->index],
742 TYPE_CMSDK_APB_TIMER);
743 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
744 assert(devinfo->index == 0);
745 object_initialize_child(obj, devinfo->name, &s->dualtimer,
746 TYPE_CMSDK_APB_DUALTIMER);
747 } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
748 assert(devinfo->index < ARRAY_SIZE(s->sse_timer));
749 object_initialize_child(obj, devinfo->name,
750 &s->sse_timer[devinfo->index],
751 TYPE_SSE_TIMER);
752 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
753 assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
754 object_initialize_child(obj, devinfo->name,
755 &s->cmsdk_watchdog[devinfo->index],
756 TYPE_CMSDK_APB_WATCHDOG);
757 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
758 assert(devinfo->index == 0);
759 object_initialize_child(obj, devinfo->name, &s->sysinfo,
760 TYPE_IOTKIT_SYSINFO);
761 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
762 assert(devinfo->index == 0);
763 object_initialize_child(obj, devinfo->name, &s->sysctl,
764 TYPE_IOTKIT_SYSCTL);
765 } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
766 assert(devinfo->index < ARRAY_SIZE(s->unimp));
767 object_initialize_child(obj, devinfo->name,
768 &s->unimp[devinfo->index],
769 TYPE_UNIMPLEMENTED_DEVICE);
770 } else {
771 g_assert_not_reached();
772 }
773 }
774
775 object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
776
777 for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
778 g_autofree char *name = g_strdup_printf("apb-ppc%d", i);
779 object_initialize_child(obj, name, &s->apb_ppc[i], TYPE_TZ_PPC);
780 }
781
782 for (i = 0; i < info->sram_banks; i++) {
783 char *name = g_strdup_printf("mpc%d", i);
784 object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC);
785 g_free(name);
786 }
787 object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
788 TYPE_OR_IRQ);
789
790 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
791 char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
792 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
793
794 object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
795 g_free(name);
796 }
797
798 if (info->has_mhus) {
799 object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
800 object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
801 }
802 if (info->has_cachectrl) {
803 for (i = 0; i < info->num_cpus; i++) {
804 char *name = g_strdup_printf("cachectrl%d", i);
805
806 object_initialize_child(obj, name, &s->cachectrl[i],
807 TYPE_UNIMPLEMENTED_DEVICE);
808 g_free(name);
809 }
810 }
811 if (info->has_cpusecctrl) {
812 for (i = 0; i < info->num_cpus; i++) {
813 char *name = g_strdup_printf("cpusecctrl%d", i);
814
815 object_initialize_child(obj, name, &s->cpusecctrl[i],
816 TYPE_UNIMPLEMENTED_DEVICE);
817 g_free(name);
818 }
819 }
820 if (info->has_cpuid) {
821 for (i = 0; i < info->num_cpus; i++) {
822 char *name = g_strdup_printf("cpuid%d", i);
823
824 object_initialize_child(obj, name, &s->cpuid[i],
825 TYPE_ARMSSE_CPUID);
826 g_free(name);
827 }
828 }
829 if (info->has_cpu_pwrctrl) {
830 for (i = 0; i < info->num_cpus; i++) {
831 char *name = g_strdup_printf("cpu_pwrctrl%d", i);
832
833 object_initialize_child(obj, name, &s->cpu_pwrctrl[i],
834 TYPE_ARMSSE_CPU_PWRCTRL);
835 g_free(name);
836 }
837 }
838 if (info->has_sse_counter) {
839 object_initialize_child(obj, "sse-counter", &s->sse_counter,
840 TYPE_SSE_COUNTER);
841 }
842
843 object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ);
844 object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
845 TYPE_OR_IRQ);
846 object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter,
847 TYPE_SPLIT_IRQ);
848 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
849 char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
850 SplitIRQ *splitter = &s->ppc_irq_splitter[i];
851
852 object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
853 g_free(name);
854 }
855 if (info->num_cpus > 1) {
856 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
857 if (info->irq_is_common[i]) {
858 char *name = g_strdup_printf("cpu-irq-splitter%d", i);
859 SplitIRQ *splitter = &s->cpu_irq_splitter[i];
860
861 object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
862 g_free(name);
863 }
864 }
865 }
866}
867
868static void armsse_exp_irq(void *opaque, int n, int level)
869{
870 qemu_irq *irqarray = opaque;
871
872 qemu_set_irq(irqarray[n], level);
873}
874
875static void armsse_mpcexp_status(void *opaque, int n, int level)
876{
877 ARMSSE *s = ARM_SSE(opaque);
878 qemu_set_irq(s->mpcexp_status_in[n], level);
879}
880
881static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
882{
883
884
885
886
887 ARMSSEClass *asc = ARM_SSE_GET_CLASS(s);
888 const ARMSSEInfo *info = asc->info;
889
890 assert(info->irq_is_common[irqno]);
891
892 if (info->num_cpus == 1) {
893
894 return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
895 } else {
896
897 return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
898 }
899}
900
901static void armsse_realize(DeviceState *dev, Error **errp)
902{
903 ARMSSE *s = ARM_SSE(dev);
904 ARMSSEClass *asc = ARM_SSE_GET_CLASS(dev);
905 const ARMSSEInfo *info = asc->info;
906 const ARMSSEDeviceInfo *devinfo;
907 int i;
908 MemoryRegion *mr;
909 SysBusDevice *sbd_apb_ppc0;
910 SysBusDevice *sbd_secctl;
911 DeviceState *dev_apb_ppc0;
912 DeviceState *dev_apb_ppc1;
913 DeviceState *dev_secctl;
914 DeviceState *dev_splitter;
915 uint32_t addr_width_max;
916
917 ERRP_GUARD();
918
919 if (!s->board_memory) {
920 error_setg(errp, "memory property was not set");
921 return;
922 }
923
924 if (!clock_has_source(s->mainclk)) {
925 error_setg(errp, "MAINCLK clock was not connected");
926 }
927 if (!clock_has_source(s->s32kclk)) {
928 error_setg(errp, "S32KCLK clock was not connected");
929 }
930
931 assert(info->num_cpus <= SSE_MAX_CPUS);
932
933
934 assert(is_power_of_2(info->sram_banks));
935 addr_width_max = 24 - ctz32(info->sram_banks);
936 if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
937 error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
938 addr_width_max);
939 return;
940 }
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978 memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
979
980 for (i = 0; i < info->num_cpus; i++) {
981 DeviceState *cpudev = DEVICE(&s->armv7m[i]);
982 Object *cpuobj = OBJECT(&s->armv7m[i]);
983 int j;
984 char *gpioname;
985
986 qdev_connect_clock_in(cpudev, "cpuclk", s->mainclk);
987
988
989 qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + NUM_SSE_IRQS);
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 if (extract32(info->cpuwait_rst, i, 1)) {
1018 if (!object_property_set_bool(cpuobj, "start-powered-off", true,
1019 errp)) {
1020 return;
1021 }
1022 }
1023 if (!s->cpu_fpu[i]) {
1024 if (!object_property_set_bool(cpuobj, "vfp", false, errp)) {
1025 return;
1026 }
1027 }
1028 if (!s->cpu_dsp[i]) {
1029 if (!object_property_set_bool(cpuobj, "dsp", false, errp)) {
1030 return;
1031 }
1032 }
1033
1034 if (i > 0) {
1035 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
1036 &s->container_alias[i - 1], -1);
1037 } else {
1038 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
1039 &s->container, -1);
1040 }
1041 object_property_set_link(cpuobj, "memory",
1042 OBJECT(&s->cpu_container[i]), &error_abort);
1043 object_property_set_link(cpuobj, "idau", OBJECT(s), &error_abort);
1044 if (!sysbus_realize(SYS_BUS_DEVICE(cpuobj), errp)) {
1045 return;
1046 }
1047
1048
1049
1050
1051
1052
1053 if (!qdev_realize(DEVICE(&s->cluster[i]), NULL, errp)) {
1054 return;
1055 }
1056
1057
1058 s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
1059 for (j = 0; j < s->exp_numirq; j++) {
1060 s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + NUM_SSE_IRQS);
1061 }
1062 if (i == 0) {
1063 gpioname = g_strdup("EXP_IRQ");
1064 } else {
1065 gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
1066 }
1067 qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
1068 s->exp_irqs[i],
1069 gpioname, s->exp_numirq);
1070 g_free(gpioname);
1071 }
1072
1073
1074 if (info->num_cpus > 1) {
1075 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
1076 if (info->irq_is_common[i]) {
1077 Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
1078 DeviceState *devs = DEVICE(splitter);
1079 int cpunum;
1080
1081 if (!object_property_set_int(splitter, "num-lines",
1082 info->num_cpus, errp)) {
1083 return;
1084 }
1085 if (!qdev_realize(DEVICE(splitter), NULL, errp)) {
1086 return;
1087 }
1088 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
1089 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
1090
1091 qdev_connect_gpio_out(devs, cpunum,
1092 qdev_get_gpio_in(cpudev, i));
1093 }
1094 }
1095 }
1096 }
1097
1098
1099 make_alias(s, &s->alias1, &s->container, "alias 1",
1100 0x10000000, 0x10000000, 0x00000000);
1101 make_alias(s, &s->alias2, &s->container,
1102 "alias 2", 0x30000000, 0x10000000, 0x20000000);
1103
1104
1105
1106
1107
1108
1109
1110 for (i = 0; i < info->num_cpus; i++) {
1111 make_alias(s, &s->alias3[i], &s->cpu_container[i],
1112 "alias 3", 0x50000000, 0x10000000, 0x40000000);
1113 }
1114
1115
1116 object_property_set_int(OBJECT(&s->secctl), "sse-version",
1117 info->sse_version, &error_abort);
1118 if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) {
1119 return;
1120 }
1121 sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
1122 dev_secctl = DEVICE(&s->secctl);
1123 sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
1124 sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
1125
1126 s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
1127 qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
1128
1129
1130
1131
1132
1133 if (!object_property_set_int(OBJECT(&s->sec_resp_splitter),
1134 "num-lines", 3, errp)) {
1135 return;
1136 }
1137 if (!qdev_realize(DEVICE(&s->sec_resp_splitter), NULL, errp)) {
1138 return;
1139 }
1140 dev_splitter = DEVICE(&s->sec_resp_splitter);
1141 qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
1142 qdev_get_gpio_in(dev_splitter, 0));
1143
1144
1145 for (i = 0; i < info->sram_banks; i++) {
1146 char *ramname = g_strdup_printf("armsse.sram%d", i);
1147 SysBusDevice *sbd_mpc;
1148 uint32_t sram_bank_size = 1 << s->sram_addr_width;
1149
1150 memory_region_init_ram(&s->sram[i], NULL, ramname,
1151 sram_bank_size, errp);
1152 g_free(ramname);
1153 if (*errp) {
1154 return;
1155 }
1156 object_property_set_link(OBJECT(&s->mpc[i]), "downstream",
1157 OBJECT(&s->sram[i]), &error_abort);
1158 if (!sysbus_realize(SYS_BUS_DEVICE(&s->mpc[i]), errp)) {
1159 return;
1160 }
1161
1162 sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
1163 memory_region_add_subregion(&s->container,
1164 info->sram_bank_base + i * sram_bank_size,
1165 sysbus_mmio_get_region(sbd_mpc, 1));
1166
1167 memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
1168 sysbus_mmio_get_region(sbd_mpc, 0));
1169 }
1170
1171
1172 if (!object_property_set_int(OBJECT(&s->mpc_irq_orgate), "num-lines",
1173 IOTS_NUM_EXP_MPC + info->sram_banks,
1174 errp)) {
1175 return;
1176 }
1177 if (!qdev_realize(DEVICE(&s->mpc_irq_orgate), NULL, errp)) {
1178 return;
1179 }
1180 qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
1181 armsse_get_common_irq_in(s, 9));
1182
1183
1184 if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
1185 errp)) {
1186 return;
1187 }
1188 if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
1189 return;
1190 }
1191 qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
1192 qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
1193
1194
1195 if (info->has_sse_counter) {
1196 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sse_counter);
1197
1198 qdev_connect_clock_in(DEVICE(sbd), "CLK", s->mainclk);
1199 if (!sysbus_realize(sbd, errp)) {
1200 return;
1201 }
1202
1203
1204
1205
1206
1207 memory_region_add_subregion(&s->container, 0x58100000,
1208 sysbus_mmio_get_region(sbd, 0));
1209 memory_region_add_subregion(&s->container, 0x48101000,
1210 sysbus_mmio_get_region(sbd, 1));
1211 }
1212
1213 if (info->has_tcms) {
1214
1215 memory_region_init_ram(&s->itcm, NULL, "sse300-itcm", 512 * KiB, errp);
1216 if (*errp) {
1217 return;
1218 }
1219 memory_region_init_ram(&s->dtcm, NULL, "sse300-dtcm", 512 * KiB, errp);
1220 if (*errp) {
1221 return;
1222 }
1223 memory_region_add_subregion(&s->container, 0x00000000, &s->itcm);
1224 memory_region_add_subregion(&s->container, 0x20000000, &s->dtcm);
1225 }
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237 for (devinfo = info->devinfo; devinfo->name; devinfo++) {
1238 SysBusDevice *sbd;
1239 qemu_irq irq;
1240
1241 if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
1242 sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
1243
1244 qdev_connect_clock_in(DEVICE(sbd), "pclk",
1245 devinfo->slowclk ? s->s32kclk : s->mainclk);
1246 if (!sysbus_realize(sbd, errp)) {
1247 return;
1248 }
1249 mr = sysbus_mmio_get_region(sbd, 0);
1250 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
1251 sbd = SYS_BUS_DEVICE(&s->dualtimer);
1252
1253 qdev_connect_clock_in(DEVICE(sbd), "TIMCLK", s->mainclk);
1254 if (!sysbus_realize(sbd, errp)) {
1255 return;
1256 }
1257 mr = sysbus_mmio_get_region(sbd, 0);
1258 } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
1259 sbd = SYS_BUS_DEVICE(&s->sse_timer[devinfo->index]);
1260
1261 assert(info->has_sse_counter);
1262 object_property_set_link(OBJECT(sbd), "counter",
1263 OBJECT(&s->sse_counter), &error_abort);
1264 if (!sysbus_realize(sbd, errp)) {
1265 return;
1266 }
1267 mr = sysbus_mmio_get_region(sbd, 0);
1268 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
1269 sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
1270
1271 qdev_connect_clock_in(DEVICE(sbd), "WDOGCLK",
1272 devinfo->slowclk ? s->s32kclk : s->mainclk);
1273 if (!sysbus_realize(sbd, errp)) {
1274 return;
1275 }
1276 mr = sysbus_mmio_get_region(sbd, 0);
1277 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
1278 sbd = SYS_BUS_DEVICE(&s->sysinfo);
1279
1280 object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
1281 info->sys_version, &error_abort);
1282 object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
1283 armsse_sys_config_value(s, info),
1284 &error_abort);
1285 object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
1286 info->sse_version, &error_abort);
1287 object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
1288 info->iidr, &error_abort);
1289 if (!sysbus_realize(sbd, errp)) {
1290 return;
1291 }
1292 mr = sysbus_mmio_get_region(sbd, 0);
1293 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
1294
1295 sbd = SYS_BUS_DEVICE(&s->sysctl);
1296
1297 object_property_set_int(OBJECT(&s->sysctl), "sse-version",
1298 info->sse_version, &error_abort);
1299 object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
1300 info->cpuwait_rst, &error_abort);
1301 object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
1302 s->init_svtor, &error_abort);
1303 object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
1304 s->init_svtor, &error_abort);
1305 if (!sysbus_realize(sbd, errp)) {
1306 return;
1307 }
1308 mr = sysbus_mmio_get_region(sbd, 0);
1309 } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
1310 sbd = SYS_BUS_DEVICE(&s->unimp[devinfo->index]);
1311
1312 qdev_prop_set_string(DEVICE(sbd), "name", devinfo->name);
1313 qdev_prop_set_uint64(DEVICE(sbd), "size", devinfo->size);
1314 if (!sysbus_realize(sbd, errp)) {
1315 return;
1316 }
1317 mr = sysbus_mmio_get_region(sbd, 0);
1318 } else {
1319 g_assert_not_reached();
1320 }
1321
1322 switch (devinfo->irq) {
1323 case NO_IRQ:
1324 irq = NULL;
1325 break;
1326 case 0 ... NUM_SSE_IRQS - 1:
1327 irq = armsse_get_common_irq_in(s, devinfo->irq);
1328 break;
1329 case NMI_0:
1330 case NMI_1:
1331 irq = qdev_get_gpio_in(DEVICE(&s->nmi_orgate),
1332 devinfo->irq - NMI_0);
1333 break;
1334 default:
1335 g_assert_not_reached();
1336 }
1337
1338 if (irq) {
1339 sysbus_connect_irq(sbd, 0, irq);
1340 }
1341
1342
1343
1344
1345
1346
1347
1348 if (devinfo->ppc != NO_PPC) {
1349 TZPPC *ppc = &s->apb_ppc[devinfo->ppc];
1350 g_autofree char *portname = g_strdup_printf("port[%d]",
1351 devinfo->ppc_port);
1352 object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
1353 &error_abort);
1354 } else {
1355 memory_region_add_subregion(&s->container, devinfo->addr, mr);
1356 }
1357 }
1358
1359 if (info->has_mhus) {
1360
1361
1362
1363
1364
1365
1366
1367 assert(info->num_cpus == ARRAY_SIZE(s->mhu));
1368
1369 for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
1370 char *port;
1371 int cpunum;
1372 SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]);
1373
1374 if (!sysbus_realize(SYS_BUS_DEVICE(&s->mhu[i]), errp)) {
1375 return;
1376 }
1377 port = g_strdup_printf("port[%d]", i + 3);
1378 mr = sysbus_mmio_get_region(mhu_sbd, 0);
1379 object_property_set_link(OBJECT(&s->apb_ppc[0]), port, OBJECT(mr),
1380 &error_abort);
1381 g_free(port);
1382
1383
1384
1385
1386
1387
1388
1389
1390 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
1391 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
1392
1393 sysbus_connect_irq(mhu_sbd, cpunum,
1394 qdev_get_gpio_in(cpudev, 6 + i));
1395 }
1396 }
1397 }
1398
1399 if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[0]), errp)) {
1400 return;
1401 }
1402
1403 sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
1404 dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
1405
1406 if (info->has_mhus) {
1407 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
1408 memory_region_add_subregion(&s->container, 0x40003000, mr);
1409 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
1410 memory_region_add_subregion(&s->container, 0x40004000, mr);
1411 }
1412 for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
1413 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
1414 qdev_get_gpio_in_named(dev_apb_ppc0,
1415 "cfg_nonsec", i));
1416 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
1417 qdev_get_gpio_in_named(dev_apb_ppc0,
1418 "cfg_ap", i));
1419 }
1420 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
1421 qdev_get_gpio_in_named(dev_apb_ppc0,
1422 "irq_enable", 0));
1423 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
1424 qdev_get_gpio_in_named(dev_apb_ppc0,
1425 "irq_clear", 0));
1426 qdev_connect_gpio_out(dev_splitter, 0,
1427 qdev_get_gpio_in_named(dev_apb_ppc0,
1428 "cfg_sec_resp", 0));
1429
1430
1431
1432
1433
1434 if (!object_property_set_int(OBJECT(&s->ppc_irq_orgate),
1435 "num-lines", NUM_PPCS, errp)) {
1436 return;
1437 }
1438 if (!qdev_realize(DEVICE(&s->ppc_irq_orgate), NULL, errp)) {
1439 return;
1440 }
1441 qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
1442 armsse_get_common_irq_in(s, 10));
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453 if (info->has_cachectrl) {
1454 for (i = 0; i < info->num_cpus; i++) {
1455 char *name = g_strdup_printf("cachectrl%d", i);
1456 MemoryRegion *mr;
1457
1458 qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
1459 g_free(name);
1460 qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
1461 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cachectrl[i]), errp)) {
1462 return;
1463 }
1464
1465 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
1466 memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
1467 }
1468 }
1469 if (info->has_cpusecctrl) {
1470 for (i = 0; i < info->num_cpus; i++) {
1471 char *name = g_strdup_printf("CPUSECCTRL%d", i);
1472 MemoryRegion *mr;
1473
1474 qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
1475 g_free(name);
1476 qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
1477 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpusecctrl[i]), errp)) {
1478 return;
1479 }
1480
1481 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
1482 memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
1483 }
1484 }
1485 if (info->has_cpuid) {
1486 for (i = 0; i < info->num_cpus; i++) {
1487 MemoryRegion *mr;
1488
1489 qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
1490 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpuid[i]), errp)) {
1491 return;
1492 }
1493
1494 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
1495 memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
1496 }
1497 }
1498 if (info->has_cpu_pwrctrl) {
1499 for (i = 0; i < info->num_cpus; i++) {
1500 MemoryRegion *mr;
1501
1502 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), errp)) {
1503 return;
1504 }
1505
1506 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), 0);
1507 memory_region_add_subregion(&s->cpu_container[i], 0x40012000, mr);
1508 }
1509 }
1510
1511 if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
1512 return;
1513 }
1514
1515 dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
1516 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
1517 qdev_get_gpio_in_named(dev_apb_ppc1,
1518 "cfg_nonsec", 0));
1519 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
1520 qdev_get_gpio_in_named(dev_apb_ppc1,
1521 "cfg_ap", 0));
1522 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
1523 qdev_get_gpio_in_named(dev_apb_ppc1,
1524 "irq_enable", 0));
1525 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
1526 qdev_get_gpio_in_named(dev_apb_ppc1,
1527 "irq_clear", 0));
1528 qdev_connect_gpio_out(dev_splitter, 1,
1529 qdev_get_gpio_in_named(dev_apb_ppc1,
1530 "cfg_sec_resp", 0));
1531
1532
1533
1534
1535
1536
1537
1538 for (devinfo = info->devinfo; devinfo->name; devinfo++) {
1539 SysBusDevice *ppc_sbd;
1540
1541 if (devinfo->ppc == NO_PPC) {
1542 continue;
1543 }
1544 ppc_sbd = SYS_BUS_DEVICE(&s->apb_ppc[devinfo->ppc]);
1545 mr = sysbus_mmio_get_region(ppc_sbd, devinfo->ppc_port);
1546 memory_region_add_subregion(&s->container, devinfo->addr, mr);
1547 }
1548
1549 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
1550 Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
1551
1552 if (!object_property_set_int(splitter, "num-lines", 2, errp)) {
1553 return;
1554 }
1555 if (!qdev_realize(DEVICE(splitter), NULL, errp)) {
1556 return;
1557 }
1558 }
1559
1560 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
1561 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
1562
1563 armsse_forward_ppc(s, ppcname, i);
1564 g_free(ppcname);
1565 }
1566
1567 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
1568 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
1569
1570 armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
1571 g_free(ppcname);
1572 }
1573
1574 for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
1575
1576 DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
1577 char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
1578 i - NUM_EXTERNAL_PPCS);
1579 TZPPC *ppc = &s->apb_ppc[i - NUM_EXTERNAL_PPCS];
1580
1581 qdev_connect_gpio_out(devs, 0,
1582 qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
1583 qdev_connect_gpio_out(devs, 1,
1584 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
1585 qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
1586 qdev_get_gpio_in(devs, 0));
1587 g_free(gpioname);
1588 }
1589
1590
1591 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
1592 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
1593 DeviceState *dev_splitter = DEVICE(splitter);
1594
1595 if (!object_property_set_int(OBJECT(splitter), "num-lines", 2,
1596 errp)) {
1597 return;
1598 }
1599 if (!qdev_realize(DEVICE(splitter), NULL, errp)) {
1600 return;
1601 }
1602
1603 if (i < IOTS_NUM_EXP_MPC) {
1604
1605 s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
1606 qdev_connect_gpio_out(dev_splitter, 0,
1607 qdev_get_gpio_in_named(dev_secctl,
1608 "mpcexp_status", i));
1609 } else {
1610
1611 qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
1612 "irq", 0,
1613 qdev_get_gpio_in(dev_splitter, 0));
1614 qdev_connect_gpio_out(dev_splitter, 0,
1615 qdev_get_gpio_in_named(dev_secctl,
1616 "mpc_status",
1617 i - IOTS_NUM_EXP_MPC));
1618 }
1619
1620 qdev_connect_gpio_out(dev_splitter, 1,
1621 qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
1622 }
1623
1624
1625
1626 qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
1627 IOTS_NUM_EXP_MPC);
1628
1629 armsse_forward_sec_resp_cfg(s);
1630
1631
1632 qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
1633 qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
1634 qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
1635 qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
1636 armsse_get_common_irq_in(s, 11));
1637
1638
1639
1640
1641
1642
1643
1644 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
1645}
1646
1647static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
1648 int *iregion, bool *exempt, bool *ns, bool *nsc)
1649{
1650
1651
1652
1653
1654
1655 ARMSSE *s = ARM_SSE(ii);
1656 int region = extract32(address, 28, 4);
1657
1658 *ns = !(region & 1);
1659 *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
1660
1661 *exempt = (address & 0xeff00000) == 0xe0000000;
1662 *iregion = region;
1663}
1664
1665static const VMStateDescription armsse_vmstate = {
1666 .name = "iotkit",
1667 .version_id = 2,
1668 .minimum_version_id = 2,
1669 .fields = (VMStateField[]) {
1670 VMSTATE_CLOCK(mainclk, ARMSSE),
1671 VMSTATE_CLOCK(s32kclk, ARMSSE),
1672 VMSTATE_UINT32(nsccfg, ARMSSE),
1673 VMSTATE_END_OF_LIST()
1674 }
1675};
1676
1677static void armsse_reset(DeviceState *dev)
1678{
1679 ARMSSE *s = ARM_SSE(dev);
1680
1681 s->nsccfg = 0;
1682}
1683
1684static void armsse_class_init(ObjectClass *klass, void *data)
1685{
1686 DeviceClass *dc = DEVICE_CLASS(klass);
1687 IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
1688 ARMSSEClass *asc = ARM_SSE_CLASS(klass);
1689 const ARMSSEInfo *info = data;
1690
1691 dc->realize = armsse_realize;
1692 dc->vmsd = &armsse_vmstate;
1693 device_class_set_props(dc, info->props);
1694 dc->reset = armsse_reset;
1695 iic->check = armsse_idau_check;
1696 asc->info = info;
1697}
1698
1699static const TypeInfo armsse_info = {
1700 .name = TYPE_ARM_SSE,
1701 .parent = TYPE_SYS_BUS_DEVICE,
1702 .instance_size = sizeof(ARMSSE),
1703 .class_size = sizeof(ARMSSEClass),
1704 .instance_init = armsse_init,
1705 .abstract = true,
1706 .interfaces = (InterfaceInfo[]) {
1707 { TYPE_IDAU_INTERFACE },
1708 { }
1709 }
1710};
1711
1712static void armsse_register_types(void)
1713{
1714 int i;
1715
1716 type_register_static(&armsse_info);
1717
1718 for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
1719 TypeInfo ti = {
1720 .name = armsse_variants[i].name,
1721 .parent = TYPE_ARM_SSE,
1722 .class_init = armsse_class_init,
1723 .class_data = (void *)&armsse_variants[i],
1724 };
1725 type_register(&ti);
1726 }
1727}
1728
1729type_init(armsse_register_types);
1730