2 * Arm SSE (Subsystems for Embedded): IoTKit
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 or
9 * (at your option) any later version.
12 #include "qemu/osdep.h"
14 #include "qemu/module.h"
15 #include "qemu/bitops.h"
16 #include "qapi/error.h"
18 #include "hw/sysbus.h"
19 #include "migration/vmstate.h"
20 #include "hw/registerfields.h"
21 #include "hw/arm/armsse.h"
22 #include "hw/arm/boot.h"
24 #include "hw/qdev-clock.h"
26 /* Format of the System Information block SYS_CONFIG register */
27 typedef enum SysConfigFormat
{
38 SysConfigFormat sys_config_format
;
47 static Property iotkit_properties
[] = {
48 DEFINE_PROP_LINK("memory", ARMSSE
, board_memory
, TYPE_MEMORY_REGION
,
50 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE
, exp_numirq
, 64),
51 DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE
, mainclk_frq
, 0),
52 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE
, sram_addr_width
, 15),
53 DEFINE_PROP_UINT32("init-svtor", ARMSSE
, init_svtor
, 0x10000000),
54 DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE
, cpu_fpu
[0], true),
55 DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE
, cpu_dsp
[0], true),
56 DEFINE_PROP_END_OF_LIST()
59 static Property armsse_properties
[] = {
60 DEFINE_PROP_LINK("memory", ARMSSE
, board_memory
, TYPE_MEMORY_REGION
,
62 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE
, exp_numirq
, 64),
63 DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE
, mainclk_frq
, 0),
64 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE
, sram_addr_width
, 15),
65 DEFINE_PROP_UINT32("init-svtor", ARMSSE
, init_svtor
, 0x10000000),
66 DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE
, cpu_fpu
[0], false),
67 DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE
, cpu_dsp
[0], false),
68 DEFINE_PROP_BOOL("CPU1_FPU", ARMSSE
, cpu_fpu
[1], true),
69 DEFINE_PROP_BOOL("CPU1_DSP", ARMSSE
, cpu_dsp
[1], true),
70 DEFINE_PROP_END_OF_LIST()
73 static const ARMSSEInfo armsse_variants
[] = {
78 .sys_version
= 0x41743,
80 .sys_config_format
= IoTKitFormat
,
83 .has_cachectrl
= false,
84 .has_cpusecctrl
= false,
86 .props
= iotkit_properties
,
92 .sys_version
= 0x22041743,
94 .sys_config_format
= SSE200Format
,
97 .has_cachectrl
= true,
98 .has_cpusecctrl
= true,
100 .props
= armsse_properties
,
104 static uint32_t armsse_sys_config_value(ARMSSE
*s
, const ARMSSEInfo
*info
)
106 /* Return the SYS_CONFIG value for this SSE */
109 switch (info
->sys_config_format
) {
112 sys_config
= deposit32(sys_config
, 0, 4, info
->sram_banks
);
113 sys_config
= deposit32(sys_config
, 4, 4, s
->sram_addr_width
- 12);
117 sys_config
= deposit32(sys_config
, 0, 4, info
->sram_banks
);
118 sys_config
= deposit32(sys_config
, 4, 5, s
->sram_addr_width
);
119 sys_config
= deposit32(sys_config
, 24, 4, 2);
120 if (info
->num_cpus
> 1) {
121 sys_config
= deposit32(sys_config
, 10, 1, 1);
122 sys_config
= deposit32(sys_config
, 20, 4, info
->sram_banks
- 1);
123 sys_config
= deposit32(sys_config
, 28, 4, 2);
127 g_assert_not_reached();
132 /* Clock frequency in HZ of the 32KHz "slow clock" */
133 #define S32KCLK (32 * 1000)
135 /* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
136 static bool irq_is_common
[32] = {
138 /* 6, 7: per-CPU MHU interrupts */
140 /* 13: per-CPU icache interrupt */
146 /* 28, 29: per-CPU CTI interrupts */
147 /* 30, 31: reserved */
151 * Create an alias region in @container of @size bytes starting at @base
152 * which mirrors the memory starting at @orig.
154 static void make_alias(ARMSSE
*s
, MemoryRegion
*mr
, MemoryRegion
*container
,
155 const char *name
, hwaddr base
, hwaddr size
, hwaddr orig
)
157 memory_region_init_alias(mr
, NULL
, name
, container
, orig
, size
);
158 /* The alias is even lower priority than unimplemented_device regions */
159 memory_region_add_subregion_overlap(container
, base
, mr
, -1500);
162 static void irq_status_forwarder(void *opaque
, int n
, int level
)
164 qemu_irq destirq
= opaque
;
166 qemu_set_irq(destirq
, level
);
169 static void nsccfg_handler(void *opaque
, int n
, int level
)
171 ARMSSE
*s
= ARM_SSE(opaque
);
176 static void armsse_forward_ppc(ARMSSE
*s
, const char *ppcname
, int ppcnum
)
178 /* Each of the 4 AHB and 4 APB PPCs that might be present in a
179 * system using the ARMSSE has a collection of control lines which
180 * are provided by the security controller and which we want to
181 * expose as control lines on the ARMSSE device itself, so the
182 * code using the ARMSSE can wire them up to the PPCs.
184 SplitIRQ
*splitter
= &s
->ppc_irq_splitter
[ppcnum
];
185 DeviceState
*armssedev
= DEVICE(s
);
186 DeviceState
*dev_secctl
= DEVICE(&s
->secctl
);
187 DeviceState
*dev_splitter
= DEVICE(splitter
);
190 name
= g_strdup_printf("%s_nonsec", ppcname
);
191 qdev_pass_gpios(dev_secctl
, armssedev
, name
);
193 name
= g_strdup_printf("%s_ap", ppcname
);
194 qdev_pass_gpios(dev_secctl
, armssedev
, name
);
196 name
= g_strdup_printf("%s_irq_enable", ppcname
);
197 qdev_pass_gpios(dev_secctl
, armssedev
, name
);
199 name
= g_strdup_printf("%s_irq_clear", ppcname
);
200 qdev_pass_gpios(dev_secctl
, armssedev
, name
);
203 /* irq_status is a little more tricky, because we need to
204 * split it so we can send it both to the security controller
205 * and to our OR gate for the NVIC interrupt line.
206 * Connect up the splitter's outputs, and create a GPIO input
207 * which will pass the line state to the input splitter.
209 name
= g_strdup_printf("%s_irq_status", ppcname
);
210 qdev_connect_gpio_out(dev_splitter
, 0,
211 qdev_get_gpio_in_named(dev_secctl
,
213 qdev_connect_gpio_out(dev_splitter
, 1,
214 qdev_get_gpio_in(DEVICE(&s
->ppc_irq_orgate
), ppcnum
));
215 s
->irq_status_in
[ppcnum
] = qdev_get_gpio_in(dev_splitter
, 0);
216 qdev_init_gpio_in_named_with_opaque(armssedev
, irq_status_forwarder
,
217 s
->irq_status_in
[ppcnum
], name
, 1);
221 static void armsse_forward_sec_resp_cfg(ARMSSE
*s
)
223 /* Forward the 3rd output from the splitter device as a
224 * named GPIO output of the armsse object.
226 DeviceState
*dev
= DEVICE(s
);
227 DeviceState
*dev_splitter
= DEVICE(&s
->sec_resp_splitter
);
229 qdev_init_gpio_out_named(dev
, &s
->sec_resp_cfg
, "sec_resp_cfg", 1);
230 s
->sec_resp_cfg_in
= qemu_allocate_irq(irq_status_forwarder
,
232 qdev_connect_gpio_out(dev_splitter
, 2, s
->sec_resp_cfg_in
);
235 static void armsse_init(Object
*obj
)
237 ARMSSE
*s
= ARM_SSE(obj
);
238 ARMSSEClass
*asc
= ARM_SSE_GET_CLASS(obj
);
239 const ARMSSEInfo
*info
= asc
->info
;
242 assert(info
->sram_banks
<= MAX_SRAM_BANKS
);
243 assert(info
->num_cpus
<= SSE_MAX_CPUS
);
245 s
->mainclk
= qdev_init_clock_in(DEVICE(s
), "MAINCLK", NULL
, NULL
);
246 s
->s32kclk
= qdev_init_clock_in(DEVICE(s
), "S32KCLK", NULL
, NULL
);
248 memory_region_init(&s
->container
, obj
, "armsse-container", UINT64_MAX
);
250 for (i
= 0; i
< info
->num_cpus
; i
++) {
252 * We put each CPU in its own cluster as they are logically
253 * distinct and may be configured differently.
257 name
= g_strdup_printf("cluster%d", i
);
258 object_initialize_child(obj
, name
, &s
->cluster
[i
], TYPE_CPU_CLUSTER
);
259 qdev_prop_set_uint32(DEVICE(&s
->cluster
[i
]), "cluster-id", i
);
262 name
= g_strdup_printf("armv7m%d", i
);
263 object_initialize_child(OBJECT(&s
->cluster
[i
]), name
, &s
->armv7m
[i
],
265 qdev_prop_set_string(DEVICE(&s
->armv7m
[i
]), "cpu-type",
266 ARM_CPU_TYPE_NAME("cortex-m33"));
268 name
= g_strdup_printf("arm-sse-cpu-container%d", i
);
269 memory_region_init(&s
->cpu_container
[i
], obj
, name
, UINT64_MAX
);
272 name
= g_strdup_printf("arm-sse-container-alias%d", i
);
273 memory_region_init_alias(&s
->container_alias
[i
- 1], obj
,
274 name
, &s
->container
, 0, UINT64_MAX
);
279 object_initialize_child(obj
, "secctl", &s
->secctl
, TYPE_IOTKIT_SECCTL
);
280 object_initialize_child(obj
, "apb-ppc0", &s
->apb_ppc0
, TYPE_TZ_PPC
);
281 object_initialize_child(obj
, "apb-ppc1", &s
->apb_ppc1
, TYPE_TZ_PPC
);
282 for (i
= 0; i
< info
->sram_banks
; i
++) {
283 char *name
= g_strdup_printf("mpc%d", i
);
284 object_initialize_child(obj
, name
, &s
->mpc
[i
], TYPE_TZ_MPC
);
287 object_initialize_child(obj
, "mpc-irq-orgate", &s
->mpc_irq_orgate
,
290 for (i
= 0; i
< IOTS_NUM_EXP_MPC
+ info
->sram_banks
; i
++) {
291 char *name
= g_strdup_printf("mpc-irq-splitter-%d", i
);
292 SplitIRQ
*splitter
= &s
->mpc_irq_splitter
[i
];
294 object_initialize_child(obj
, name
, splitter
, TYPE_SPLIT_IRQ
);
297 object_initialize_child(obj
, "timer0", &s
->timer0
, TYPE_CMSDK_APB_TIMER
);
298 object_initialize_child(obj
, "timer1", &s
->timer1
, TYPE_CMSDK_APB_TIMER
);
299 object_initialize_child(obj
, "s32ktimer", &s
->s32ktimer
,
300 TYPE_CMSDK_APB_TIMER
);
301 object_initialize_child(obj
, "dualtimer", &s
->dualtimer
,
302 TYPE_CMSDK_APB_DUALTIMER
);
303 object_initialize_child(obj
, "s32kwatchdog", &s
->s32kwatchdog
,
304 TYPE_CMSDK_APB_WATCHDOG
);
305 object_initialize_child(obj
, "nswatchdog", &s
->nswatchdog
,
306 TYPE_CMSDK_APB_WATCHDOG
);
307 object_initialize_child(obj
, "swatchdog", &s
->swatchdog
,
308 TYPE_CMSDK_APB_WATCHDOG
);
309 object_initialize_child(obj
, "armsse-sysctl", &s
->sysctl
,
311 object_initialize_child(obj
, "armsse-sysinfo", &s
->sysinfo
,
312 TYPE_IOTKIT_SYSINFO
);
313 if (info
->has_mhus
) {
314 object_initialize_child(obj
, "mhu0", &s
->mhu
[0], TYPE_ARMSSE_MHU
);
315 object_initialize_child(obj
, "mhu1", &s
->mhu
[1], TYPE_ARMSSE_MHU
);
317 if (info
->has_ppus
) {
318 for (i
= 0; i
< info
->num_cpus
; i
++) {
319 char *name
= g_strdup_printf("CPU%dCORE_PPU", i
);
320 int ppuidx
= CPU0CORE_PPU
+ i
;
322 object_initialize_child(obj
, name
, &s
->ppu
[ppuidx
],
323 TYPE_UNIMPLEMENTED_DEVICE
);
326 object_initialize_child(obj
, "DBG_PPU", &s
->ppu
[DBG_PPU
],
327 TYPE_UNIMPLEMENTED_DEVICE
);
328 for (i
= 0; i
< info
->sram_banks
; i
++) {
329 char *name
= g_strdup_printf("RAM%d_PPU", i
);
330 int ppuidx
= RAM0_PPU
+ i
;
332 object_initialize_child(obj
, name
, &s
->ppu
[ppuidx
],
333 TYPE_UNIMPLEMENTED_DEVICE
);
337 if (info
->has_cachectrl
) {
338 for (i
= 0; i
< info
->num_cpus
; i
++) {
339 char *name
= g_strdup_printf("cachectrl%d", i
);
341 object_initialize_child(obj
, name
, &s
->cachectrl
[i
],
342 TYPE_UNIMPLEMENTED_DEVICE
);
346 if (info
->has_cpusecctrl
) {
347 for (i
= 0; i
< info
->num_cpus
; i
++) {
348 char *name
= g_strdup_printf("cpusecctrl%d", i
);
350 object_initialize_child(obj
, name
, &s
->cpusecctrl
[i
],
351 TYPE_UNIMPLEMENTED_DEVICE
);
355 if (info
->has_cpuid
) {
356 for (i
= 0; i
< info
->num_cpus
; i
++) {
357 char *name
= g_strdup_printf("cpuid%d", i
);
359 object_initialize_child(obj
, name
, &s
->cpuid
[i
],
364 object_initialize_child(obj
, "nmi-orgate", &s
->nmi_orgate
, TYPE_OR_IRQ
);
365 object_initialize_child(obj
, "ppc-irq-orgate", &s
->ppc_irq_orgate
,
367 object_initialize_child(obj
, "sec-resp-splitter", &s
->sec_resp_splitter
,
369 for (i
= 0; i
< ARRAY_SIZE(s
->ppc_irq_splitter
); i
++) {
370 char *name
= g_strdup_printf("ppc-irq-splitter-%d", i
);
371 SplitIRQ
*splitter
= &s
->ppc_irq_splitter
[i
];
373 object_initialize_child(obj
, name
, splitter
, TYPE_SPLIT_IRQ
);
376 if (info
->num_cpus
> 1) {
377 for (i
= 0; i
< ARRAY_SIZE(s
->cpu_irq_splitter
); i
++) {
378 if (irq_is_common
[i
]) {
379 char *name
= g_strdup_printf("cpu-irq-splitter%d", i
);
380 SplitIRQ
*splitter
= &s
->cpu_irq_splitter
[i
];
382 object_initialize_child(obj
, name
, splitter
, TYPE_SPLIT_IRQ
);
389 static void armsse_exp_irq(void *opaque
, int n
, int level
)
391 qemu_irq
*irqarray
= opaque
;
393 qemu_set_irq(irqarray
[n
], level
);
396 static void armsse_mpcexp_status(void *opaque
, int n
, int level
)
398 ARMSSE
*s
= ARM_SSE(opaque
);
399 qemu_set_irq(s
->mpcexp_status_in
[n
], level
);
402 static qemu_irq
armsse_get_common_irq_in(ARMSSE
*s
, int irqno
)
405 * Return a qemu_irq which can be used to signal IRQ n to
406 * all CPUs in the SSE.
408 ARMSSEClass
*asc
= ARM_SSE_GET_CLASS(s
);
409 const ARMSSEInfo
*info
= asc
->info
;
411 assert(irq_is_common
[irqno
]);
413 if (info
->num_cpus
== 1) {
414 /* Only one CPU -- just connect directly to it */
415 return qdev_get_gpio_in(DEVICE(&s
->armv7m
[0]), irqno
);
417 /* Connect to the splitter which feeds all CPUs */
418 return qdev_get_gpio_in(DEVICE(&s
->cpu_irq_splitter
[irqno
]), 0);
422 static void map_ppu(ARMSSE
*s
, int ppuidx
, const char *name
, hwaddr addr
)
424 /* Map a PPU unimplemented device stub */
425 DeviceState
*dev
= DEVICE(&s
->ppu
[ppuidx
]);
427 qdev_prop_set_string(dev
, "name", name
);
428 qdev_prop_set_uint64(dev
, "size", 0x1000);
429 sysbus_realize(SYS_BUS_DEVICE(dev
), &error_fatal
);
430 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->ppu
[ppuidx
]), 0, addr
);
433 static void armsse_realize(DeviceState
*dev
, Error
**errp
)
435 ARMSSE
*s
= ARM_SSE(dev
);
436 ARMSSEClass
*asc
= ARM_SSE_GET_CLASS(dev
);
437 const ARMSSEInfo
*info
= asc
->info
;
441 SysBusDevice
*sbd_apb_ppc0
;
442 SysBusDevice
*sbd_secctl
;
443 DeviceState
*dev_apb_ppc0
;
444 DeviceState
*dev_apb_ppc1
;
445 DeviceState
*dev_secctl
;
446 DeviceState
*dev_splitter
;
447 uint32_t addr_width_max
;
449 if (!s
->board_memory
) {
450 error_setg(errp
, "memory property was not set");
454 if (!s
->mainclk_frq
) {
455 error_setg(errp
, "MAINCLK_FRQ property was not set");
459 assert(info
->num_cpus
<= SSE_MAX_CPUS
);
461 /* max SRAM_ADDR_WIDTH: 24 - log2(SRAM_NUM_BANK) */
462 assert(is_power_of_2(info
->sram_banks
));
463 addr_width_max
= 24 - ctz32(info
->sram_banks
);
464 if (s
->sram_addr_width
< 1 || s
->sram_addr_width
> addr_width_max
) {
465 error_setg(errp
, "SRAM_ADDR_WIDTH must be between 1 and %d",
470 /* Handling of which devices should be available only to secure
471 * code is usually done differently for M profile than for A profile.
472 * Instead of putting some devices only into the secure address space,
473 * devices exist in both address spaces but with hard-wired security
474 * permissions that will cause the CPU to fault for non-secure accesses.
476 * The ARMSSE has an IDAU (Implementation Defined Access Unit),
477 * which specifies hard-wired security permissions for different
478 * areas of the physical address space. For the ARMSSE IDAU, the
479 * top 4 bits of the physical address are the IDAU region ID, and
480 * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
481 * region, otherwise it is an S region.
483 * The various devices and RAMs are generally all mapped twice,
484 * once into a region that the IDAU defines as secure and once
485 * into a non-secure region. They sit behind either a Memory
486 * Protection Controller (for RAM) or a Peripheral Protection
487 * Controller (for devices), which allow a more fine grained
488 * configuration of whether non-secure accesses are permitted.
490 * (The other place that guest software can configure security
491 * permissions is in the architected SAU (Security Attribution
492 * Unit), which is entirely inside the CPU. The IDAU can upgrade
493 * the security attributes for a region to more restrictive than
494 * the SAU specifies, but cannot downgrade them.)
496 * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
497 * 0x20000000..0x2007ffff 32KB FPGA block RAM
498 * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
499 * 0x40000000..0x4000ffff base peripheral region 1
500 * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE)
501 * 0x40020000..0x4002ffff system control element peripherals
502 * 0x40080000..0x400fffff base peripheral region 2
503 * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
506 memory_region_add_subregion_overlap(&s
->container
, 0, s
->board_memory
, -2);
508 for (i
= 0; i
< info
->num_cpus
; i
++) {
509 DeviceState
*cpudev
= DEVICE(&s
->armv7m
[i
]);
510 Object
*cpuobj
= OBJECT(&s
->armv7m
[i
]);
514 qdev_prop_set_uint32(cpudev
, "num-irq", s
->exp_numirq
+ 32);
516 * In real hardware the initial Secure VTOR is set from the INITSVTOR*
517 * registers in the IoT Kit System Control Register block. In QEMU
518 * we set the initial value here, and also the reset value of the
519 * sysctl register, from this object's QOM init-svtor property.
520 * If the guest changes the INITSVTOR* registers at runtime then the
521 * code in iotkit-sysctl.c will update the CPU init-svtor property
522 * (which will then take effect on the next CPU warm-reset).
524 * Note that typically a board using the SSE-200 will have a system
525 * control processor whose boot firmware initializes the INITSVTOR*
526 * registers before powering up the CPUs. QEMU doesn't emulate
527 * the control processor, so instead we behave in the way that the
528 * firmware does: the initial value should be set by the board code
529 * (using the init-svtor property on the ARMSSE object) to match
530 * whatever its firmware does.
532 qdev_prop_set_uint32(cpudev
, "init-svtor", s
->init_svtor
);
534 * CPUs start powered down if the corresponding bit in the CPUWAIT
535 * register is 1. In real hardware the CPUWAIT register reset value is
536 * a configurable property of the SSE-200 (via the CPUWAIT0_RST and
537 * CPUWAIT1_RST parameters), but since all the boards we care about
538 * start CPU0 and leave CPU1 powered off, we hard-code that in
539 * info->cpuwait_rst for now. We can add QOM properties for this
540 * later if necessary.
542 if (extract32(info
->cpuwait_rst
, i
, 1)) {
543 if (!object_property_set_bool(cpuobj
, "start-powered-off", true,
548 if (!s
->cpu_fpu
[i
]) {
549 if (!object_property_set_bool(cpuobj
, "vfp", false, errp
)) {
553 if (!s
->cpu_dsp
[i
]) {
554 if (!object_property_set_bool(cpuobj
, "dsp", false, errp
)) {
560 memory_region_add_subregion_overlap(&s
->cpu_container
[i
], 0,
561 &s
->container_alias
[i
- 1], -1);
563 memory_region_add_subregion_overlap(&s
->cpu_container
[i
], 0,
566 object_property_set_link(cpuobj
, "memory",
567 OBJECT(&s
->cpu_container
[i
]), &error_abort
);
568 object_property_set_link(cpuobj
, "idau", OBJECT(s
), &error_abort
);
569 if (!sysbus_realize(SYS_BUS_DEVICE(cpuobj
), errp
)) {
573 * The cluster must be realized after the armv7m container, as
574 * the container's CPU object is only created on realize, and the
575 * CPU must exist and have been parented into the cluster before
576 * the cluster is realized.
578 if (!qdev_realize(DEVICE(&s
->cluster
[i
]), NULL
, errp
)) {
582 /* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
583 s
->exp_irqs
[i
] = g_new(qemu_irq
, s
->exp_numirq
);
584 for (j
= 0; j
< s
->exp_numirq
; j
++) {
585 s
->exp_irqs
[i
][j
] = qdev_get_gpio_in(cpudev
, j
+ 32);
588 gpioname
= g_strdup("EXP_IRQ");
590 gpioname
= g_strdup_printf("EXP_CPU%d_IRQ", i
);
592 qdev_init_gpio_in_named_with_opaque(dev
, armsse_exp_irq
,
594 gpioname
, s
->exp_numirq
);
598 /* Wire up the splitters that connect common IRQs to all CPUs */
599 if (info
->num_cpus
> 1) {
600 for (i
= 0; i
< ARRAY_SIZE(s
->cpu_irq_splitter
); i
++) {
601 if (irq_is_common
[i
]) {
602 Object
*splitter
= OBJECT(&s
->cpu_irq_splitter
[i
]);
603 DeviceState
*devs
= DEVICE(splitter
);
606 if (!object_property_set_int(splitter
, "num-lines",
607 info
->num_cpus
, errp
)) {
610 if (!qdev_realize(DEVICE(splitter
), NULL
, errp
)) {
613 for (cpunum
= 0; cpunum
< info
->num_cpus
; cpunum
++) {
614 DeviceState
*cpudev
= DEVICE(&s
->armv7m
[cpunum
]);
616 qdev_connect_gpio_out(devs
, cpunum
,
617 qdev_get_gpio_in(cpudev
, i
));
623 /* Set up the big aliases first */
624 make_alias(s
, &s
->alias1
, &s
->container
, "alias 1",
625 0x10000000, 0x10000000, 0x00000000);
626 make_alias(s
, &s
->alias2
, &s
->container
,
627 "alias 2", 0x30000000, 0x10000000, 0x20000000);
628 /* The 0x50000000..0x5fffffff region is not a pure alias: it has
629 * a few extra devices that only appear there (generally the
630 * control interfaces for the protection controllers).
631 * We implement this by mapping those devices over the top of this
632 * alias MR at a higher priority. Some of the devices in this range
633 * are per-CPU, so we must put this alias in the per-cpu containers.
635 for (i
= 0; i
< info
->num_cpus
; i
++) {
636 make_alias(s
, &s
->alias3
[i
], &s
->cpu_container
[i
],
637 "alias 3", 0x50000000, 0x10000000, 0x40000000);
640 /* Security controller */
641 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->secctl
), errp
)) {
644 sbd_secctl
= SYS_BUS_DEVICE(&s
->secctl
);
645 dev_secctl
= DEVICE(&s
->secctl
);
646 sysbus_mmio_map(sbd_secctl
, 0, 0x50080000);
647 sysbus_mmio_map(sbd_secctl
, 1, 0x40080000);
649 s
->nsc_cfg_in
= qemu_allocate_irq(nsccfg_handler
, s
, 1);
650 qdev_connect_gpio_out_named(dev_secctl
, "nsc_cfg", 0, s
->nsc_cfg_in
);
652 /* The sec_resp_cfg output from the security controller must be split into
653 * multiple lines, one for each of the PPCs within the ARMSSE and one
654 * that will be an output from the ARMSSE to the system.
656 if (!object_property_set_int(OBJECT(&s
->sec_resp_splitter
),
657 "num-lines", 3, errp
)) {
660 if (!qdev_realize(DEVICE(&s
->sec_resp_splitter
), NULL
, errp
)) {
663 dev_splitter
= DEVICE(&s
->sec_resp_splitter
);
664 qdev_connect_gpio_out_named(dev_secctl
, "sec_resp_cfg", 0,
665 qdev_get_gpio_in(dev_splitter
, 0));
667 /* Each SRAM bank lives behind its own Memory Protection Controller */
668 for (i
= 0; i
< info
->sram_banks
; i
++) {
669 char *ramname
= g_strdup_printf("armsse.sram%d", i
);
670 SysBusDevice
*sbd_mpc
;
671 uint32_t sram_bank_size
= 1 << s
->sram_addr_width
;
673 memory_region_init_ram(&s
->sram
[i
], NULL
, ramname
,
674 sram_bank_size
, &err
);
677 error_propagate(errp
, err
);
680 object_property_set_link(OBJECT(&s
->mpc
[i
]), "downstream",
681 OBJECT(&s
->sram
[i
]), &error_abort
);
682 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->mpc
[i
]), errp
)) {
685 /* Map the upstream end of the MPC into the right place... */
686 sbd_mpc
= SYS_BUS_DEVICE(&s
->mpc
[i
]);
687 memory_region_add_subregion(&s
->container
,
688 0x20000000 + i
* sram_bank_size
,
689 sysbus_mmio_get_region(sbd_mpc
, 1));
690 /* ...and its register interface */
691 memory_region_add_subregion(&s
->container
, 0x50083000 + i
* 0x1000,
692 sysbus_mmio_get_region(sbd_mpc
, 0));
695 /* We must OR together lines from the MPC splitters to go to the NVIC */
696 if (!object_property_set_int(OBJECT(&s
->mpc_irq_orgate
), "num-lines",
697 IOTS_NUM_EXP_MPC
+ info
->sram_banks
,
701 if (!qdev_realize(DEVICE(&s
->mpc_irq_orgate
), NULL
, errp
)) {
704 qdev_connect_gpio_out(DEVICE(&s
->mpc_irq_orgate
), 0,
705 armsse_get_common_irq_in(s
, 9));
707 /* Devices behind APB PPC0:
710 * 0x40002000: dual timer
711 * 0x40003000: MHU0 (SSE-200 only)
712 * 0x40004000: MHU1 (SSE-200 only)
713 * We must configure and realize each downstream device and connect
714 * it to the appropriate PPC port; then we can realize the PPC and
715 * map its upstream ends to the right place in the container.
717 qdev_prop_set_uint32(DEVICE(&s
->timer0
), "pclk-frq", s
->mainclk_frq
);
718 qdev_connect_clock_in(DEVICE(&s
->timer0
), "pclk", s
->mainclk
);
719 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->timer0
), errp
)) {
722 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->timer0
), 0,
723 armsse_get_common_irq_in(s
, 3));
724 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->timer0
), 0);
725 object_property_set_link(OBJECT(&s
->apb_ppc0
), "port[0]", OBJECT(mr
),
728 qdev_prop_set_uint32(DEVICE(&s
->timer1
), "pclk-frq", s
->mainclk_frq
);
729 qdev_connect_clock_in(DEVICE(&s
->timer1
), "pclk", s
->mainclk
);
730 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->timer1
), errp
)) {
733 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->timer1
), 0,
734 armsse_get_common_irq_in(s
, 4));
735 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->timer1
), 0);
736 object_property_set_link(OBJECT(&s
->apb_ppc0
), "port[1]", OBJECT(mr
),
739 qdev_prop_set_uint32(DEVICE(&s
->dualtimer
), "pclk-frq", s
->mainclk_frq
);
740 qdev_connect_clock_in(DEVICE(&s
->dualtimer
), "TIMCLK", s
->mainclk
);
741 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->dualtimer
), errp
)) {
744 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->dualtimer
), 0,
745 armsse_get_common_irq_in(s
, 5));
746 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->dualtimer
), 0);
747 object_property_set_link(OBJECT(&s
->apb_ppc0
), "port[2]", OBJECT(mr
),
750 if (info
->has_mhus
) {
752 * An SSE-200 with only one CPU should have only one MHU created,
753 * with the region where the second MHU usually is being RAZ/WI.
754 * We don't implement that SSE-200 config; if we want to support
755 * it then this code needs to be enhanced to handle creating the
756 * RAZ/WI region instead of the second MHU.
758 assert(info
->num_cpus
== ARRAY_SIZE(s
->mhu
));
760 for (i
= 0; i
< ARRAY_SIZE(s
->mhu
); i
++) {
763 SysBusDevice
*mhu_sbd
= SYS_BUS_DEVICE(&s
->mhu
[i
]);
765 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->mhu
[i
]), errp
)) {
768 port
= g_strdup_printf("port[%d]", i
+ 3);
769 mr
= sysbus_mmio_get_region(mhu_sbd
, 0);
770 object_property_set_link(OBJECT(&s
->apb_ppc0
), port
, OBJECT(mr
),
775 * Each MHU has an irq line for each CPU:
776 * MHU 0 irq line 0 -> CPU 0 IRQ 6
777 * MHU 0 irq line 1 -> CPU 1 IRQ 6
778 * MHU 1 irq line 0 -> CPU 0 IRQ 7
779 * MHU 1 irq line 1 -> CPU 1 IRQ 7
781 for (cpunum
= 0; cpunum
< info
->num_cpus
; cpunum
++) {
782 DeviceState
*cpudev
= DEVICE(&s
->armv7m
[cpunum
]);
784 sysbus_connect_irq(mhu_sbd
, cpunum
,
785 qdev_get_gpio_in(cpudev
, 6 + i
));
790 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->apb_ppc0
), errp
)) {
794 sbd_apb_ppc0
= SYS_BUS_DEVICE(&s
->apb_ppc0
);
795 dev_apb_ppc0
= DEVICE(&s
->apb_ppc0
);
797 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 0);
798 memory_region_add_subregion(&s
->container
, 0x40000000, mr
);
799 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 1);
800 memory_region_add_subregion(&s
->container
, 0x40001000, mr
);
801 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 2);
802 memory_region_add_subregion(&s
->container
, 0x40002000, mr
);
803 if (info
->has_mhus
) {
804 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 3);
805 memory_region_add_subregion(&s
->container
, 0x40003000, mr
);
806 mr
= sysbus_mmio_get_region(sbd_apb_ppc0
, 4);
807 memory_region_add_subregion(&s
->container
, 0x40004000, mr
);
809 for (i
= 0; i
< IOTS_APB_PPC0_NUM_PORTS
; i
++) {
810 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_nonsec", i
,
811 qdev_get_gpio_in_named(dev_apb_ppc0
,
813 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_ap", i
,
814 qdev_get_gpio_in_named(dev_apb_ppc0
,
817 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_irq_enable", 0,
818 qdev_get_gpio_in_named(dev_apb_ppc0
,
820 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc0_irq_clear", 0,
821 qdev_get_gpio_in_named(dev_apb_ppc0
,
823 qdev_connect_gpio_out(dev_splitter
, 0,
824 qdev_get_gpio_in_named(dev_apb_ppc0
,
827 /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
828 * ones) are sent individually to the security controller, and also
829 * ORed together to give a single combined PPC interrupt to the NVIC.
831 if (!object_property_set_int(OBJECT(&s
->ppc_irq_orgate
),
832 "num-lines", NUM_PPCS
, errp
)) {
835 if (!qdev_realize(DEVICE(&s
->ppc_irq_orgate
), NULL
, errp
)) {
838 qdev_connect_gpio_out(DEVICE(&s
->ppc_irq_orgate
), 0,
839 armsse_get_common_irq_in(s
, 10));
842 * 0x40010000 .. 0x4001ffff (and the 0x5001000... secure-only alias):
843 * private per-CPU region (all these devices are SSE-200 only):
844 * 0x50010000: L1 icache control registers
845 * 0x50011000: CPUSECCTRL (CPU local security control registers)
846 * 0x4001f000 and 0x5001f000: CPU_IDENTITY register block
848 if (info
->has_cachectrl
) {
849 for (i
= 0; i
< info
->num_cpus
; i
++) {
850 char *name
= g_strdup_printf("cachectrl%d", i
);
853 qdev_prop_set_string(DEVICE(&s
->cachectrl
[i
]), "name", name
);
855 qdev_prop_set_uint64(DEVICE(&s
->cachectrl
[i
]), "size", 0x1000);
856 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->cachectrl
[i
]), errp
)) {
860 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->cachectrl
[i
]), 0);
861 memory_region_add_subregion(&s
->cpu_container
[i
], 0x50010000, mr
);
864 if (info
->has_cpusecctrl
) {
865 for (i
= 0; i
< info
->num_cpus
; i
++) {
866 char *name
= g_strdup_printf("CPUSECCTRL%d", i
);
869 qdev_prop_set_string(DEVICE(&s
->cpusecctrl
[i
]), "name", name
);
871 qdev_prop_set_uint64(DEVICE(&s
->cpusecctrl
[i
]), "size", 0x1000);
872 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->cpusecctrl
[i
]), errp
)) {
876 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->cpusecctrl
[i
]), 0);
877 memory_region_add_subregion(&s
->cpu_container
[i
], 0x50011000, mr
);
880 if (info
->has_cpuid
) {
881 for (i
= 0; i
< info
->num_cpus
; i
++) {
884 qdev_prop_set_uint32(DEVICE(&s
->cpuid
[i
]), "CPUID", i
);
885 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->cpuid
[i
]), errp
)) {
889 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->cpuid
[i
]), 0);
890 memory_region_add_subregion(&s
->cpu_container
[i
], 0x4001F000, mr
);
894 /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
895 /* Devices behind APB PPC1:
896 * 0x4002f000: S32K timer
898 qdev_prop_set_uint32(DEVICE(&s
->s32ktimer
), "pclk-frq", S32KCLK
);
899 qdev_connect_clock_in(DEVICE(&s
->s32ktimer
), "pclk", s
->s32kclk
);
900 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->s32ktimer
), errp
)) {
903 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->s32ktimer
), 0,
904 armsse_get_common_irq_in(s
, 2));
905 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->s32ktimer
), 0);
906 object_property_set_link(OBJECT(&s
->apb_ppc1
), "port[0]", OBJECT(mr
),
909 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->apb_ppc1
), errp
)) {
912 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(&s
->apb_ppc1
), 0);
913 memory_region_add_subregion(&s
->container
, 0x4002f000, mr
);
915 dev_apb_ppc1
= DEVICE(&s
->apb_ppc1
);
916 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_nonsec", 0,
917 qdev_get_gpio_in_named(dev_apb_ppc1
,
919 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_ap", 0,
920 qdev_get_gpio_in_named(dev_apb_ppc1
,
922 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_irq_enable", 0,
923 qdev_get_gpio_in_named(dev_apb_ppc1
,
925 qdev_connect_gpio_out_named(dev_secctl
, "apb_ppc1_irq_clear", 0,
926 qdev_get_gpio_in_named(dev_apb_ppc1
,
928 qdev_connect_gpio_out(dev_splitter
, 1,
929 qdev_get_gpio_in_named(dev_apb_ppc1
,
932 if (!object_property_set_int(OBJECT(&s
->sysinfo
), "SYS_VERSION",
933 info
->sys_version
, errp
)) {
936 if (!object_property_set_int(OBJECT(&s
->sysinfo
), "SYS_CONFIG",
937 armsse_sys_config_value(s
, info
), errp
)) {
940 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->sysinfo
), errp
)) {
943 /* System information registers */
944 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->sysinfo
), 0, 0x40020000);
945 /* System control registers */
946 object_property_set_int(OBJECT(&s
->sysctl
), "SYS_VERSION",
947 info
->sys_version
, &error_abort
);
948 object_property_set_int(OBJECT(&s
->sysctl
), "CPUWAIT_RST",
949 info
->cpuwait_rst
, &error_abort
);
950 object_property_set_int(OBJECT(&s
->sysctl
), "INITSVTOR0_RST",
951 s
->init_svtor
, &error_abort
);
952 object_property_set_int(OBJECT(&s
->sysctl
), "INITSVTOR1_RST",
953 s
->init_svtor
, &error_abort
);
954 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->sysctl
), errp
)) {
957 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->sysctl
), 0, 0x50021000);
959 if (info
->has_ppus
) {
960 /* CPUnCORE_PPU for each CPU */
961 for (i
= 0; i
< info
->num_cpus
; i
++) {
962 char *name
= g_strdup_printf("CPU%dCORE_PPU", i
);
964 map_ppu(s
, CPU0CORE_PPU
+ i
, name
, 0x50023000 + i
* 0x2000);
966 * We don't support CPU debug so don't create the
967 * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
971 map_ppu(s
, DBG_PPU
, "DBG_PPU", 0x50029000);
973 for (i
= 0; i
< info
->sram_banks
; i
++) {
974 char *name
= g_strdup_printf("RAM%d_PPU", i
);
976 map_ppu(s
, RAM0_PPU
+ i
, name
, 0x5002a000 + i
* 0x1000);
981 /* This OR gate wires together outputs from the secure watchdogs to NMI */
982 if (!object_property_set_int(OBJECT(&s
->nmi_orgate
), "num-lines", 2,
986 if (!qdev_realize(DEVICE(&s
->nmi_orgate
), NULL
, errp
)) {
989 qdev_connect_gpio_out(DEVICE(&s
->nmi_orgate
), 0,
990 qdev_get_gpio_in_named(DEVICE(&s
->armv7m
), "NMI", 0));
992 qdev_prop_set_uint32(DEVICE(&s
->s32kwatchdog
), "wdogclk-frq", S32KCLK
);
993 qdev_connect_clock_in(DEVICE(&s
->s32kwatchdog
), "WDOGCLK", s
->s32kclk
);
994 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->s32kwatchdog
), errp
)) {
997 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->s32kwatchdog
), 0,
998 qdev_get_gpio_in(DEVICE(&s
->nmi_orgate
), 0));
999 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->s32kwatchdog
), 0, 0x5002e000);
1001 /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
1003 qdev_prop_set_uint32(DEVICE(&s
->nswatchdog
), "wdogclk-frq", s
->mainclk_frq
);
1004 qdev_connect_clock_in(DEVICE(&s
->nswatchdog
), "WDOGCLK", s
->mainclk
);
1005 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->nswatchdog
), errp
)) {
1008 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->nswatchdog
), 0,
1009 armsse_get_common_irq_in(s
, 1));
1010 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->nswatchdog
), 0, 0x40081000);
1012 qdev_prop_set_uint32(DEVICE(&s
->swatchdog
), "wdogclk-frq", s
->mainclk_frq
);
1013 qdev_connect_clock_in(DEVICE(&s
->swatchdog
), "WDOGCLK", s
->mainclk
);
1014 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->swatchdog
), errp
)) {
1017 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->swatchdog
), 0,
1018 qdev_get_gpio_in(DEVICE(&s
->nmi_orgate
), 1));
1019 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->swatchdog
), 0, 0x50081000);
1021 for (i
= 0; i
< ARRAY_SIZE(s
->ppc_irq_splitter
); i
++) {
1022 Object
*splitter
= OBJECT(&s
->ppc_irq_splitter
[i
]);
1024 if (!object_property_set_int(splitter
, "num-lines", 2, errp
)) {
1027 if (!qdev_realize(DEVICE(splitter
), NULL
, errp
)) {
1032 for (i
= 0; i
< IOTS_NUM_AHB_EXP_PPC
; i
++) {
1033 char *ppcname
= g_strdup_printf("ahb_ppcexp%d", i
);
1035 armsse_forward_ppc(s
, ppcname
, i
);
1039 for (i
= 0; i
< IOTS_NUM_APB_EXP_PPC
; i
++) {
1040 char *ppcname
= g_strdup_printf("apb_ppcexp%d", i
);
1042 armsse_forward_ppc(s
, ppcname
, i
+ IOTS_NUM_AHB_EXP_PPC
);
1046 for (i
= NUM_EXTERNAL_PPCS
; i
< NUM_PPCS
; i
++) {
1047 /* Wire up IRQ splitter for internal PPCs */
1048 DeviceState
*devs
= DEVICE(&s
->ppc_irq_splitter
[i
]);
1049 char *gpioname
= g_strdup_printf("apb_ppc%d_irq_status",
1050 i
- NUM_EXTERNAL_PPCS
);
1051 TZPPC
*ppc
= (i
== NUM_EXTERNAL_PPCS
) ? &s
->apb_ppc0
: &s
->apb_ppc1
;
1053 qdev_connect_gpio_out(devs
, 0,
1054 qdev_get_gpio_in_named(dev_secctl
, gpioname
, 0));
1055 qdev_connect_gpio_out(devs
, 1,
1056 qdev_get_gpio_in(DEVICE(&s
->ppc_irq_orgate
), i
));
1057 qdev_connect_gpio_out_named(DEVICE(ppc
), "irq", 0,
1058 qdev_get_gpio_in(devs
, 0));
1062 /* Wire up the splitters for the MPC IRQs */
1063 for (i
= 0; i
< IOTS_NUM_EXP_MPC
+ info
->sram_banks
; i
++) {
1064 SplitIRQ
*splitter
= &s
->mpc_irq_splitter
[i
];
1065 DeviceState
*dev_splitter
= DEVICE(splitter
);
1067 if (!object_property_set_int(OBJECT(splitter
), "num-lines", 2,
1071 if (!qdev_realize(DEVICE(splitter
), NULL
, errp
)) {
1075 if (i
< IOTS_NUM_EXP_MPC
) {
1076 /* Splitter input is from GPIO input line */
1077 s
->mpcexp_status_in
[i
] = qdev_get_gpio_in(dev_splitter
, 0);
1078 qdev_connect_gpio_out(dev_splitter
, 0,
1079 qdev_get_gpio_in_named(dev_secctl
,
1080 "mpcexp_status", i
));
1082 /* Splitter input is from our own MPC */
1083 qdev_connect_gpio_out_named(DEVICE(&s
->mpc
[i
- IOTS_NUM_EXP_MPC
]),
1085 qdev_get_gpio_in(dev_splitter
, 0));
1086 qdev_connect_gpio_out(dev_splitter
, 0,
1087 qdev_get_gpio_in_named(dev_secctl
,
1089 i
- IOTS_NUM_EXP_MPC
));
1092 qdev_connect_gpio_out(dev_splitter
, 1,
1093 qdev_get_gpio_in(DEVICE(&s
->mpc_irq_orgate
), i
));
1095 /* Create GPIO inputs which will pass the line state for our
1096 * mpcexp_irq inputs to the correct splitter devices.
1098 qdev_init_gpio_in_named(dev
, armsse_mpcexp_status
, "mpcexp_status",
1101 armsse_forward_sec_resp_cfg(s
);
1103 /* Forward the MSC related signals */
1104 qdev_pass_gpios(dev_secctl
, dev
, "mscexp_status");
1105 qdev_pass_gpios(dev_secctl
, dev
, "mscexp_clear");
1106 qdev_pass_gpios(dev_secctl
, dev
, "mscexp_ns");
1107 qdev_connect_gpio_out_named(dev_secctl
, "msc_irq", 0,
1108 armsse_get_common_irq_in(s
, 11));
1111 * Expose our container region to the board model; this corresponds
1112 * to the AHB Slave Expansion ports which allow bus master devices
1113 * (eg DMA controllers) in the board model to make transactions into
1114 * devices in the ARMSSE.
1116 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->container
);
1118 system_clock_scale
= NANOSECONDS_PER_SECOND
/ s
->mainclk_frq
;
1121 static void armsse_idau_check(IDAUInterface
*ii
, uint32_t address
,
1122 int *iregion
, bool *exempt
, bool *ns
, bool *nsc
)
1125 * For ARMSSE systems the IDAU responses are simple logical functions
1126 * of the address bits. The NSC attribute is guest-adjustable via the
1127 * NSCCFG register in the security controller.
1129 ARMSSE
*s
= ARM_SSE(ii
);
1130 int region
= extract32(address
, 28, 4);
1132 *ns
= !(region
& 1);
1133 *nsc
= (region
== 1 && (s
->nsccfg
& 1)) || (region
== 3 && (s
->nsccfg
& 2));
1134 /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
1135 *exempt
= (address
& 0xeff00000) == 0xe0000000;
1139 static const VMStateDescription armsse_vmstate
= {
1142 .minimum_version_id
= 2,
1143 .fields
= (VMStateField
[]) {
1144 VMSTATE_CLOCK(mainclk
, ARMSSE
),
1145 VMSTATE_CLOCK(s32kclk
, ARMSSE
),
1146 VMSTATE_UINT32(nsccfg
, ARMSSE
),
1147 VMSTATE_END_OF_LIST()
1151 static void armsse_reset(DeviceState
*dev
)
1153 ARMSSE
*s
= ARM_SSE(dev
);
1158 static void armsse_class_init(ObjectClass
*klass
, void *data
)
1160 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1161 IDAUInterfaceClass
*iic
= IDAU_INTERFACE_CLASS(klass
);
1162 ARMSSEClass
*asc
= ARM_SSE_CLASS(klass
);
1163 const ARMSSEInfo
*info
= data
;
1165 dc
->realize
= armsse_realize
;
1166 dc
->vmsd
= &armsse_vmstate
;
1167 device_class_set_props(dc
, info
->props
);
1168 dc
->reset
= armsse_reset
;
1169 iic
->check
= armsse_idau_check
;
1173 static const TypeInfo armsse_info
= {
1174 .name
= TYPE_ARM_SSE
,
1175 .parent
= TYPE_SYS_BUS_DEVICE
,
1176 .instance_size
= sizeof(ARMSSE
),
1177 .class_size
= sizeof(ARMSSEClass
),
1178 .instance_init
= armsse_init
,
1180 .interfaces
= (InterfaceInfo
[]) {
1181 { TYPE_IDAU_INTERFACE
},
1186 static void armsse_register_types(void)
1190 type_register_static(&armsse_info
);
1192 for (i
= 0; i
< ARRAY_SIZE(armsse_variants
); i
++) {
1194 .name
= armsse_variants
[i
].name
,
1195 .parent
= TYPE_ARM_SSE
,
1196 .class_init
= armsse_class_init
,
1197 .class_data
= (void *)&armsse_variants
[i
],
1203 type_init(armsse_register_types
);