]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/armsse.c
arm: Rename hw/arm/arm.h to hw/arm/boot.h
[mirror_qemu.git] / hw / arm / armsse.c
CommitLineData
9e5e54d1 1/*
93dbd103 2 * Arm SSE (Subsystems for Embedded): IoTKit
9e5e54d1
PM
3 *
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
6 *
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.
10 */
11
12#include "qemu/osdep.h"
13#include "qemu/log.h"
aab7a378 14#include "qemu/bitops.h"
9e5e54d1
PM
15#include "qapi/error.h"
16#include "trace.h"
17#include "hw/sysbus.h"
18#include "hw/registerfields.h"
6eee5d24 19#include "hw/arm/armsse.h"
12ec8bd5 20#include "hw/arm/boot.h"
9e5e54d1 21
dde0c491
PM
22/* Format of the System Information block SYS_CONFIG register */
23typedef enum SysConfigFormat {
24 IoTKitFormat,
25 SSE200Format,
26} SysConfigFormat;
27
4c3690b5
PM
28struct ARMSSEInfo {
29 const char *name;
f0cab7fe 30 int sram_banks;
91c1e9fc 31 int num_cpus;
dde0c491 32 uint32_t sys_version;
aab7a378 33 uint32_t cpuwait_rst;
dde0c491 34 SysConfigFormat sys_config_format;
f8574705 35 bool has_mhus;
e0b00f1b 36 bool has_ppus;
2357bca5 37 bool has_cachectrl;
c1f57257 38 bool has_cpusecctrl;
ade67dcd 39 bool has_cpuid;
4c3690b5
PM
40};
41
42static const ARMSSEInfo armsse_variants[] = {
43 {
44 .name = TYPE_IOTKIT,
f0cab7fe 45 .sram_banks = 1,
91c1e9fc 46 .num_cpus = 1,
dde0c491 47 .sys_version = 0x41743,
aab7a378 48 .cpuwait_rst = 0,
dde0c491 49 .sys_config_format = IoTKitFormat,
f8574705 50 .has_mhus = false,
e0b00f1b 51 .has_ppus = false,
2357bca5 52 .has_cachectrl = false,
c1f57257 53 .has_cpusecctrl = false,
ade67dcd 54 .has_cpuid = false,
4c3690b5 55 },
0829d24e
PM
56 {
57 .name = TYPE_SSE200,
58 .sram_banks = 4,
59 .num_cpus = 2,
60 .sys_version = 0x22041743,
aab7a378 61 .cpuwait_rst = 2,
0829d24e
PM
62 .sys_config_format = SSE200Format,
63 .has_mhus = true,
64 .has_ppus = true,
65 .has_cachectrl = true,
66 .has_cpusecctrl = true,
67 .has_cpuid = true,
68 },
4c3690b5
PM
69};
70
dde0c491
PM
71static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
72{
73 /* Return the SYS_CONFIG value for this SSE */
74 uint32_t sys_config;
75
76 switch (info->sys_config_format) {
77 case IoTKitFormat:
78 sys_config = 0;
79 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
80 sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
81 break;
82 case SSE200Format:
83 sys_config = 0;
84 sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
85 sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
86 sys_config = deposit32(sys_config, 24, 4, 2);
87 if (info->num_cpus > 1) {
88 sys_config = deposit32(sys_config, 10, 1, 1);
89 sys_config = deposit32(sys_config, 20, 4, info->sram_banks - 1);
90 sys_config = deposit32(sys_config, 28, 4, 2);
91 }
92 break;
93 default:
94 g_assert_not_reached();
95 }
96 return sys_config;
97}
98
d61e4e1f
PM
99/* Clock frequency in HZ of the 32KHz "slow clock" */
100#define S32KCLK (32 * 1000)
101
91c1e9fc
PM
102/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
103static bool irq_is_common[32] = {
104 [0 ... 5] = true,
105 /* 6, 7: per-CPU MHU interrupts */
106 [8 ... 12] = true,
107 /* 13: per-CPU icache interrupt */
108 /* 14: reserved */
109 [15 ... 20] = true,
110 /* 21: reserved */
111 [22 ... 26] = true,
112 /* 27: reserved */
113 /* 28, 29: per-CPU CTI interrupts */
114 /* 30, 31: reserved */
115};
116
3733f803
PM
117/*
118 * Create an alias region in @container of @size bytes starting at @base
9e5e54d1
PM
119 * which mirrors the memory starting at @orig.
120 */
3733f803
PM
121static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
122 const char *name, hwaddr base, hwaddr size, hwaddr orig)
9e5e54d1 123{
3733f803 124 memory_region_init_alias(mr, NULL, name, container, orig, size);
9e5e54d1 125 /* The alias is even lower priority than unimplemented_device regions */
3733f803 126 memory_region_add_subregion_overlap(container, base, mr, -1500);
9e5e54d1
PM
127}
128
9e5e54d1
PM
129static void irq_status_forwarder(void *opaque, int n, int level)
130{
131 qemu_irq destirq = opaque;
132
133 qemu_set_irq(destirq, level);
134}
135
136static void nsccfg_handler(void *opaque, int n, int level)
137{
93dbd103 138 ARMSSE *s = ARMSSE(opaque);
9e5e54d1
PM
139
140 s->nsccfg = level;
141}
142
13628891 143static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
9e5e54d1
PM
144{
145 /* Each of the 4 AHB and 4 APB PPCs that might be present in a
93dbd103 146 * system using the ARMSSE has a collection of control lines which
9e5e54d1 147 * are provided by the security controller and which we want to
93dbd103
PM
148 * expose as control lines on the ARMSSE device itself, so the
149 * code using the ARMSSE can wire them up to the PPCs.
9e5e54d1
PM
150 */
151 SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
13628891 152 DeviceState *armssedev = DEVICE(s);
9e5e54d1
PM
153 DeviceState *dev_secctl = DEVICE(&s->secctl);
154 DeviceState *dev_splitter = DEVICE(splitter);
155 char *name;
156
157 name = g_strdup_printf("%s_nonsec", ppcname);
13628891 158 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
159 g_free(name);
160 name = g_strdup_printf("%s_ap", ppcname);
13628891 161 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
162 g_free(name);
163 name = g_strdup_printf("%s_irq_enable", ppcname);
13628891 164 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
165 g_free(name);
166 name = g_strdup_printf("%s_irq_clear", ppcname);
13628891 167 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
168 g_free(name);
169
170 /* irq_status is a little more tricky, because we need to
171 * split it so we can send it both to the security controller
172 * and to our OR gate for the NVIC interrupt line.
173 * Connect up the splitter's outputs, and create a GPIO input
174 * which will pass the line state to the input splitter.
175 */
176 name = g_strdup_printf("%s_irq_status", ppcname);
177 qdev_connect_gpio_out(dev_splitter, 0,
178 qdev_get_gpio_in_named(dev_secctl,
179 name, 0));
180 qdev_connect_gpio_out(dev_splitter, 1,
181 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
182 s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
13628891 183 qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
9e5e54d1
PM
184 s->irq_status_in[ppcnum], name, 1);
185 g_free(name);
186}
187
13628891 188static void armsse_forward_sec_resp_cfg(ARMSSE *s)
9e5e54d1
PM
189{
190 /* Forward the 3rd output from the splitter device as a
13628891 191 * named GPIO output of the armsse object.
9e5e54d1
PM
192 */
193 DeviceState *dev = DEVICE(s);
194 DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
195
196 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
197 s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
198 s->sec_resp_cfg, 1);
199 qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
200}
201
13628891 202static void armsse_init(Object *obj)
9e5e54d1 203{
93dbd103 204 ARMSSE *s = ARMSSE(obj);
f0cab7fe
PM
205 ARMSSEClass *asc = ARMSSE_GET_CLASS(obj);
206 const ARMSSEInfo *info = asc->info;
9e5e54d1
PM
207 int i;
208
f0cab7fe 209 assert(info->sram_banks <= MAX_SRAM_BANKS);
91c1e9fc 210 assert(info->num_cpus <= SSE_MAX_CPUS);
f0cab7fe 211
13628891 212 memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
9e5e54d1 213
91c1e9fc 214 for (i = 0; i < info->num_cpus; i++) {
7cd3a2e0
PM
215 /*
216 * We put each CPU in its own cluster as they are logically
217 * distinct and may be configured differently.
218 */
219 char *name;
220
221 name = g_strdup_printf("cluster%d", i);
222 object_initialize_child(obj, name, &s->cluster[i],
223 sizeof(s->cluster[i]), TYPE_CPU_CLUSTER,
224 &error_abort, NULL);
225 qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
226 g_free(name);
227
228 name = g_strdup_printf("armv7m%d", i);
229 sysbus_init_child_obj(OBJECT(&s->cluster[i]), name,
230 &s->armv7m[i], sizeof(s->armv7m), TYPE_ARMV7M);
91c1e9fc
PM
231 qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
232 ARM_CPU_TYPE_NAME("cortex-m33"));
233 g_free(name);
d847ca51
PM
234 name = g_strdup_printf("arm-sse-cpu-container%d", i);
235 memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
236 g_free(name);
237 if (i > 0) {
238 name = g_strdup_printf("arm-sse-container-alias%d", i);
239 memory_region_init_alias(&s->container_alias[i - 1], obj,
240 name, &s->container, 0, UINT64_MAX);
241 g_free(name);
242 }
91c1e9fc 243 }
9e5e54d1 244
955cbc6b
TH
245 sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
246 TYPE_IOTKIT_SECCTL);
247 sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
248 TYPE_TZ_PPC);
249 sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
250 TYPE_TZ_PPC);
f0cab7fe
PM
251 for (i = 0; i < info->sram_banks; i++) {
252 char *name = g_strdup_printf("mpc%d", i);
253 sysbus_init_child_obj(obj, name, &s->mpc[i],
254 sizeof(s->mpc[i]), TYPE_TZ_MPC);
255 g_free(name);
256 }
955cbc6b
TH
257 object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
258 sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
259 &error_abort, NULL);
260
f0cab7fe 261 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
bb75e16d
PM
262 char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
263 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
264
955cbc6b
TH
265 object_initialize_child(obj, name, splitter, sizeof(*splitter),
266 TYPE_SPLIT_IRQ, &error_abort, NULL);
bb75e16d
PM
267 g_free(name);
268 }
955cbc6b
TH
269 sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0),
270 TYPE_CMSDK_APB_TIMER);
271 sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
272 TYPE_CMSDK_APB_TIMER);
e2d203ba
PM
273 sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
274 TYPE_CMSDK_APB_TIMER);
955cbc6b 275 sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
017d069d 276 TYPE_CMSDK_APB_DUALTIMER);
d61e4e1f
PM
277 sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
278 sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG);
279 sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog,
280 sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
281 sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
282 sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
13628891 283 sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl,
06e65af3 284 sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
13628891 285 sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
06e65af3 286 sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
f8574705
PM
287 if (info->has_mhus) {
288 sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
68d6b36f 289 TYPE_ARMSSE_MHU);
f8574705 290 sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
68d6b36f 291 TYPE_ARMSSE_MHU);
f8574705 292 }
e0b00f1b
PM
293 if (info->has_ppus) {
294 for (i = 0; i < info->num_cpus; i++) {
295 char *name = g_strdup_printf("CPU%dCORE_PPU", i);
296 int ppuidx = CPU0CORE_PPU + i;
297
298 sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
299 sizeof(s->ppu[ppuidx]),
300 TYPE_UNIMPLEMENTED_DEVICE);
301 g_free(name);
302 }
303 sysbus_init_child_obj(obj, "DBG_PPU", &s->ppu[DBG_PPU],
304 sizeof(s->ppu[DBG_PPU]),
305 TYPE_UNIMPLEMENTED_DEVICE);
306 for (i = 0; i < info->sram_banks; i++) {
307 char *name = g_strdup_printf("RAM%d_PPU", i);
308 int ppuidx = RAM0_PPU + i;
309
310 sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
311 sizeof(s->ppu[ppuidx]),
312 TYPE_UNIMPLEMENTED_DEVICE);
313 g_free(name);
314 }
315 }
2357bca5
PM
316 if (info->has_cachectrl) {
317 for (i = 0; i < info->num_cpus; i++) {
318 char *name = g_strdup_printf("cachectrl%d", i);
319
320 sysbus_init_child_obj(obj, name, &s->cachectrl[i],
321 sizeof(s->cachectrl[i]),
322 TYPE_UNIMPLEMENTED_DEVICE);
323 g_free(name);
324 }
325 }
c1f57257
PM
326 if (info->has_cpusecctrl) {
327 for (i = 0; i < info->num_cpus; i++) {
328 char *name = g_strdup_printf("cpusecctrl%d", i);
329
330 sysbus_init_child_obj(obj, name, &s->cpusecctrl[i],
331 sizeof(s->cpusecctrl[i]),
332 TYPE_UNIMPLEMENTED_DEVICE);
333 g_free(name);
334 }
335 }
ade67dcd
PM
336 if (info->has_cpuid) {
337 for (i = 0; i < info->num_cpus; i++) {
338 char *name = g_strdup_printf("cpuid%d", i);
339
340 sysbus_init_child_obj(obj, name, &s->cpuid[i],
341 sizeof(s->cpuid[i]),
342 TYPE_ARMSSE_CPUID);
343 g_free(name);
344 }
345 }
d61e4e1f
PM
346 object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
347 sizeof(s->nmi_orgate), TYPE_OR_IRQ,
348 &error_abort, NULL);
955cbc6b
TH
349 object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
350 sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
351 &error_abort, NULL);
352 object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter,
353 sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ,
354 &error_abort, NULL);
9e5e54d1
PM
355 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
356 char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
357 SplitIRQ *splitter = &s->ppc_irq_splitter[i];
358
955cbc6b
TH
359 object_initialize_child(obj, name, splitter, sizeof(*splitter),
360 TYPE_SPLIT_IRQ, &error_abort, NULL);
361 g_free(name);
9e5e54d1 362 }
91c1e9fc
PM
363 if (info->num_cpus > 1) {
364 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
365 if (irq_is_common[i]) {
366 char *name = g_strdup_printf("cpu-irq-splitter%d", i);
367 SplitIRQ *splitter = &s->cpu_irq_splitter[i];
368
369 object_initialize_child(obj, name, splitter, sizeof(*splitter),
370 TYPE_SPLIT_IRQ, &error_abort, NULL);
371 g_free(name);
372 }
373 }
374 }
9e5e54d1
PM
375}
376
13628891 377static void armsse_exp_irq(void *opaque, int n, int level)
9e5e54d1 378{
91c1e9fc 379 qemu_irq *irqarray = opaque;
9e5e54d1 380
91c1e9fc 381 qemu_set_irq(irqarray[n], level);
9e5e54d1
PM
382}
383
13628891 384static void armsse_mpcexp_status(void *opaque, int n, int level)
bb75e16d 385{
93dbd103 386 ARMSSE *s = ARMSSE(opaque);
bb75e16d
PM
387 qemu_set_irq(s->mpcexp_status_in[n], level);
388}
389
91c1e9fc
PM
390static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
391{
392 /*
393 * Return a qemu_irq which can be used to signal IRQ n to
394 * all CPUs in the SSE.
395 */
396 ARMSSEClass *asc = ARMSSE_GET_CLASS(s);
397 const ARMSSEInfo *info = asc->info;
398
399 assert(irq_is_common[irqno]);
400
401 if (info->num_cpus == 1) {
402 /* Only one CPU -- just connect directly to it */
403 return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
404 } else {
405 /* Connect to the splitter which feeds all CPUs */
406 return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
407 }
408}
409
e0b00f1b
PM
410static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
411{
412 /* Map a PPU unimplemented device stub */
413 DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
414
415 qdev_prop_set_string(dev, "name", name);
416 qdev_prop_set_uint64(dev, "size", 0x1000);
417 qdev_init_nofail(dev);
418 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
419}
420
13628891 421static void armsse_realize(DeviceState *dev, Error **errp)
9e5e54d1 422{
93dbd103 423 ARMSSE *s = ARMSSE(dev);
f0cab7fe
PM
424 ARMSSEClass *asc = ARMSSE_GET_CLASS(dev);
425 const ARMSSEInfo *info = asc->info;
9e5e54d1
PM
426 int i;
427 MemoryRegion *mr;
428 Error *err = NULL;
429 SysBusDevice *sbd_apb_ppc0;
430 SysBusDevice *sbd_secctl;
431 DeviceState *dev_apb_ppc0;
432 DeviceState *dev_apb_ppc1;
433 DeviceState *dev_secctl;
434 DeviceState *dev_splitter;
4b635cf7 435 uint32_t addr_width_max;
9e5e54d1
PM
436
437 if (!s->board_memory) {
438 error_setg(errp, "memory property was not set");
439 return;
440 }
441
442 if (!s->mainclk_frq) {
443 error_setg(errp, "MAINCLK property was not set");
444 return;
445 }
446
4b635cf7
PM
447 /* max SRAM_ADDR_WIDTH: 24 - log2(SRAM_NUM_BANK) */
448 assert(is_power_of_2(info->sram_banks));
449 addr_width_max = 24 - ctz32(info->sram_banks);
450 if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
451 error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
452 addr_width_max);
453 return;
454 }
455
9e5e54d1
PM
456 /* Handling of which devices should be available only to secure
457 * code is usually done differently for M profile than for A profile.
458 * Instead of putting some devices only into the secure address space,
459 * devices exist in both address spaces but with hard-wired security
460 * permissions that will cause the CPU to fault for non-secure accesses.
461 *
93dbd103 462 * The ARMSSE has an IDAU (Implementation Defined Access Unit),
9e5e54d1 463 * which specifies hard-wired security permissions for different
93dbd103 464 * areas of the physical address space. For the ARMSSE IDAU, the
9e5e54d1
PM
465 * top 4 bits of the physical address are the IDAU region ID, and
466 * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
467 * region, otherwise it is an S region.
468 *
469 * The various devices and RAMs are generally all mapped twice,
470 * once into a region that the IDAU defines as secure and once
471 * into a non-secure region. They sit behind either a Memory
472 * Protection Controller (for RAM) or a Peripheral Protection
473 * Controller (for devices), which allow a more fine grained
474 * configuration of whether non-secure accesses are permitted.
475 *
476 * (The other place that guest software can configure security
477 * permissions is in the architected SAU (Security Attribution
478 * Unit), which is entirely inside the CPU. The IDAU can upgrade
479 * the security attributes for a region to more restrictive than
480 * the SAU specifies, but cannot downgrade them.)
481 *
482 * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
483 * 0x20000000..0x2007ffff 32KB FPGA block RAM
484 * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
485 * 0x40000000..0x4000ffff base peripheral region 1
93dbd103 486 * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE)
9e5e54d1
PM
487 * 0x40020000..0x4002ffff system control element peripherals
488 * 0x40080000..0x400fffff base peripheral region 2
489 * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
490 */
491
d847ca51 492 memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
9e5e54d1 493
91c1e9fc
PM
494 for (i = 0; i < info->num_cpus; i++) {
495 DeviceState *cpudev = DEVICE(&s->armv7m[i]);
496 Object *cpuobj = OBJECT(&s->armv7m[i]);
497 int j;
498 char *gpioname;
499
500 qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
501 /*
aab7a378
PM
502 * In real hardware the initial Secure VTOR is set from the INITSVTOR*
503 * registers in the IoT Kit System Control Register block. In QEMU
504 * we set the initial value here, and also the reset value of the
505 * sysctl register, from this object's QOM init-svtor property.
506 * If the guest changes the INITSVTOR* registers at runtime then the
507 * code in iotkit-sysctl.c will update the CPU init-svtor property
508 * (which will then take effect on the next CPU warm-reset).
509 *
510 * Note that typically a board using the SSE-200 will have a system
511 * control processor whose boot firmware initializes the INITSVTOR*
512 * registers before powering up the CPUs. QEMU doesn't emulate
91c1e9fc 513 * the control processor, so instead we behave in the way that the
aab7a378
PM
514 * firmware does: the initial value should be set by the board code
515 * (using the init-svtor property on the ARMSSE object) to match
516 * whatever its firmware does.
91c1e9fc 517 */
32187419 518 qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
91c1e9fc 519 /*
aab7a378
PM
520 * CPUs start powered down if the corresponding bit in the CPUWAIT
521 * register is 1. In real hardware the CPUWAIT register reset value is
522 * a configurable property of the SSE-200 (via the CPUWAIT0_RST and
523 * CPUWAIT1_RST parameters), but since all the boards we care about
524 * start CPU0 and leave CPU1 powered off, we hard-code that in
525 * info->cpuwait_rst for now. We can add QOM properties for this
91c1e9fc
PM
526 * later if necessary.
527 */
aab7a378 528 if (extract32(info->cpuwait_rst, i, 1)) {
91c1e9fc
PM
529 object_property_set_bool(cpuobj, true, "start-powered-off", &err);
530 if (err) {
531 error_propagate(errp, err);
532 return;
533 }
534 }
d847ca51
PM
535
536 if (i > 0) {
537 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
538 &s->container_alias[i - 1], -1);
539 } else {
540 memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
541 &s->container, -1);
542 }
543 object_property_set_link(cpuobj, OBJECT(&s->cpu_container[i]),
544 "memory", &err);
91c1e9fc
PM
545 if (err) {
546 error_propagate(errp, err);
547 return;
548 }
549 object_property_set_link(cpuobj, OBJECT(s), "idau", &err);
550 if (err) {
551 error_propagate(errp, err);
552 return;
553 }
554 object_property_set_bool(cpuobj, true, "realized", &err);
555 if (err) {
556 error_propagate(errp, err);
557 return;
558 }
7cd3a2e0
PM
559 /*
560 * The cluster must be realized after the armv7m container, as
561 * the container's CPU object is only created on realize, and the
562 * CPU must exist and have been parented into the cluster before
563 * the cluster is realized.
564 */
565 object_property_set_bool(OBJECT(&s->cluster[i]),
566 true, "realized", &err);
567 if (err) {
568 error_propagate(errp, err);
569 return;
570 }
91c1e9fc
PM
571
572 /* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
573 s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
574 for (j = 0; j < s->exp_numirq; j++) {
5007c904 575 s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + 32);
91c1e9fc
PM
576 }
577 if (i == 0) {
578 gpioname = g_strdup("EXP_IRQ");
579 } else {
580 gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
581 }
582 qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
583 s->exp_irqs[i],
584 gpioname, s->exp_numirq);
585 g_free(gpioname);
9e5e54d1
PM
586 }
587
91c1e9fc
PM
588 /* Wire up the splitters that connect common IRQs to all CPUs */
589 if (info->num_cpus > 1) {
590 for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
591 if (irq_is_common[i]) {
592 Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
593 DeviceState *devs = DEVICE(splitter);
594 int cpunum;
595
596 object_property_set_int(splitter, info->num_cpus,
597 "num-lines", &err);
598 if (err) {
599 error_propagate(errp, err);
600 return;
601 }
602 object_property_set_bool(splitter, true, "realized", &err);
603 if (err) {
604 error_propagate(errp, err);
605 return;
606 }
607 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
608 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
609
610 qdev_connect_gpio_out(devs, cpunum,
611 qdev_get_gpio_in(cpudev, i));
612 }
613 }
614 }
9e5e54d1 615 }
9e5e54d1
PM
616
617 /* Set up the big aliases first */
3733f803
PM
618 make_alias(s, &s->alias1, &s->container, "alias 1",
619 0x10000000, 0x10000000, 0x00000000);
620 make_alias(s, &s->alias2, &s->container,
621 "alias 2", 0x30000000, 0x10000000, 0x20000000);
9e5e54d1
PM
622 /* The 0x50000000..0x5fffffff region is not a pure alias: it has
623 * a few extra devices that only appear there (generally the
624 * control interfaces for the protection controllers).
625 * We implement this by mapping those devices over the top of this
3733f803
PM
626 * alias MR at a higher priority. Some of the devices in this range
627 * are per-CPU, so we must put this alias in the per-cpu containers.
9e5e54d1 628 */
3733f803
PM
629 for (i = 0; i < info->num_cpus; i++) {
630 make_alias(s, &s->alias3[i], &s->cpu_container[i],
631 "alias 3", 0x50000000, 0x10000000, 0x40000000);
632 }
9e5e54d1
PM
633
634 /* Security controller */
635 object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
636 if (err) {
637 error_propagate(errp, err);
638 return;
639 }
640 sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
641 dev_secctl = DEVICE(&s->secctl);
642 sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
643 sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
644
645 s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
646 qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
647
648 /* The sec_resp_cfg output from the security controller must be split into
93dbd103
PM
649 * multiple lines, one for each of the PPCs within the ARMSSE and one
650 * that will be an output from the ARMSSE to the system.
9e5e54d1
PM
651 */
652 object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
653 "num-lines", &err);
654 if (err) {
655 error_propagate(errp, err);
656 return;
657 }
658 object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
659 "realized", &err);
660 if (err) {
661 error_propagate(errp, err);
662 return;
663 }
664 dev_splitter = DEVICE(&s->sec_resp_splitter);
665 qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
666 qdev_get_gpio_in(dev_splitter, 0));
667
f0cab7fe
PM
668 /* Each SRAM bank lives behind its own Memory Protection Controller */
669 for (i = 0; i < info->sram_banks; i++) {
670 char *ramname = g_strdup_printf("armsse.sram%d", i);
671 SysBusDevice *sbd_mpc;
4b635cf7 672 uint32_t sram_bank_size = 1 << s->sram_addr_width;
f0cab7fe 673
4b635cf7
PM
674 memory_region_init_ram(&s->sram[i], NULL, ramname,
675 sram_bank_size, &err);
f0cab7fe
PM
676 g_free(ramname);
677 if (err) {
678 error_propagate(errp, err);
679 return;
680 }
681 object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]),
682 "downstream", &err);
683 if (err) {
684 error_propagate(errp, err);
685 return;
686 }
687 object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err);
688 if (err) {
689 error_propagate(errp, err);
690 return;
691 }
692 /* Map the upstream end of the MPC into the right place... */
693 sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
4b635cf7
PM
694 memory_region_add_subregion(&s->container,
695 0x20000000 + i * sram_bank_size,
f0cab7fe
PM
696 sysbus_mmio_get_region(sbd_mpc, 1));
697 /* ...and its register interface */
698 memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
699 sysbus_mmio_get_region(sbd_mpc, 0));
af60b291 700 }
af60b291 701
bb75e16d
PM
702 /* We must OR together lines from the MPC splitters to go to the NVIC */
703 object_property_set_int(OBJECT(&s->mpc_irq_orgate),
f0cab7fe
PM
704 IOTS_NUM_EXP_MPC + info->sram_banks,
705 "num-lines", &err);
bb75e16d
PM
706 if (err) {
707 error_propagate(errp, err);
708 return;
709 }
710 object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
711 "realized", &err);
712 if (err) {
713 error_propagate(errp, err);
714 return;
715 }
716 qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
91c1e9fc 717 armsse_get_common_irq_in(s, 9));
bb75e16d 718
9e5e54d1
PM
719 /* Devices behind APB PPC0:
720 * 0x40000000: timer0
721 * 0x40001000: timer1
722 * 0x40002000: dual timer
f8574705
PM
723 * 0x40003000: MHU0 (SSE-200 only)
724 * 0x40004000: MHU1 (SSE-200 only)
9e5e54d1
PM
725 * We must configure and realize each downstream device and connect
726 * it to the appropriate PPC port; then we can realize the PPC and
727 * map its upstream ends to the right place in the container.
728 */
729 qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
730 object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
731 if (err) {
732 error_propagate(errp, err);
733 return;
734 }
735 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
91c1e9fc 736 armsse_get_common_irq_in(s, 3));
9e5e54d1
PM
737 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
738 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
739 if (err) {
740 error_propagate(errp, err);
741 return;
742 }
743
744 qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
745 object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
746 if (err) {
747 error_propagate(errp, err);
748 return;
749 }
750 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
91c1e9fc 751 armsse_get_common_irq_in(s, 4));
9e5e54d1
PM
752 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
753 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
754 if (err) {
755 error_propagate(errp, err);
756 return;
757 }
758
017d069d
PM
759
760 qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
9e5e54d1
PM
761 object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
762 if (err) {
763 error_propagate(errp, err);
764 return;
765 }
017d069d 766 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
91c1e9fc 767 armsse_get_common_irq_in(s, 5));
9e5e54d1
PM
768 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
769 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
770 if (err) {
771 error_propagate(errp, err);
772 return;
773 }
774
f8574705 775 if (info->has_mhus) {
68d6b36f
PM
776 /*
777 * An SSE-200 with only one CPU should have only one MHU created,
778 * with the region where the second MHU usually is being RAZ/WI.
779 * We don't implement that SSE-200 config; if we want to support
780 * it then this code needs to be enhanced to handle creating the
781 * RAZ/WI region instead of the second MHU.
782 */
783 assert(info->num_cpus == ARRAY_SIZE(s->mhu));
784
f8574705 785 for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
763e10f7 786 char *port;
68d6b36f
PM
787 int cpunum;
788 SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]);
f8574705 789
f8574705
PM
790 object_property_set_bool(OBJECT(&s->mhu[i]), true,
791 "realized", &err);
792 if (err) {
793 error_propagate(errp, err);
794 return;
795 }
763e10f7 796 port = g_strdup_printf("port[%d]", i + 3);
68d6b36f 797 mr = sysbus_mmio_get_region(mhu_sbd, 0);
f8574705
PM
798 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
799 port, &err);
763e10f7 800 g_free(port);
f8574705
PM
801 if (err) {
802 error_propagate(errp, err);
803 return;
804 }
68d6b36f
PM
805
806 /*
807 * Each MHU has an irq line for each CPU:
808 * MHU 0 irq line 0 -> CPU 0 IRQ 6
809 * MHU 0 irq line 1 -> CPU 1 IRQ 6
810 * MHU 1 irq line 0 -> CPU 0 IRQ 7
811 * MHU 1 irq line 1 -> CPU 1 IRQ 7
812 */
813 for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
814 DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
815
816 sysbus_connect_irq(mhu_sbd, cpunum,
817 qdev_get_gpio_in(cpudev, 6 + i));
818 }
f8574705
PM
819 }
820 }
821
9e5e54d1
PM
822 object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
823 if (err) {
824 error_propagate(errp, err);
825 return;
826 }
827
828 sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
829 dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
830
831 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
832 memory_region_add_subregion(&s->container, 0x40000000, mr);
833 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
834 memory_region_add_subregion(&s->container, 0x40001000, mr);
835 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
836 memory_region_add_subregion(&s->container, 0x40002000, mr);
f8574705
PM
837 if (info->has_mhus) {
838 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
839 memory_region_add_subregion(&s->container, 0x40003000, mr);
840 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
841 memory_region_add_subregion(&s->container, 0x40004000, mr);
842 }
9e5e54d1
PM
843 for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
844 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
845 qdev_get_gpio_in_named(dev_apb_ppc0,
846 "cfg_nonsec", i));
847 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
848 qdev_get_gpio_in_named(dev_apb_ppc0,
849 "cfg_ap", i));
850 }
851 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
852 qdev_get_gpio_in_named(dev_apb_ppc0,
853 "irq_enable", 0));
854 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
855 qdev_get_gpio_in_named(dev_apb_ppc0,
856 "irq_clear", 0));
857 qdev_connect_gpio_out(dev_splitter, 0,
858 qdev_get_gpio_in_named(dev_apb_ppc0,
859 "cfg_sec_resp", 0));
860
861 /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
862 * ones) are sent individually to the security controller, and also
863 * ORed together to give a single combined PPC interrupt to the NVIC.
864 */
865 object_property_set_int(OBJECT(&s->ppc_irq_orgate),
866 NUM_PPCS, "num-lines", &err);
867 if (err) {
868 error_propagate(errp, err);
869 return;
870 }
871 object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
872 "realized", &err);
873 if (err) {
874 error_propagate(errp, err);
875 return;
876 }
877 qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
91c1e9fc 878 armsse_get_common_irq_in(s, 10));
9e5e54d1 879
2357bca5
PM
880 /*
881 * 0x40010000 .. 0x4001ffff (and the 0x5001000... secure-only alias):
882 * private per-CPU region (all these devices are SSE-200 only):
883 * 0x50010000: L1 icache control registers
884 * 0x50011000: CPUSECCTRL (CPU local security control registers)
885 * 0x4001f000 and 0x5001f000: CPU_IDENTITY register block
886 */
887 if (info->has_cachectrl) {
888 for (i = 0; i < info->num_cpus; i++) {
889 char *name = g_strdup_printf("cachectrl%d", i);
890 MemoryRegion *mr;
891
892 qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
893 g_free(name);
894 qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
895 object_property_set_bool(OBJECT(&s->cachectrl[i]), true,
896 "realized", &err);
897 if (err) {
898 error_propagate(errp, err);
899 return;
900 }
901
902 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
903 memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
904 }
905 }
c1f57257
PM
906 if (info->has_cpusecctrl) {
907 for (i = 0; i < info->num_cpus; i++) {
908 char *name = g_strdup_printf("CPUSECCTRL%d", i);
909 MemoryRegion *mr;
910
911 qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
912 g_free(name);
913 qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
914 object_property_set_bool(OBJECT(&s->cpusecctrl[i]), true,
915 "realized", &err);
916 if (err) {
917 error_propagate(errp, err);
918 return;
919 }
920
921 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
922 memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
923 }
924 }
ade67dcd
PM
925 if (info->has_cpuid) {
926 for (i = 0; i < info->num_cpus; i++) {
927 MemoryRegion *mr;
928
929 qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
930 object_property_set_bool(OBJECT(&s->cpuid[i]), true,
931 "realized", &err);
932 if (err) {
933 error_propagate(errp, err);
934 return;
935 }
936
937 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
938 memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
939 }
940 }
9e5e54d1 941
93dbd103 942 /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
9e5e54d1
PM
943 /* Devices behind APB PPC1:
944 * 0x4002f000: S32K timer
945 */
e2d203ba 946 qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
9e5e54d1
PM
947 object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
948 if (err) {
949 error_propagate(errp, err);
950 return;
951 }
e2d203ba 952 sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
91c1e9fc 953 armsse_get_common_irq_in(s, 2));
9e5e54d1
PM
954 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
955 object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
956 if (err) {
957 error_propagate(errp, err);
958 return;
959 }
960
961 object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
962 if (err) {
963 error_propagate(errp, err);
964 return;
965 }
966 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
967 memory_region_add_subregion(&s->container, 0x4002f000, mr);
968
969 dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
970 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
971 qdev_get_gpio_in_named(dev_apb_ppc1,
972 "cfg_nonsec", 0));
973 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
974 qdev_get_gpio_in_named(dev_apb_ppc1,
975 "cfg_ap", 0));
976 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
977 qdev_get_gpio_in_named(dev_apb_ppc1,
978 "irq_enable", 0));
979 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
980 qdev_get_gpio_in_named(dev_apb_ppc1,
981 "irq_clear", 0));
982 qdev_connect_gpio_out(dev_splitter, 1,
983 qdev_get_gpio_in_named(dev_apb_ppc1,
984 "cfg_sec_resp", 0));
985
dde0c491
PM
986 object_property_set_int(OBJECT(&s->sysinfo), info->sys_version,
987 "SYS_VERSION", &err);
988 if (err) {
989 error_propagate(errp, err);
990 return;
991 }
992 object_property_set_int(OBJECT(&s->sysinfo),
993 armsse_sys_config_value(s, info),
994 "SYS_CONFIG", &err);
995 if (err) {
996 error_propagate(errp, err);
997 return;
998 }
06e65af3
PM
999 object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
1000 if (err) {
1001 error_propagate(errp, err);
1002 return;
1003 }
1004 /* System information registers */
1005 sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
1006 /* System control registers */
04836414
PM
1007 object_property_set_int(OBJECT(&s->sysctl), info->sys_version,
1008 "SYS_VERSION", &err);
aab7a378
PM
1009 object_property_set_int(OBJECT(&s->sysctl), info->cpuwait_rst,
1010 "CPUWAIT_RST", &err);
1011 object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
1012 "INITSVTOR0_RST", &err);
1013 object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
1014 "INITSVTOR1_RST", &err);
06e65af3
PM
1015 object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
1016 if (err) {
1017 error_propagate(errp, err);
1018 return;
1019 }
1020 sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
d61e4e1f 1021
e0b00f1b
PM
1022 if (info->has_ppus) {
1023 /* CPUnCORE_PPU for each CPU */
1024 for (i = 0; i < info->num_cpus; i++) {
1025 char *name = g_strdup_printf("CPU%dCORE_PPU", i);
1026
1027 map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
1028 /*
1029 * We don't support CPU debug so don't create the
1030 * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
1031 */
1032 g_free(name);
1033 }
1034 map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
1035
1036 for (i = 0; i < info->sram_banks; i++) {
1037 char *name = g_strdup_printf("RAM%d_PPU", i);
1038
1039 map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
1040 g_free(name);
1041 }
1042 }
1043
d61e4e1f
PM
1044 /* This OR gate wires together outputs from the secure watchdogs to NMI */
1045 object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
1046 if (err) {
1047 error_propagate(errp, err);
1048 return;
1049 }
1050 object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err);
1051 if (err) {
1052 error_propagate(errp, err);
1053 return;
1054 }
1055 qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
1056 qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
1057
1058 qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
1059 object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err);
1060 if (err) {
1061 error_propagate(errp, err);
1062 return;
1063 }
1064 sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
1065 qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
1066 sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
9e5e54d1 1067
93dbd103 1068 /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
9e5e54d1 1069
d61e4e1f
PM
1070 qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
1071 object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
1072 if (err) {
1073 error_propagate(errp, err);
1074 return;
1075 }
1076 sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
91c1e9fc 1077 armsse_get_common_irq_in(s, 1));
d61e4e1f
PM
1078 sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
1079
1080 qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
1081 object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err);
1082 if (err) {
1083 error_propagate(errp, err);
1084 return;
1085 }
1086 sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
1087 qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
1088 sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
9e5e54d1 1089
9e5e54d1
PM
1090 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
1091 Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
1092
1093 object_property_set_int(splitter, 2, "num-lines", &err);
1094 if (err) {
1095 error_propagate(errp, err);
1096 return;
1097 }
1098 object_property_set_bool(splitter, true, "realized", &err);
1099 if (err) {
1100 error_propagate(errp, err);
1101 return;
1102 }
1103 }
1104
1105 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
1106 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
1107
13628891 1108 armsse_forward_ppc(s, ppcname, i);
9e5e54d1
PM
1109 g_free(ppcname);
1110 }
1111
1112 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
1113 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
1114
13628891 1115 armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
9e5e54d1
PM
1116 g_free(ppcname);
1117 }
1118
1119 for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
1120 /* Wire up IRQ splitter for internal PPCs */
1121 DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
1122 char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
1123 i - NUM_EXTERNAL_PPCS);
1124 TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
1125
1126 qdev_connect_gpio_out(devs, 0,
1127 qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
1128 qdev_connect_gpio_out(devs, 1,
1129 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
1130 qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
1131 qdev_get_gpio_in(devs, 0));
7a35383a 1132 g_free(gpioname);
9e5e54d1
PM
1133 }
1134
bb75e16d 1135 /* Wire up the splitters for the MPC IRQs */
f0cab7fe 1136 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
bb75e16d
PM
1137 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
1138 DeviceState *dev_splitter = DEVICE(splitter);
1139
1140 object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
1141 if (err) {
1142 error_propagate(errp, err);
1143 return;
1144 }
1145 object_property_set_bool(OBJECT(splitter), true, "realized", &err);
1146 if (err) {
1147 error_propagate(errp, err);
1148 return;
1149 }
1150
1151 if (i < IOTS_NUM_EXP_MPC) {
1152 /* Splitter input is from GPIO input line */
1153 s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
1154 qdev_connect_gpio_out(dev_splitter, 0,
1155 qdev_get_gpio_in_named(dev_secctl,
1156 "mpcexp_status", i));
1157 } else {
1158 /* Splitter input is from our own MPC */
f0cab7fe
PM
1159 qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
1160 "irq", 0,
bb75e16d
PM
1161 qdev_get_gpio_in(dev_splitter, 0));
1162 qdev_connect_gpio_out(dev_splitter, 0,
1163 qdev_get_gpio_in_named(dev_secctl,
1164 "mpc_status", 0));
1165 }
1166
1167 qdev_connect_gpio_out(dev_splitter, 1,
1168 qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
1169 }
1170 /* Create GPIO inputs which will pass the line state for our
1171 * mpcexp_irq inputs to the correct splitter devices.
1172 */
13628891 1173 qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
bb75e16d
PM
1174 IOTS_NUM_EXP_MPC);
1175
13628891 1176 armsse_forward_sec_resp_cfg(s);
9e5e54d1 1177
132b475a
PM
1178 /* Forward the MSC related signals */
1179 qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
1180 qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
1181 qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
1182 qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
91c1e9fc 1183 armsse_get_common_irq_in(s, 11));
132b475a
PM
1184
1185 /*
1186 * Expose our container region to the board model; this corresponds
1187 * to the AHB Slave Expansion ports which allow bus master devices
1188 * (eg DMA controllers) in the board model to make transactions into
93dbd103 1189 * devices in the ARMSSE.
132b475a
PM
1190 */
1191 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
1192
9e5e54d1
PM
1193 system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
1194}
1195
13628891 1196static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
9e5e54d1
PM
1197 int *iregion, bool *exempt, bool *ns, bool *nsc)
1198{
93dbd103
PM
1199 /*
1200 * For ARMSSE systems the IDAU responses are simple logical functions
9e5e54d1
PM
1201 * of the address bits. The NSC attribute is guest-adjustable via the
1202 * NSCCFG register in the security controller.
1203 */
93dbd103 1204 ARMSSE *s = ARMSSE(ii);
9e5e54d1
PM
1205 int region = extract32(address, 28, 4);
1206
1207 *ns = !(region & 1);
1208 *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
1209 /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
1210 *exempt = (address & 0xeff00000) == 0xe0000000;
1211 *iregion = region;
1212}
1213
13628891 1214static const VMStateDescription armsse_vmstate = {
9e5e54d1
PM
1215 .name = "iotkit",
1216 .version_id = 1,
1217 .minimum_version_id = 1,
1218 .fields = (VMStateField[]) {
93dbd103 1219 VMSTATE_UINT32(nsccfg, ARMSSE),
9e5e54d1
PM
1220 VMSTATE_END_OF_LIST()
1221 }
1222};
1223
13628891 1224static Property armsse_properties[] = {
93dbd103 1225 DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
9e5e54d1 1226 MemoryRegion *),
93dbd103
PM
1227 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
1228 DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
4b635cf7 1229 DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
32187419 1230 DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
9e5e54d1
PM
1231 DEFINE_PROP_END_OF_LIST()
1232};
1233
13628891 1234static void armsse_reset(DeviceState *dev)
9e5e54d1 1235{
93dbd103 1236 ARMSSE *s = ARMSSE(dev);
9e5e54d1
PM
1237
1238 s->nsccfg = 0;
1239}
1240
13628891 1241static void armsse_class_init(ObjectClass *klass, void *data)
9e5e54d1
PM
1242{
1243 DeviceClass *dc = DEVICE_CLASS(klass);
1244 IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
4c3690b5 1245 ARMSSEClass *asc = ARMSSE_CLASS(klass);
9e5e54d1 1246
13628891
PM
1247 dc->realize = armsse_realize;
1248 dc->vmsd = &armsse_vmstate;
1249 dc->props = armsse_properties;
1250 dc->reset = armsse_reset;
1251 iic->check = armsse_idau_check;
4c3690b5 1252 asc->info = data;
9e5e54d1
PM
1253}
1254
4c3690b5 1255static const TypeInfo armsse_info = {
93dbd103 1256 .name = TYPE_ARMSSE,
9e5e54d1 1257 .parent = TYPE_SYS_BUS_DEVICE,
93dbd103 1258 .instance_size = sizeof(ARMSSE),
13628891 1259 .instance_init = armsse_init,
4c3690b5 1260 .abstract = true,
9e5e54d1
PM
1261 .interfaces = (InterfaceInfo[]) {
1262 { TYPE_IDAU_INTERFACE },
1263 { }
1264 }
1265};
1266
4c3690b5 1267static void armsse_register_types(void)
9e5e54d1 1268{
4c3690b5
PM
1269 int i;
1270
1271 type_register_static(&armsse_info);
1272
1273 for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
1274 TypeInfo ti = {
1275 .name = armsse_variants[i].name,
1276 .parent = TYPE_ARMSSE,
13628891 1277 .class_init = armsse_class_init,
4c3690b5
PM
1278 .class_data = (void *)&armsse_variants[i],
1279 };
1280 type_register(&ti);
1281 }
9e5e54d1
PM
1282}
1283
4c3690b5 1284type_init(armsse_register_types);