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