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