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_mainclk_update(void *opaque, ClockEvent event)
693{
694 ARMSSE *s = ARM_SSE(opaque);
695
696
697
698
699
700 system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
701}
702
703static void armsse_init(Object *obj)
704{
705 ARMSSE *s = ARM_SSE(obj);
706 ARMSSEClass *asc = ARM_SSE_GET_CLASS(obj);
707 const ARMSSEInfo *info = asc->info;
708 const ARMSSEDeviceInfo *devinfo;
709 int i;
710
711 assert(info->sram_banks <= MAX_SRAM_BANKS);
712 assert(info->num_cpus <= SSE_MAX_CPUS);
713
714 s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
715 armsse_mainclk_update, s, ClockUpdate);
716 s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
717
718 memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
719
720 for (i = 0; i < info->num_cpus; i++) {
721
722
723
724
725 char *name;
726
727 name = g_strdup_printf("cluster%d", i);
728 object_initialize_child(obj, name, &s->cluster[i], TYPE_CPU_CLUSTER);
729 qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
730 g_free(name);
731
732 name = g_strdup_printf("armv7m%d", i);
733 object_initialize_child(OBJECT(&s->cluster[i]), name, &s->armv7m[i],
734 TYPE_ARMV7M);
735 qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type", info->cpu_type);
736 g_free(name);
737 name = g_strdup_printf("arm-sse-cpu-container%d", i);
738 memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
739 g_free(name);
740 if (i > 0) {
741 name = g_strdup_printf("arm-sse-container-alias%d", i);
742 memory_region_init_alias(&s->container_alias[i - 1], obj,
743 name, &s->container, 0, UINT64_MAX);
744 g_free(name);
745 }
746 }
747
748 for (devinfo = info->devinfo; devinfo->name; devinfo++) {
749 assert(devinfo->ppc == NO_PPC || devinfo->ppc < ARRAY_SIZE(s->apb_ppc));
750 if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
751 assert(devinfo->index < ARRAY_SIZE(s->timer));
752 object_initialize_child(obj, devinfo->name,
753 &s->timer[devinfo->index],
754 TYPE_CMSDK_APB_TIMER);
755 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
756 assert(devinfo->index == 0);
757 object_initialize_child(obj, devinfo->name, &s->dualtimer,
758 TYPE_CMSDK_APB_DUALTIMER);
759 } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
760 assert(devinfo->index < ARRAY_SIZE(s->sse_timer));
761 object_initialize_child(obj, devinfo->name,
762 &s->sse_timer[devinfo->index],
763 TYPE_SSE_TIMER);
764 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
765 assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
766 object_initialize_child(obj, devinfo->name,
767 &s->cmsdk_watchdog[devinfo->index],
768 TYPE_CMSDK_APB_WATCHDOG);
769 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
770 assert(devinfo->index == 0);
771 object_initialize_child(obj, devinfo->name, &s->sysinfo,
772 TYPE_IOTKIT_SYSINFO);
773 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
774 assert(devinfo->index == 0);
775 object_initialize_child(obj, devinfo->name, &s->sysctl,
776 TYPE_IOTKIT_SYSCTL);
777 } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
778 assert(devinfo->index < ARRAY_SIZE(s->unimp));
779 object_initialize_child(obj, devinfo->name,
780 &s->unimp[devinfo->index],
781 TYPE_UNIMPLEMENTED_DEVICE);
782 } else {
783 g_assert_not_reached();
784 }
785 }
786
787 object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
788
789 for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
790 g_autofree char *name = g_strdup_printf("apb-ppc%d", i);
791 object_initialize_child(obj, name, &s->apb_ppc[i], TYPE_TZ_PPC);
792 }
793
794 for (i = 0; i < info->sram_banks; i++) {
795 char *name = g_strdup_printf("mpc%d", i);
796 object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC);
797 g_free(name);
798 }
799 object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
800 TYPE_OR_IRQ);
801
802 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
803 char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
804 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
805
806 object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
807 g_free(name);
808 }
809
810 if (info->has_mhus) {
811 object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
812 object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
813 }
814 if (info->has_cachectrl) {
815 for (i = 0; i < info->num_cpus; i++) {
816 char *name = g_strdup_printf("cachectrl%d", i);
817
818 object_initialize_child(obj, name, &s->cachectrl[i],
819 TYPE_UNIMPLEMENTED_DEVICE);
820 g_free(name);
821 }
822 }
823 if (info->has_cpusecctrl) {
824 for (i = 0; i < info->num_cpus; i++) {
825 char *name = g_strdup_printf("cpusecctrl%d", i);
826
827 object_initialize_child(obj, name, &s->cpusecctrl[i],
828 TYPE_UNIMPLEMENTED_DEVICE);
829 g_free(name);
830 }
831 }
832 if (info->has_cpuid) {
833 for (i = 0; i < info->num_cpus; i++) {
834 char *name = g_strdup_printf("cpuid%d", i);
835
836 object_initialize_child(obj, name, &s->cpuid[i],
837 TYPE_ARMSSE_CPUID);
838 g_free(name);
839 }
840 }
841 if (info->has_cpu_pwrctrl) {
842 for (i = 0; i < info->num_cpus; i++) {
843 char *name = g_strdup_printf("cpu_pwrctrl%d", i);
844
845 object_initialize_child(obj, name, &s->cpu_pwrctrl[i],
846 TYPE_ARMSSE_CPU_PWRCTRL);
847 g_free(name);
848 }
849 }
850 if (info->has_sse_counter) {
851 object_initialize_child(obj, "sse-counter", &s->sse_counter,
852 TYPE_SSE_COUNTER);
853 }
854
855 object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ);
856 object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
857 TYPE_OR_IRQ);
858 object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter,
859 TYPE_SPLIT_IRQ);
860 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
861 char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
862 SplitIRQ *splitter = &s->ppc_irq_splitter[i];
863
864 object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
865 g_free(name);
866 }
867 if (info->num_cpus > 1) {
868 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
869 if (info->irq_is_common[i]) {
870 char *name = g_strdup_printf("cpu-irq-splitter%d", i);
871 SplitIRQ *splitter = &s->cpu_irq_splitter[i];
872
873 object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
874 g_free(name);
875 }
876 }
877 }
878}
879
880static void armsse_exp_irq(void *opaque, int n, int level)
881{
882 qemu_irq *irqarray = opaque;
883
884 qemu_set_irq(irqarray[n], level);
885}
886
887static void armsse_mpcexp_status(void *opaque, int n, int level)
888{
889 ARMSSE *s = ARM_SSE(opaque);
890 qemu_set_irq(s->mpcexp_status_in[n], level);
891}
892
893static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
894{
895
896
897
898
899 ARMSSEClass *asc = ARM_SSE_GET_CLASS(s);
900 const ARMSSEInfo *info = asc->info;
901
902 assert(info->irq_is_common[irqno]);
903
904 if (info->num_cpus == 1) {
905
906 return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
907 } else {
908
909 return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
910 }
911}
912
913static void armsse_realize(DeviceState *dev, Error **errp)
914{
915 ARMSSE *s = ARM_SSE(dev);
916 ARMSSEClass *asc = ARM_SSE_GET_CLASS(dev);
917 const ARMSSEInfo *info = asc->info;
918 const ARMSSEDeviceInfo *devinfo;
919 int i;
920 MemoryRegion *mr;
921 SysBusDevice *sbd_apb_ppc0;
922 SysBusDevice *sbd_secctl;
923 DeviceState *dev_apb_ppc0;
924 DeviceState *dev_apb_ppc1;
925 DeviceState *dev_secctl;
926 DeviceState *dev_splitter;
927 uint32_t addr_width_max;
928
929 ERRP_GUARD();
930
931 if (!s->board_memory) {
932 error_setg(errp, "memory property was not set");
933 return;
934 }
935
936 if (!clock_has_source(s->mainclk)) {
937 error_setg(errp, "MAINCLK clock was not connected");
938 }
939 if (!clock_has_source(s->s32kclk)) {
940 error_setg(errp, "S32KCLK clock was not connected");
941 }
942
943 assert(info->num_cpus <= SSE_MAX_CPUS);
944
945
946 assert(is_power_of_2(info->sram_banks));
947 addr_width_max = 24 - ctz32(info->sram_banks);
948 if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
949 error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
950 addr_width_max);
951 return;
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
979
980
981
982
983
984
985
986
987
988
989
990 memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
991
992 for (i = 0; i < info->num_cpus; i++) {
993 DeviceState *cpudev = DEVICE(&s->armv7m[i]);
994 Object *cpuobj = OBJECT(&s->armv7m[i]);
995 int j;
996 char *gpioname;
997
998 qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + NUM_SSE_IRQS);
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 if (extract32(info->cpuwait_rst, i, 1)) {
1027 if (!object_property_set_bool(cpuobj, "start-powered-off", true,
1028 errp)) {
1029 return;
1030 }
1031 }
1032 if (!s->cpu_fpu[i]) {
1033 if (!object_property_set_bool(cpuobj, "vfp", false, errp)) {
1034 return;
1035 }
1036 }
1037 if (!s->cpu_dsp[i]) {
1038 if (!object_property_set_bool(cpuobj, "dsp", false, errp)) {
1039 return;
1040 }
1041 }
1042
1043 if (i > 0) {
1044 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
1045 &s->container_alias[i - 1], -1);
1046 } else {
1047 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
1048 &s->container, -1);
1049 }
1050 object_property_set_link(cpuobj, "memory",
1051 OBJECT(&s->cpu_container[i]), &error_abort);
1052 object_property_set_link(cpuobj, "idau", OBJECT(s), &error_abort);
1053 if (!sysbus_realize(SYS_BUS_DEVICE(cpuobj), errp)) {
1054 return;
1055 }
1056
1057
1058
1059
1060
1061
1062 if (!qdev_realize(DEVICE(&s->cluster[i]), NULL, errp)) {
1063 return;
1064 }
1065
1066
1067 s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
1068 for (j = 0; j < s->exp_numirq; j++) {
1069 s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + NUM_SSE_IRQS);
1070 }
1071 if (i == 0) {
1072 gpioname = g_strdup("EXP_IRQ");
1073 } else {
1074 gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
1075 }
1076 qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
1077 s->exp_irqs[i],
1078 gpioname, s->exp_numirq);
1079 g_free(gpioname);
1080 }
1081
1082
1083 if (info->num_cpus > 1) {
1084 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
1085 if (info->irq_is_common[i]) {
1086 Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
1087 DeviceState *devs = DEVICE(splitter);
1088 int cpunum;
1089
1090 if (!object_property_set_int(splitter, "num-lines",
1091 info->num_cpus, errp)) {
1092 return;
1093 }
1094 if (!qdev_realize(DEVICE(splitter), NULL, errp)) {
1095 return;
1096 }
1097 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
1098 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
1099
1100 qdev_connect_gpio_out(devs, cpunum,
1101 qdev_get_gpio_in(cpudev, i));
1102 }
1103 }
1104 }
1105 }
1106
1107
1108 make_alias(s, &s->alias1, &s->container, "alias 1",
1109 0x10000000, 0x10000000, 0x00000000);
1110 make_alias(s, &s->alias2, &s->container,
1111 "alias 2", 0x30000000, 0x10000000, 0x20000000);
1112
1113
1114
1115
1116
1117
1118
1119 for (i = 0; i < info->num_cpus; i++) {
1120 make_alias(s, &s->alias3[i], &s->cpu_container[i],
1121 "alias 3", 0x50000000, 0x10000000, 0x40000000);
1122 }
1123
1124
1125 object_property_set_int(OBJECT(&s->secctl), "sse-version",
1126 info->sse_version, &error_abort);
1127 if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) {
1128 return;
1129 }
1130 sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
1131 dev_secctl = DEVICE(&s->secctl);
1132 sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
1133 sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
1134
1135 s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
1136 qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
1137
1138
1139
1140
1141
1142 if (!object_property_set_int(OBJECT(&s->sec_resp_splitter),
1143 "num-lines", 3, errp)) {
1144 return;
1145 }
1146 if (!qdev_realize(DEVICE(&s->sec_resp_splitter), NULL, errp)) {
1147 return;
1148 }
1149 dev_splitter = DEVICE(&s->sec_resp_splitter);
1150 qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
1151 qdev_get_gpio_in(dev_splitter, 0));
1152
1153
1154 for (i = 0; i < info->sram_banks; i++) {
1155 char *ramname = g_strdup_printf("armsse.sram%d", i);
1156 SysBusDevice *sbd_mpc;
1157 uint32_t sram_bank_size = 1 << s->sram_addr_width;
1158
1159 memory_region_init_ram(&s->sram[i], NULL, ramname,
1160 sram_bank_size, errp);
1161 g_free(ramname);
1162 if (*errp) {
1163 return;
1164 }
1165 object_property_set_link(OBJECT(&s->mpc[i]), "downstream",
1166 OBJECT(&s->sram[i]), &error_abort);
1167 if (!sysbus_realize(SYS_BUS_DEVICE(&s->mpc[i]), errp)) {
1168 return;
1169 }
1170
1171 sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
1172 memory_region_add_subregion(&s->container,
1173 info->sram_bank_base + i * sram_bank_size,
1174 sysbus_mmio_get_region(sbd_mpc, 1));
1175
1176 memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
1177 sysbus_mmio_get_region(sbd_mpc, 0));
1178 }
1179
1180
1181 if (!object_property_set_int(OBJECT(&s->mpc_irq_orgate), "num-lines",
1182 IOTS_NUM_EXP_MPC + info->sram_banks,
1183 errp)) {
1184 return;
1185 }
1186 if (!qdev_realize(DEVICE(&s->mpc_irq_orgate), NULL, errp)) {
1187 return;
1188 }
1189 qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
1190 armsse_get_common_irq_in(s, 9));
1191
1192
1193 if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
1194 errp)) {
1195 return;
1196 }
1197 if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
1198 return;
1199 }
1200 qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
1201 qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
1202
1203
1204 if (info->has_sse_counter) {
1205 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sse_counter);
1206
1207 qdev_connect_clock_in(DEVICE(sbd), "CLK", s->mainclk);
1208 if (!sysbus_realize(sbd, errp)) {
1209 return;
1210 }
1211
1212
1213
1214
1215
1216 memory_region_add_subregion(&s->container, 0x58100000,
1217 sysbus_mmio_get_region(sbd, 0));
1218 memory_region_add_subregion(&s->container, 0x48101000,
1219 sysbus_mmio_get_region(sbd, 1));
1220 }
1221
1222 if (info->has_tcms) {
1223
1224 memory_region_init_ram(&s->itcm, NULL, "sse300-itcm", 512 * KiB, errp);
1225 if (*errp) {
1226 return;
1227 }
1228 memory_region_init_ram(&s->dtcm, NULL, "sse300-dtcm", 512 * KiB, errp);
1229 if (*errp) {
1230 return;
1231 }
1232 memory_region_add_subregion(&s->container, 0x00000000, &s->itcm);
1233 memory_region_add_subregion(&s->container, 0x20000000, &s->dtcm);
1234 }
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246 for (devinfo = info->devinfo; devinfo->name; devinfo++) {
1247 SysBusDevice *sbd;
1248 qemu_irq irq;
1249
1250 if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
1251 sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
1252
1253 qdev_connect_clock_in(DEVICE(sbd), "pclk",
1254 devinfo->slowclk ? s->s32kclk : s->mainclk);
1255 if (!sysbus_realize(sbd, errp)) {
1256 return;
1257 }
1258 mr = sysbus_mmio_get_region(sbd, 0);
1259 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
1260 sbd = SYS_BUS_DEVICE(&s->dualtimer);
1261
1262 qdev_connect_clock_in(DEVICE(sbd), "TIMCLK", s->mainclk);
1263 if (!sysbus_realize(sbd, errp)) {
1264 return;
1265 }
1266 mr = sysbus_mmio_get_region(sbd, 0);
1267 } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
1268 sbd = SYS_BUS_DEVICE(&s->sse_timer[devinfo->index]);
1269
1270 assert(info->has_sse_counter);
1271 object_property_set_link(OBJECT(sbd), "counter",
1272 OBJECT(&s->sse_counter), &error_abort);
1273 if (!sysbus_realize(sbd, errp)) {
1274 return;
1275 }
1276 mr = sysbus_mmio_get_region(sbd, 0);
1277 } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
1278 sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
1279
1280 qdev_connect_clock_in(DEVICE(sbd), "WDOGCLK",
1281 devinfo->slowclk ? s->s32kclk : s->mainclk);
1282 if (!sysbus_realize(sbd, errp)) {
1283 return;
1284 }
1285 mr = sysbus_mmio_get_region(sbd, 0);
1286 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
1287 sbd = SYS_BUS_DEVICE(&s->sysinfo);
1288
1289 object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
1290 info->sys_version, &error_abort);
1291 object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
1292 armsse_sys_config_value(s, info),
1293 &error_abort);
1294 object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
1295 info->sse_version, &error_abort);
1296 object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
1297 info->iidr, &error_abort);
1298 if (!sysbus_realize(sbd, errp)) {
1299 return;
1300 }
1301 mr = sysbus_mmio_get_region(sbd, 0);
1302 } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
1303
1304 sbd = SYS_BUS_DEVICE(&s->sysctl);
1305
1306 object_property_set_int(OBJECT(&s->sysctl), "sse-version",
1307 info->sse_version, &error_abort);
1308 object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
1309 info->cpuwait_rst, &error_abort);
1310 object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
1311 s->init_svtor, &error_abort);
1312 object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
1313 s->init_svtor, &error_abort);
1314 if (!sysbus_realize(sbd, errp)) {
1315 return;
1316 }
1317 mr = sysbus_mmio_get_region(sbd, 0);
1318 } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
1319 sbd = SYS_BUS_DEVICE(&s->unimp[devinfo->index]);
1320
1321 qdev_prop_set_string(DEVICE(sbd), "name", devinfo->name);
1322 qdev_prop_set_uint64(DEVICE(sbd), "size", devinfo->size);
1323 if (!sysbus_realize(sbd, errp)) {
1324 return;
1325 }
1326 mr = sysbus_mmio_get_region(sbd, 0);
1327 } else {
1328 g_assert_not_reached();
1329 }
1330
1331 switch (devinfo->irq) {
1332 case NO_IRQ:
1333 irq = NULL;
1334 break;
1335 case 0 ... NUM_SSE_IRQS - 1:
1336 irq = armsse_get_common_irq_in(s, devinfo->irq);
1337 break;
1338 case NMI_0:
1339 case NMI_1:
1340 irq = qdev_get_gpio_in(DEVICE(&s->nmi_orgate),
1341 devinfo->irq - NMI_0);
1342 break;
1343 default:
1344 g_assert_not_reached();
1345 }
1346
1347 if (irq) {
1348 sysbus_connect_irq(sbd, 0, irq);
1349 }
1350
1351
1352
1353
1354
1355
1356
1357 if (devinfo->ppc != NO_PPC) {
1358 TZPPC *ppc = &s->apb_ppc[devinfo->ppc];
1359 g_autofree char *portname = g_strdup_printf("port[%d]",
1360 devinfo->ppc_port);
1361 object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
1362 &error_abort);
1363 } else {
1364 memory_region_add_subregion(&s->container, devinfo->addr, mr);
1365 }
1366 }
1367
1368 if (info->has_mhus) {
1369
1370
1371
1372
1373
1374
1375
1376 assert(info->num_cpus == ARRAY_SIZE(s->mhu));
1377
1378 for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
1379 char *port;
1380 int cpunum;
1381 SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]);
1382
1383 if (!sysbus_realize(SYS_BUS_DEVICE(&s->mhu[i]), errp)) {
1384 return;
1385 }
1386 port = g_strdup_printf("port[%d]", i + 3);
1387 mr = sysbus_mmio_get_region(mhu_sbd, 0);
1388 object_property_set_link(OBJECT(&s->apb_ppc[0]), port, OBJECT(mr),
1389 &error_abort);
1390 g_free(port);
1391
1392
1393
1394
1395
1396
1397
1398
1399 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
1400 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
1401
1402 sysbus_connect_irq(mhu_sbd, cpunum,
1403 qdev_get_gpio_in(cpudev, 6 + i));
1404 }
1405 }
1406 }
1407
1408 if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[0]), errp)) {
1409 return;
1410 }
1411
1412 sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
1413 dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
1414
1415 if (info->has_mhus) {
1416 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
1417 memory_region_add_subregion(&s->container, 0x40003000, mr);
1418 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
1419 memory_region_add_subregion(&s->container, 0x40004000, mr);
1420 }
1421 for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
1422 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
1423 qdev_get_gpio_in_named(dev_apb_ppc0,
1424 "cfg_nonsec", i));
1425 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
1426 qdev_get_gpio_in_named(dev_apb_ppc0,
1427 "cfg_ap", i));
1428 }
1429 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
1430 qdev_get_gpio_in_named(dev_apb_ppc0,
1431 "irq_enable", 0));
1432 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
1433 qdev_get_gpio_in_named(dev_apb_ppc0,
1434 "irq_clear", 0));
1435 qdev_connect_gpio_out(dev_splitter, 0,
1436 qdev_get_gpio_in_named(dev_apb_ppc0,
1437 "cfg_sec_resp", 0));
1438
1439
1440
1441
1442
1443 if (!object_property_set_int(OBJECT(&s->ppc_irq_orgate),
1444 "num-lines", NUM_PPCS, errp)) {
1445 return;
1446 }
1447 if (!qdev_realize(DEVICE(&s->ppc_irq_orgate), NULL, errp)) {
1448 return;
1449 }
1450 qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
1451 armsse_get_common_irq_in(s, 10));
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462 if (info->has_cachectrl) {
1463 for (i = 0; i < info->num_cpus; i++) {
1464 char *name = g_strdup_printf("cachectrl%d", i);
1465 MemoryRegion *mr;
1466
1467 qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
1468 g_free(name);
1469 qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
1470 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cachectrl[i]), errp)) {
1471 return;
1472 }
1473
1474 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
1475 memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
1476 }
1477 }
1478 if (info->has_cpusecctrl) {
1479 for (i = 0; i < info->num_cpus; i++) {
1480 char *name = g_strdup_printf("CPUSECCTRL%d", i);
1481 MemoryRegion *mr;
1482
1483 qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
1484 g_free(name);
1485 qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
1486 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpusecctrl[i]), errp)) {
1487 return;
1488 }
1489
1490 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
1491 memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
1492 }
1493 }
1494 if (info->has_cpuid) {
1495 for (i = 0; i < info->num_cpus; i++) {
1496 MemoryRegion *mr;
1497
1498 qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
1499 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpuid[i]), errp)) {
1500 return;
1501 }
1502
1503 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
1504 memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
1505 }
1506 }
1507 if (info->has_cpu_pwrctrl) {
1508 for (i = 0; i < info->num_cpus; i++) {
1509 MemoryRegion *mr;
1510
1511 if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), errp)) {
1512 return;
1513 }
1514
1515 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), 0);
1516 memory_region_add_subregion(&s->cpu_container[i], 0x40012000, mr);
1517 }
1518 }
1519
1520 if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
1521 return;
1522 }
1523
1524 dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
1525 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
1526 qdev_get_gpio_in_named(dev_apb_ppc1,
1527 "cfg_nonsec", 0));
1528 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
1529 qdev_get_gpio_in_named(dev_apb_ppc1,
1530 "cfg_ap", 0));
1531 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
1532 qdev_get_gpio_in_named(dev_apb_ppc1,
1533 "irq_enable", 0));
1534 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
1535 qdev_get_gpio_in_named(dev_apb_ppc1,
1536 "irq_clear", 0));
1537 qdev_connect_gpio_out(dev_splitter, 1,
1538 qdev_get_gpio_in_named(dev_apb_ppc1,
1539 "cfg_sec_resp", 0));
1540
1541
1542
1543
1544
1545
1546
1547 for (devinfo = info->devinfo; devinfo->name; devinfo++) {
1548 SysBusDevice *ppc_sbd;
1549
1550 if (devinfo->ppc == NO_PPC) {
1551 continue;
1552 }
1553 ppc_sbd = SYS_BUS_DEVICE(&s->apb_ppc[devinfo->ppc]);
1554 mr = sysbus_mmio_get_region(ppc_sbd, devinfo->ppc_port);
1555 memory_region_add_subregion(&s->container, devinfo->addr, mr);
1556 }
1557
1558 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
1559 Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
1560
1561 if (!object_property_set_int(splitter, "num-lines", 2, errp)) {
1562 return;
1563 }
1564 if (!qdev_realize(DEVICE(splitter), NULL, errp)) {
1565 return;
1566 }
1567 }
1568
1569 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
1570 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
1571
1572 armsse_forward_ppc(s, ppcname, i);
1573 g_free(ppcname);
1574 }
1575
1576 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
1577 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
1578
1579 armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
1580 g_free(ppcname);
1581 }
1582
1583 for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
1584
1585 DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
1586 char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
1587 i - NUM_EXTERNAL_PPCS);
1588 TZPPC *ppc = &s->apb_ppc[i - NUM_EXTERNAL_PPCS];
1589
1590 qdev_connect_gpio_out(devs, 0,
1591 qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
1592 qdev_connect_gpio_out(devs, 1,
1593 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
1594 qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
1595 qdev_get_gpio_in(devs, 0));
1596 g_free(gpioname);
1597 }
1598
1599
1600 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
1601 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
1602 DeviceState *dev_splitter = DEVICE(splitter);
1603
1604 if (!object_property_set_int(OBJECT(splitter), "num-lines", 2,
1605 errp)) {
1606 return;
1607 }
1608 if (!qdev_realize(DEVICE(splitter), NULL, errp)) {
1609 return;
1610 }
1611
1612 if (i < IOTS_NUM_EXP_MPC) {
1613
1614 s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
1615 qdev_connect_gpio_out(dev_splitter, 0,
1616 qdev_get_gpio_in_named(dev_secctl,
1617 "mpcexp_status", i));
1618 } else {
1619
1620 qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
1621 "irq", 0,
1622 qdev_get_gpio_in(dev_splitter, 0));
1623 qdev_connect_gpio_out(dev_splitter, 0,
1624 qdev_get_gpio_in_named(dev_secctl,
1625 "mpc_status",
1626 i - IOTS_NUM_EXP_MPC));
1627 }
1628
1629 qdev_connect_gpio_out(dev_splitter, 1,
1630 qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
1631 }
1632
1633
1634
1635 qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
1636 IOTS_NUM_EXP_MPC);
1637
1638 armsse_forward_sec_resp_cfg(s);
1639
1640
1641 qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
1642 qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
1643 qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
1644 qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
1645 armsse_get_common_irq_in(s, 11));
1646
1647
1648
1649
1650
1651
1652
1653 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
1654
1655
1656 armsse_mainclk_update(s, ClockUpdate);
1657}
1658
1659static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
1660 int *iregion, bool *exempt, bool *ns, bool *nsc)
1661{
1662
1663
1664
1665
1666
1667 ARMSSE *s = ARM_SSE(ii);
1668 int region = extract32(address, 28, 4);
1669
1670 *ns = !(region & 1);
1671 *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
1672
1673 *exempt = (address & 0xeff00000) == 0xe0000000;
1674 *iregion = region;
1675}
1676
1677static const VMStateDescription armsse_vmstate = {
1678 .name = "iotkit",
1679 .version_id = 2,
1680 .minimum_version_id = 2,
1681 .fields = (VMStateField[]) {
1682 VMSTATE_CLOCK(mainclk, ARMSSE),
1683 VMSTATE_CLOCK(s32kclk, ARMSSE),
1684 VMSTATE_UINT32(nsccfg, ARMSSE),
1685 VMSTATE_END_OF_LIST()
1686 }
1687};
1688
1689static void armsse_reset(DeviceState *dev)
1690{
1691 ARMSSE *s = ARM_SSE(dev);
1692
1693 s->nsccfg = 0;
1694}
1695
1696static void armsse_class_init(ObjectClass *klass, void *data)
1697{
1698 DeviceClass *dc = DEVICE_CLASS(klass);
1699 IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
1700 ARMSSEClass *asc = ARM_SSE_CLASS(klass);
1701 const ARMSSEInfo *info = data;
1702
1703 dc->realize = armsse_realize;
1704 dc->vmsd = &armsse_vmstate;
1705 device_class_set_props(dc, info->props);
1706 dc->reset = armsse_reset;
1707 iic->check = armsse_idau_check;
1708 asc->info = info;
1709}
1710
1711static const TypeInfo armsse_info = {
1712 .name = TYPE_ARM_SSE,
1713 .parent = TYPE_SYS_BUS_DEVICE,
1714 .instance_size = sizeof(ARMSSE),
1715 .class_size = sizeof(ARMSSEClass),
1716 .instance_init = armsse_init,
1717 .abstract = true,
1718 .interfaces = (InterfaceInfo[]) {
1719 { TYPE_IDAU_INTERFACE },
1720 { }
1721 }
1722};
1723
1724static void armsse_register_types(void)
1725{
1726 int i;
1727
1728 type_register_static(&armsse_info);
1729
1730 for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
1731 TypeInfo ti = {
1732 .name = armsse_variants[i].name,
1733 .parent = TYPE_ARM_SSE,
1734 .class_init = armsse_class_init,
1735 .class_data = (void *)&armsse_variants[i],
1736 };
1737 type_register(&ti);
1738 }
1739}
1740
1741type_init(armsse_register_types);
1742