]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/armsse.c
hw/arm/armsse: Make number of SRAM banks parameterised
[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"
14#include "qapi/error.h"
15#include "trace.h"
16#include "hw/sysbus.h"
17#include "hw/registerfields.h"
6eee5d24 18#include "hw/arm/armsse.h"
9e5e54d1
PM
19#include "hw/arm/arm.h"
20
4c3690b5
PM
21struct ARMSSEInfo {
22 const char *name;
f0cab7fe 23 int sram_banks;
4c3690b5
PM
24};
25
26static const ARMSSEInfo armsse_variants[] = {
27 {
28 .name = TYPE_IOTKIT,
f0cab7fe 29 .sram_banks = 1,
4c3690b5
PM
30 },
31};
32
d61e4e1f
PM
33/* Clock frequency in HZ of the 32KHz "slow clock" */
34#define S32KCLK (32 * 1000)
35
9e5e54d1
PM
36/* Create an alias region of @size bytes starting at @base
37 * which mirrors the memory starting at @orig.
38 */
93dbd103 39static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
9e5e54d1
PM
40 hwaddr base, hwaddr size, hwaddr orig)
41{
42 memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
43 /* The alias is even lower priority than unimplemented_device regions */
44 memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
45}
46
9e5e54d1
PM
47static void irq_status_forwarder(void *opaque, int n, int level)
48{
49 qemu_irq destirq = opaque;
50
51 qemu_set_irq(destirq, level);
52}
53
54static void nsccfg_handler(void *opaque, int n, int level)
55{
93dbd103 56 ARMSSE *s = ARMSSE(opaque);
9e5e54d1
PM
57
58 s->nsccfg = level;
59}
60
13628891 61static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
9e5e54d1
PM
62{
63 /* Each of the 4 AHB and 4 APB PPCs that might be present in a
93dbd103 64 * system using the ARMSSE has a collection of control lines which
9e5e54d1 65 * are provided by the security controller and which we want to
93dbd103
PM
66 * expose as control lines on the ARMSSE device itself, so the
67 * code using the ARMSSE can wire them up to the PPCs.
9e5e54d1
PM
68 */
69 SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
13628891 70 DeviceState *armssedev = DEVICE(s);
9e5e54d1
PM
71 DeviceState *dev_secctl = DEVICE(&s->secctl);
72 DeviceState *dev_splitter = DEVICE(splitter);
73 char *name;
74
75 name = g_strdup_printf("%s_nonsec", ppcname);
13628891 76 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
77 g_free(name);
78 name = g_strdup_printf("%s_ap", ppcname);
13628891 79 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
80 g_free(name);
81 name = g_strdup_printf("%s_irq_enable", ppcname);
13628891 82 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
83 g_free(name);
84 name = g_strdup_printf("%s_irq_clear", ppcname);
13628891 85 qdev_pass_gpios(dev_secctl, armssedev, name);
9e5e54d1
PM
86 g_free(name);
87
88 /* irq_status is a little more tricky, because we need to
89 * split it so we can send it both to the security controller
90 * and to our OR gate for the NVIC interrupt line.
91 * Connect up the splitter's outputs, and create a GPIO input
92 * which will pass the line state to the input splitter.
93 */
94 name = g_strdup_printf("%s_irq_status", ppcname);
95 qdev_connect_gpio_out(dev_splitter, 0,
96 qdev_get_gpio_in_named(dev_secctl,
97 name, 0));
98 qdev_connect_gpio_out(dev_splitter, 1,
99 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
100 s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
13628891 101 qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
9e5e54d1
PM
102 s->irq_status_in[ppcnum], name, 1);
103 g_free(name);
104}
105
13628891 106static void armsse_forward_sec_resp_cfg(ARMSSE *s)
9e5e54d1
PM
107{
108 /* Forward the 3rd output from the splitter device as a
13628891 109 * named GPIO output of the armsse object.
9e5e54d1
PM
110 */
111 DeviceState *dev = DEVICE(s);
112 DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
113
114 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
115 s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
116 s->sec_resp_cfg, 1);
117 qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
118}
119
13628891 120static void armsse_init(Object *obj)
9e5e54d1 121{
93dbd103 122 ARMSSE *s = ARMSSE(obj);
f0cab7fe
PM
123 ARMSSEClass *asc = ARMSSE_GET_CLASS(obj);
124 const ARMSSEInfo *info = asc->info;
9e5e54d1
PM
125 int i;
126
f0cab7fe
PM
127 assert(info->sram_banks <= MAX_SRAM_BANKS);
128
13628891 129 memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
9e5e54d1 130
955cbc6b
TH
131 sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
132 TYPE_ARMV7M);
9e5e54d1
PM
133 qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
134 ARM_CPU_TYPE_NAME("cortex-m33"));
135
955cbc6b
TH
136 sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
137 TYPE_IOTKIT_SECCTL);
138 sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
139 TYPE_TZ_PPC);
140 sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
141 TYPE_TZ_PPC);
f0cab7fe
PM
142 for (i = 0; i < info->sram_banks; i++) {
143 char *name = g_strdup_printf("mpc%d", i);
144 sysbus_init_child_obj(obj, name, &s->mpc[i],
145 sizeof(s->mpc[i]), TYPE_TZ_MPC);
146 g_free(name);
147 }
955cbc6b
TH
148 object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
149 sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
150 &error_abort, NULL);
151
f0cab7fe 152 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
bb75e16d
PM
153 char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
154 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
155
955cbc6b
TH
156 object_initialize_child(obj, name, splitter, sizeof(*splitter),
157 TYPE_SPLIT_IRQ, &error_abort, NULL);
bb75e16d
PM
158 g_free(name);
159 }
955cbc6b
TH
160 sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0),
161 TYPE_CMSDK_APB_TIMER);
162 sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
163 TYPE_CMSDK_APB_TIMER);
e2d203ba
PM
164 sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
165 TYPE_CMSDK_APB_TIMER);
955cbc6b 166 sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
017d069d 167 TYPE_CMSDK_APB_DUALTIMER);
d61e4e1f
PM
168 sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
169 sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG);
170 sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog,
171 sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
172 sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
173 sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
13628891 174 sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl,
06e65af3 175 sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
13628891 176 sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
06e65af3 177 sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
d61e4e1f
PM
178 object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
179 sizeof(s->nmi_orgate), TYPE_OR_IRQ,
180 &error_abort, NULL);
955cbc6b
TH
181 object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
182 sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
183 &error_abort, NULL);
184 object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter,
185 sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ,
186 &error_abort, NULL);
9e5e54d1
PM
187 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
188 char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
189 SplitIRQ *splitter = &s->ppc_irq_splitter[i];
190
955cbc6b
TH
191 object_initialize_child(obj, name, splitter, sizeof(*splitter),
192 TYPE_SPLIT_IRQ, &error_abort, NULL);
193 g_free(name);
9e5e54d1 194 }
9e5e54d1
PM
195}
196
13628891 197static void armsse_exp_irq(void *opaque, int n, int level)
9e5e54d1 198{
93dbd103 199 ARMSSE *s = ARMSSE(opaque);
9e5e54d1
PM
200
201 qemu_set_irq(s->exp_irqs[n], level);
202}
203
13628891 204static void armsse_mpcexp_status(void *opaque, int n, int level)
bb75e16d 205{
93dbd103 206 ARMSSE *s = ARMSSE(opaque);
bb75e16d
PM
207 qemu_set_irq(s->mpcexp_status_in[n], level);
208}
209
13628891 210static void armsse_realize(DeviceState *dev, Error **errp)
9e5e54d1 211{
93dbd103 212 ARMSSE *s = ARMSSE(dev);
f0cab7fe
PM
213 ARMSSEClass *asc = ARMSSE_GET_CLASS(dev);
214 const ARMSSEInfo *info = asc->info;
9e5e54d1
PM
215 int i;
216 MemoryRegion *mr;
217 Error *err = NULL;
218 SysBusDevice *sbd_apb_ppc0;
219 SysBusDevice *sbd_secctl;
220 DeviceState *dev_apb_ppc0;
221 DeviceState *dev_apb_ppc1;
222 DeviceState *dev_secctl;
223 DeviceState *dev_splitter;
224
225 if (!s->board_memory) {
226 error_setg(errp, "memory property was not set");
227 return;
228 }
229
230 if (!s->mainclk_frq) {
231 error_setg(errp, "MAINCLK property was not set");
232 return;
233 }
234
235 /* Handling of which devices should be available only to secure
236 * code is usually done differently for M profile than for A profile.
237 * Instead of putting some devices only into the secure address space,
238 * devices exist in both address spaces but with hard-wired security
239 * permissions that will cause the CPU to fault for non-secure accesses.
240 *
93dbd103 241 * The ARMSSE has an IDAU (Implementation Defined Access Unit),
9e5e54d1 242 * which specifies hard-wired security permissions for different
93dbd103 243 * areas of the physical address space. For the ARMSSE IDAU, the
9e5e54d1
PM
244 * top 4 bits of the physical address are the IDAU region ID, and
245 * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
246 * region, otherwise it is an S region.
247 *
248 * The various devices and RAMs are generally all mapped twice,
249 * once into a region that the IDAU defines as secure and once
250 * into a non-secure region. They sit behind either a Memory
251 * Protection Controller (for RAM) or a Peripheral Protection
252 * Controller (for devices), which allow a more fine grained
253 * configuration of whether non-secure accesses are permitted.
254 *
255 * (The other place that guest software can configure security
256 * permissions is in the architected SAU (Security Attribution
257 * Unit), which is entirely inside the CPU. The IDAU can upgrade
258 * the security attributes for a region to more restrictive than
259 * the SAU specifies, but cannot downgrade them.)
260 *
261 * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
262 * 0x20000000..0x2007ffff 32KB FPGA block RAM
263 * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
264 * 0x40000000..0x4000ffff base peripheral region 1
93dbd103 265 * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE)
9e5e54d1
PM
266 * 0x40020000..0x4002ffff system control element peripherals
267 * 0x40080000..0x400fffff base peripheral region 2
268 * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
269 */
270
271 memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
272
273 qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
274 /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
275 * register in the IoT Kit System Control Register block, and the
276 * initial value of that is in turn specifiable by the FPGA that
277 * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
278 * and simply set the CPU's init-svtor to the IoT Kit default value.
279 */
280 qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
281 object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
282 "memory", &err);
283 if (err) {
284 error_propagate(errp, err);
285 return;
286 }
287 object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
288 if (err) {
289 error_propagate(errp, err);
290 return;
291 }
292 object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
293 if (err) {
294 error_propagate(errp, err);
295 return;
296 }
297
298 /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
299 s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
300 for (i = 0; i < s->exp_numirq; i++) {
301 s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
302 }
13628891 303 qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
9e5e54d1
PM
304
305 /* Set up the big aliases first */
306 make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
307 make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
308 /* The 0x50000000..0x5fffffff region is not a pure alias: it has
309 * a few extra devices that only appear there (generally the
310 * control interfaces for the protection controllers).
311 * We implement this by mapping those devices over the top of this
312 * alias MR at a higher priority.
313 */
314 make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
315
9e5e54d1
PM
316
317 /* Security controller */
318 object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
319 if (err) {
320 error_propagate(errp, err);
321 return;
322 }
323 sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
324 dev_secctl = DEVICE(&s->secctl);
325 sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
326 sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
327
328 s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
329 qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
330
331 /* The sec_resp_cfg output from the security controller must be split into
93dbd103
PM
332 * multiple lines, one for each of the PPCs within the ARMSSE and one
333 * that will be an output from the ARMSSE to the system.
9e5e54d1
PM
334 */
335 object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
336 "num-lines", &err);
337 if (err) {
338 error_propagate(errp, err);
339 return;
340 }
341 object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
342 "realized", &err);
343 if (err) {
344 error_propagate(errp, err);
345 return;
346 }
347 dev_splitter = DEVICE(&s->sec_resp_splitter);
348 qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
349 qdev_get_gpio_in(dev_splitter, 0));
350
f0cab7fe
PM
351 /* Each SRAM bank lives behind its own Memory Protection Controller */
352 for (i = 0; i < info->sram_banks; i++) {
353 char *ramname = g_strdup_printf("armsse.sram%d", i);
354 SysBusDevice *sbd_mpc;
355
356 memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
357 g_free(ramname);
358 if (err) {
359 error_propagate(errp, err);
360 return;
361 }
362 object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]),
363 "downstream", &err);
364 if (err) {
365 error_propagate(errp, err);
366 return;
367 }
368 object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err);
369 if (err) {
370 error_propagate(errp, err);
371 return;
372 }
373 /* Map the upstream end of the MPC into the right place... */
374 sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
375 memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
376 sysbus_mmio_get_region(sbd_mpc, 1));
377 /* ...and its register interface */
378 memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
379 sysbus_mmio_get_region(sbd_mpc, 0));
af60b291 380 }
af60b291 381
bb75e16d
PM
382 /* We must OR together lines from the MPC splitters to go to the NVIC */
383 object_property_set_int(OBJECT(&s->mpc_irq_orgate),
f0cab7fe
PM
384 IOTS_NUM_EXP_MPC + info->sram_banks,
385 "num-lines", &err);
bb75e16d
PM
386 if (err) {
387 error_propagate(errp, err);
388 return;
389 }
390 object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
391 "realized", &err);
392 if (err) {
393 error_propagate(errp, err);
394 return;
395 }
396 qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
397 qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
398
9e5e54d1
PM
399 /* Devices behind APB PPC0:
400 * 0x40000000: timer0
401 * 0x40001000: timer1
402 * 0x40002000: dual timer
403 * We must configure and realize each downstream device and connect
404 * it to the appropriate PPC port; then we can realize the PPC and
405 * map its upstream ends to the right place in the container.
406 */
407 qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
408 object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
409 if (err) {
410 error_propagate(errp, err);
411 return;
412 }
413 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
414 qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
415 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
416 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
417 if (err) {
418 error_propagate(errp, err);
419 return;
420 }
421
422 qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
423 object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
424 if (err) {
425 error_propagate(errp, err);
426 return;
427 }
428 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
984b0c10 429 qdev_get_gpio_in(DEVICE(&s->armv7m), 4));
9e5e54d1
PM
430 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
431 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
432 if (err) {
433 error_propagate(errp, err);
434 return;
435 }
436
017d069d
PM
437
438 qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
9e5e54d1
PM
439 object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
440 if (err) {
441 error_propagate(errp, err);
442 return;
443 }
017d069d
PM
444 sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
445 qdev_get_gpio_in(DEVICE(&s->armv7m), 5));
9e5e54d1
PM
446 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
447 object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
448 if (err) {
449 error_propagate(errp, err);
450 return;
451 }
452
453 object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
454 if (err) {
455 error_propagate(errp, err);
456 return;
457 }
458
459 sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
460 dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
461
462 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
463 memory_region_add_subregion(&s->container, 0x40000000, mr);
464 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
465 memory_region_add_subregion(&s->container, 0x40001000, mr);
466 mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
467 memory_region_add_subregion(&s->container, 0x40002000, mr);
468 for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
469 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
470 qdev_get_gpio_in_named(dev_apb_ppc0,
471 "cfg_nonsec", i));
472 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
473 qdev_get_gpio_in_named(dev_apb_ppc0,
474 "cfg_ap", i));
475 }
476 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
477 qdev_get_gpio_in_named(dev_apb_ppc0,
478 "irq_enable", 0));
479 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
480 qdev_get_gpio_in_named(dev_apb_ppc0,
481 "irq_clear", 0));
482 qdev_connect_gpio_out(dev_splitter, 0,
483 qdev_get_gpio_in_named(dev_apb_ppc0,
484 "cfg_sec_resp", 0));
485
486 /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
487 * ones) are sent individually to the security controller, and also
488 * ORed together to give a single combined PPC interrupt to the NVIC.
489 */
490 object_property_set_int(OBJECT(&s->ppc_irq_orgate),
491 NUM_PPCS, "num-lines", &err);
492 if (err) {
493 error_propagate(errp, err);
494 return;
495 }
496 object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
497 "realized", &err);
498 if (err) {
499 error_propagate(errp, err);
500 return;
501 }
502 qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
503 qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
504
505 /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
506
93dbd103 507 /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
9e5e54d1
PM
508 /* Devices behind APB PPC1:
509 * 0x4002f000: S32K timer
510 */
e2d203ba 511 qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
9e5e54d1
PM
512 object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
513 if (err) {
514 error_propagate(errp, err);
515 return;
516 }
e2d203ba
PM
517 sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
518 qdev_get_gpio_in(DEVICE(&s->armv7m), 2));
9e5e54d1
PM
519 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
520 object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
521 if (err) {
522 error_propagate(errp, err);
523 return;
524 }
525
526 object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
527 if (err) {
528 error_propagate(errp, err);
529 return;
530 }
531 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
532 memory_region_add_subregion(&s->container, 0x4002f000, mr);
533
534 dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
535 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
536 qdev_get_gpio_in_named(dev_apb_ppc1,
537 "cfg_nonsec", 0));
538 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
539 qdev_get_gpio_in_named(dev_apb_ppc1,
540 "cfg_ap", 0));
541 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
542 qdev_get_gpio_in_named(dev_apb_ppc1,
543 "irq_enable", 0));
544 qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
545 qdev_get_gpio_in_named(dev_apb_ppc1,
546 "irq_clear", 0));
547 qdev_connect_gpio_out(dev_splitter, 1,
548 qdev_get_gpio_in_named(dev_apb_ppc1,
549 "cfg_sec_resp", 0));
550
06e65af3
PM
551 object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
552 if (err) {
553 error_propagate(errp, err);
554 return;
555 }
556 /* System information registers */
557 sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
558 /* System control registers */
559 object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
560 if (err) {
561 error_propagate(errp, err);
562 return;
563 }
564 sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
d61e4e1f
PM
565
566 /* This OR gate wires together outputs from the secure watchdogs to NMI */
567 object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
568 if (err) {
569 error_propagate(errp, err);
570 return;
571 }
572 object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err);
573 if (err) {
574 error_propagate(errp, err);
575 return;
576 }
577 qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
578 qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
579
580 qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
581 object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err);
582 if (err) {
583 error_propagate(errp, err);
584 return;
585 }
586 sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
587 qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
588 sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
9e5e54d1 589
93dbd103 590 /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
9e5e54d1 591
d61e4e1f
PM
592 qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
593 object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
594 if (err) {
595 error_propagate(errp, err);
596 return;
597 }
598 sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
599 qdev_get_gpio_in(DEVICE(&s->armv7m), 1));
600 sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
601
602 qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
603 object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err);
604 if (err) {
605 error_propagate(errp, err);
606 return;
607 }
608 sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
609 qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
610 sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
9e5e54d1 611
9e5e54d1
PM
612 for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
613 Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
614
615 object_property_set_int(splitter, 2, "num-lines", &err);
616 if (err) {
617 error_propagate(errp, err);
618 return;
619 }
620 object_property_set_bool(splitter, true, "realized", &err);
621 if (err) {
622 error_propagate(errp, err);
623 return;
624 }
625 }
626
627 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
628 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
629
13628891 630 armsse_forward_ppc(s, ppcname, i);
9e5e54d1
PM
631 g_free(ppcname);
632 }
633
634 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
635 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
636
13628891 637 armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
9e5e54d1
PM
638 g_free(ppcname);
639 }
640
641 for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
642 /* Wire up IRQ splitter for internal PPCs */
643 DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
644 char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
645 i - NUM_EXTERNAL_PPCS);
646 TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
647
648 qdev_connect_gpio_out(devs, 0,
649 qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
650 qdev_connect_gpio_out(devs, 1,
651 qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
652 qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
653 qdev_get_gpio_in(devs, 0));
7a35383a 654 g_free(gpioname);
9e5e54d1
PM
655 }
656
bb75e16d 657 /* Wire up the splitters for the MPC IRQs */
f0cab7fe 658 for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
bb75e16d
PM
659 SplitIRQ *splitter = &s->mpc_irq_splitter[i];
660 DeviceState *dev_splitter = DEVICE(splitter);
661
662 object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
663 if (err) {
664 error_propagate(errp, err);
665 return;
666 }
667 object_property_set_bool(OBJECT(splitter), true, "realized", &err);
668 if (err) {
669 error_propagate(errp, err);
670 return;
671 }
672
673 if (i < IOTS_NUM_EXP_MPC) {
674 /* Splitter input is from GPIO input line */
675 s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
676 qdev_connect_gpio_out(dev_splitter, 0,
677 qdev_get_gpio_in_named(dev_secctl,
678 "mpcexp_status", i));
679 } else {
680 /* Splitter input is from our own MPC */
f0cab7fe
PM
681 qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
682 "irq", 0,
bb75e16d
PM
683 qdev_get_gpio_in(dev_splitter, 0));
684 qdev_connect_gpio_out(dev_splitter, 0,
685 qdev_get_gpio_in_named(dev_secctl,
686 "mpc_status", 0));
687 }
688
689 qdev_connect_gpio_out(dev_splitter, 1,
690 qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
691 }
692 /* Create GPIO inputs which will pass the line state for our
693 * mpcexp_irq inputs to the correct splitter devices.
694 */
13628891 695 qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
bb75e16d
PM
696 IOTS_NUM_EXP_MPC);
697
13628891 698 armsse_forward_sec_resp_cfg(s);
9e5e54d1 699
132b475a
PM
700 /* Forward the MSC related signals */
701 qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
702 qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
703 qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
704 qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
705 qdev_get_gpio_in(DEVICE(&s->armv7m), 11));
706
707 /*
708 * Expose our container region to the board model; this corresponds
709 * to the AHB Slave Expansion ports which allow bus master devices
710 * (eg DMA controllers) in the board model to make transactions into
93dbd103 711 * devices in the ARMSSE.
132b475a
PM
712 */
713 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
714
9e5e54d1
PM
715 system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
716}
717
13628891 718static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
9e5e54d1
PM
719 int *iregion, bool *exempt, bool *ns, bool *nsc)
720{
93dbd103
PM
721 /*
722 * For ARMSSE systems the IDAU responses are simple logical functions
9e5e54d1
PM
723 * of the address bits. The NSC attribute is guest-adjustable via the
724 * NSCCFG register in the security controller.
725 */
93dbd103 726 ARMSSE *s = ARMSSE(ii);
9e5e54d1
PM
727 int region = extract32(address, 28, 4);
728
729 *ns = !(region & 1);
730 *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
731 /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
732 *exempt = (address & 0xeff00000) == 0xe0000000;
733 *iregion = region;
734}
735
13628891 736static const VMStateDescription armsse_vmstate = {
9e5e54d1
PM
737 .name = "iotkit",
738 .version_id = 1,
739 .minimum_version_id = 1,
740 .fields = (VMStateField[]) {
93dbd103 741 VMSTATE_UINT32(nsccfg, ARMSSE),
9e5e54d1
PM
742 VMSTATE_END_OF_LIST()
743 }
744};
745
13628891 746static Property armsse_properties[] = {
93dbd103 747 DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
9e5e54d1 748 MemoryRegion *),
93dbd103
PM
749 DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
750 DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
9e5e54d1
PM
751 DEFINE_PROP_END_OF_LIST()
752};
753
13628891 754static void armsse_reset(DeviceState *dev)
9e5e54d1 755{
93dbd103 756 ARMSSE *s = ARMSSE(dev);
9e5e54d1
PM
757
758 s->nsccfg = 0;
759}
760
13628891 761static void armsse_class_init(ObjectClass *klass, void *data)
9e5e54d1
PM
762{
763 DeviceClass *dc = DEVICE_CLASS(klass);
764 IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
4c3690b5 765 ARMSSEClass *asc = ARMSSE_CLASS(klass);
9e5e54d1 766
13628891
PM
767 dc->realize = armsse_realize;
768 dc->vmsd = &armsse_vmstate;
769 dc->props = armsse_properties;
770 dc->reset = armsse_reset;
771 iic->check = armsse_idau_check;
4c3690b5 772 asc->info = data;
9e5e54d1
PM
773}
774
4c3690b5 775static const TypeInfo armsse_info = {
93dbd103 776 .name = TYPE_ARMSSE,
9e5e54d1 777 .parent = TYPE_SYS_BUS_DEVICE,
93dbd103 778 .instance_size = sizeof(ARMSSE),
13628891 779 .instance_init = armsse_init,
4c3690b5 780 .abstract = true,
9e5e54d1
PM
781 .interfaces = (InterfaceInfo[]) {
782 { TYPE_IDAU_INTERFACE },
783 { }
784 }
785};
786
4c3690b5 787static void armsse_register_types(void)
9e5e54d1 788{
4c3690b5
PM
789 int i;
790
791 type_register_static(&armsse_info);
792
793 for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
794 TypeInfo ti = {
795 .name = armsse_variants[i].name,
796 .parent = TYPE_ARMSSE,
13628891 797 .class_init = armsse_class_init,
4c3690b5
PM
798 .class_data = (void *)&armsse_variants[i],
799 };
800 type_register(&ti);
801 }
9e5e54d1
PM
802}
803
4c3690b5 804type_init(armsse_register_types);