19e5e54d1SPeter Maydell /* 293dbd103SPeter Maydell * Arm SSE (Subsystems for Embedded): IoTKit 39e5e54d1SPeter Maydell * 49e5e54d1SPeter Maydell * Copyright (c) 2018 Linaro Limited 59e5e54d1SPeter Maydell * Written by Peter Maydell 69e5e54d1SPeter Maydell * 79e5e54d1SPeter Maydell * This program is free software; you can redistribute it and/or modify 89e5e54d1SPeter Maydell * it under the terms of the GNU General Public License version 2 or 99e5e54d1SPeter Maydell * (at your option) any later version. 109e5e54d1SPeter Maydell */ 119e5e54d1SPeter Maydell 129e5e54d1SPeter Maydell #include "qemu/osdep.h" 139e5e54d1SPeter Maydell #include "qemu/log.h" 149e5e54d1SPeter Maydell #include "qapi/error.h" 159e5e54d1SPeter Maydell #include "trace.h" 169e5e54d1SPeter Maydell #include "hw/sysbus.h" 179e5e54d1SPeter Maydell #include "hw/registerfields.h" 18*6eee5d24SPeter Maydell #include "hw/arm/armsse.h" 199e5e54d1SPeter Maydell #include "hw/arm/arm.h" 209e5e54d1SPeter Maydell 214c3690b5SPeter Maydell struct ARMSSEInfo { 224c3690b5SPeter Maydell const char *name; 234c3690b5SPeter Maydell }; 244c3690b5SPeter Maydell 254c3690b5SPeter Maydell static const ARMSSEInfo armsse_variants[] = { 264c3690b5SPeter Maydell { 274c3690b5SPeter Maydell .name = TYPE_IOTKIT, 284c3690b5SPeter Maydell }, 294c3690b5SPeter Maydell }; 304c3690b5SPeter Maydell 31d61e4e1fSPeter Maydell /* Clock frequency in HZ of the 32KHz "slow clock" */ 32d61e4e1fSPeter Maydell #define S32KCLK (32 * 1000) 33d61e4e1fSPeter Maydell 349e5e54d1SPeter Maydell /* Create an alias region of @size bytes starting at @base 359e5e54d1SPeter Maydell * which mirrors the memory starting at @orig. 369e5e54d1SPeter Maydell */ 3793dbd103SPeter Maydell static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name, 389e5e54d1SPeter Maydell hwaddr base, hwaddr size, hwaddr orig) 399e5e54d1SPeter Maydell { 409e5e54d1SPeter Maydell memory_region_init_alias(mr, NULL, name, &s->container, orig, size); 419e5e54d1SPeter Maydell /* The alias is even lower priority than unimplemented_device regions */ 429e5e54d1SPeter Maydell memory_region_add_subregion_overlap(&s->container, base, mr, -1500); 439e5e54d1SPeter Maydell } 449e5e54d1SPeter Maydell 459e5e54d1SPeter Maydell static void irq_status_forwarder(void *opaque, int n, int level) 469e5e54d1SPeter Maydell { 479e5e54d1SPeter Maydell qemu_irq destirq = opaque; 489e5e54d1SPeter Maydell 499e5e54d1SPeter Maydell qemu_set_irq(destirq, level); 509e5e54d1SPeter Maydell } 519e5e54d1SPeter Maydell 529e5e54d1SPeter Maydell static void nsccfg_handler(void *opaque, int n, int level) 539e5e54d1SPeter Maydell { 5493dbd103SPeter Maydell ARMSSE *s = ARMSSE(opaque); 559e5e54d1SPeter Maydell 569e5e54d1SPeter Maydell s->nsccfg = level; 579e5e54d1SPeter Maydell } 589e5e54d1SPeter Maydell 5913628891SPeter Maydell static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum) 609e5e54d1SPeter Maydell { 619e5e54d1SPeter Maydell /* Each of the 4 AHB and 4 APB PPCs that might be present in a 6293dbd103SPeter Maydell * system using the ARMSSE has a collection of control lines which 639e5e54d1SPeter Maydell * are provided by the security controller and which we want to 6493dbd103SPeter Maydell * expose as control lines on the ARMSSE device itself, so the 6593dbd103SPeter Maydell * code using the ARMSSE can wire them up to the PPCs. 669e5e54d1SPeter Maydell */ 679e5e54d1SPeter Maydell SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum]; 6813628891SPeter Maydell DeviceState *armssedev = DEVICE(s); 699e5e54d1SPeter Maydell DeviceState *dev_secctl = DEVICE(&s->secctl); 709e5e54d1SPeter Maydell DeviceState *dev_splitter = DEVICE(splitter); 719e5e54d1SPeter Maydell char *name; 729e5e54d1SPeter Maydell 739e5e54d1SPeter Maydell name = g_strdup_printf("%s_nonsec", ppcname); 7413628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 759e5e54d1SPeter Maydell g_free(name); 769e5e54d1SPeter Maydell name = g_strdup_printf("%s_ap", ppcname); 7713628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 789e5e54d1SPeter Maydell g_free(name); 799e5e54d1SPeter Maydell name = g_strdup_printf("%s_irq_enable", ppcname); 8013628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 819e5e54d1SPeter Maydell g_free(name); 829e5e54d1SPeter Maydell name = g_strdup_printf("%s_irq_clear", ppcname); 8313628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 849e5e54d1SPeter Maydell g_free(name); 859e5e54d1SPeter Maydell 869e5e54d1SPeter Maydell /* irq_status is a little more tricky, because we need to 879e5e54d1SPeter Maydell * split it so we can send it both to the security controller 889e5e54d1SPeter Maydell * and to our OR gate for the NVIC interrupt line. 899e5e54d1SPeter Maydell * Connect up the splitter's outputs, and create a GPIO input 909e5e54d1SPeter Maydell * which will pass the line state to the input splitter. 919e5e54d1SPeter Maydell */ 929e5e54d1SPeter Maydell name = g_strdup_printf("%s_irq_status", ppcname); 939e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 949e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_secctl, 959e5e54d1SPeter Maydell name, 0)); 969e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 1, 979e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum)); 989e5e54d1SPeter Maydell s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0); 9913628891SPeter Maydell qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder, 1009e5e54d1SPeter Maydell s->irq_status_in[ppcnum], name, 1); 1019e5e54d1SPeter Maydell g_free(name); 1029e5e54d1SPeter Maydell } 1039e5e54d1SPeter Maydell 10413628891SPeter Maydell static void armsse_forward_sec_resp_cfg(ARMSSE *s) 1059e5e54d1SPeter Maydell { 1069e5e54d1SPeter Maydell /* Forward the 3rd output from the splitter device as a 10713628891SPeter Maydell * named GPIO output of the armsse object. 1089e5e54d1SPeter Maydell */ 1099e5e54d1SPeter Maydell DeviceState *dev = DEVICE(s); 1109e5e54d1SPeter Maydell DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter); 1119e5e54d1SPeter Maydell 1129e5e54d1SPeter Maydell qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1); 1139e5e54d1SPeter Maydell s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder, 1149e5e54d1SPeter Maydell s->sec_resp_cfg, 1); 1159e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in); 1169e5e54d1SPeter Maydell } 1179e5e54d1SPeter Maydell 11813628891SPeter Maydell static void armsse_init(Object *obj) 1199e5e54d1SPeter Maydell { 12093dbd103SPeter Maydell ARMSSE *s = ARMSSE(obj); 1219e5e54d1SPeter Maydell int i; 1229e5e54d1SPeter Maydell 12313628891SPeter Maydell memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX); 1249e5e54d1SPeter Maydell 125955cbc6bSThomas Huth sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), 1269e5e54d1SPeter Maydell TYPE_ARMV7M); 1279e5e54d1SPeter Maydell qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type", 1289e5e54d1SPeter Maydell ARM_CPU_TYPE_NAME("cortex-m33")); 1299e5e54d1SPeter Maydell 130955cbc6bSThomas Huth sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl), 1319e5e54d1SPeter Maydell TYPE_IOTKIT_SECCTL); 132955cbc6bSThomas Huth sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0), 1339e5e54d1SPeter Maydell TYPE_TZ_PPC); 134955cbc6bSThomas Huth sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1), 1359e5e54d1SPeter Maydell TYPE_TZ_PPC); 136955cbc6bSThomas Huth sysbus_init_child_obj(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC); 137955cbc6bSThomas Huth object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate, 138955cbc6bSThomas Huth sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ, 139955cbc6bSThomas Huth &error_abort, NULL); 140955cbc6bSThomas Huth 141bb75e16dSPeter Maydell for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) { 142bb75e16dSPeter Maydell char *name = g_strdup_printf("mpc-irq-splitter-%d", i); 143bb75e16dSPeter Maydell SplitIRQ *splitter = &s->mpc_irq_splitter[i]; 144bb75e16dSPeter Maydell 145955cbc6bSThomas Huth object_initialize_child(obj, name, splitter, sizeof(*splitter), 146955cbc6bSThomas Huth TYPE_SPLIT_IRQ, &error_abort, NULL); 147bb75e16dSPeter Maydell g_free(name); 148bb75e16dSPeter Maydell } 149955cbc6bSThomas Huth sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0), 1509e5e54d1SPeter Maydell TYPE_CMSDK_APB_TIMER); 151955cbc6bSThomas Huth sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1), 1529e5e54d1SPeter Maydell TYPE_CMSDK_APB_TIMER); 153e2d203baSPeter Maydell sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer), 154e2d203baSPeter Maydell TYPE_CMSDK_APB_TIMER); 155955cbc6bSThomas Huth sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer), 156017d069dSPeter Maydell TYPE_CMSDK_APB_DUALTIMER); 157d61e4e1fSPeter Maydell sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog, 158d61e4e1fSPeter Maydell sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG); 159d61e4e1fSPeter Maydell sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog, 160d61e4e1fSPeter Maydell sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG); 161d61e4e1fSPeter Maydell sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog, 162d61e4e1fSPeter Maydell sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG); 16313628891SPeter Maydell sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl, 16406e65af3SPeter Maydell sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL); 16513628891SPeter Maydell sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo, 16606e65af3SPeter Maydell sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO); 167d61e4e1fSPeter Maydell object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, 168d61e4e1fSPeter Maydell sizeof(s->nmi_orgate), TYPE_OR_IRQ, 169d61e4e1fSPeter Maydell &error_abort, NULL); 170955cbc6bSThomas Huth object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate, 171955cbc6bSThomas Huth sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ, 172955cbc6bSThomas Huth &error_abort, NULL); 173955cbc6bSThomas Huth object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter, 174955cbc6bSThomas Huth sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ, 175955cbc6bSThomas Huth &error_abort, NULL); 1769e5e54d1SPeter Maydell for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { 1779e5e54d1SPeter Maydell char *name = g_strdup_printf("ppc-irq-splitter-%d", i); 1789e5e54d1SPeter Maydell SplitIRQ *splitter = &s->ppc_irq_splitter[i]; 1799e5e54d1SPeter Maydell 180955cbc6bSThomas Huth object_initialize_child(obj, name, splitter, sizeof(*splitter), 181955cbc6bSThomas Huth TYPE_SPLIT_IRQ, &error_abort, NULL); 182955cbc6bSThomas Huth g_free(name); 1839e5e54d1SPeter Maydell } 1849e5e54d1SPeter Maydell } 1859e5e54d1SPeter Maydell 18613628891SPeter Maydell static void armsse_exp_irq(void *opaque, int n, int level) 1879e5e54d1SPeter Maydell { 18893dbd103SPeter Maydell ARMSSE *s = ARMSSE(opaque); 1899e5e54d1SPeter Maydell 1909e5e54d1SPeter Maydell qemu_set_irq(s->exp_irqs[n], level); 1919e5e54d1SPeter Maydell } 1929e5e54d1SPeter Maydell 19313628891SPeter Maydell static void armsse_mpcexp_status(void *opaque, int n, int level) 194bb75e16dSPeter Maydell { 19593dbd103SPeter Maydell ARMSSE *s = ARMSSE(opaque); 196bb75e16dSPeter Maydell qemu_set_irq(s->mpcexp_status_in[n], level); 197bb75e16dSPeter Maydell } 198bb75e16dSPeter Maydell 19913628891SPeter Maydell static void armsse_realize(DeviceState *dev, Error **errp) 2009e5e54d1SPeter Maydell { 20193dbd103SPeter Maydell ARMSSE *s = ARMSSE(dev); 2029e5e54d1SPeter Maydell int i; 2039e5e54d1SPeter Maydell MemoryRegion *mr; 2049e5e54d1SPeter Maydell Error *err = NULL; 2059e5e54d1SPeter Maydell SysBusDevice *sbd_apb_ppc0; 2069e5e54d1SPeter Maydell SysBusDevice *sbd_secctl; 2079e5e54d1SPeter Maydell DeviceState *dev_apb_ppc0; 2089e5e54d1SPeter Maydell DeviceState *dev_apb_ppc1; 2099e5e54d1SPeter Maydell DeviceState *dev_secctl; 2109e5e54d1SPeter Maydell DeviceState *dev_splitter; 2119e5e54d1SPeter Maydell 2129e5e54d1SPeter Maydell if (!s->board_memory) { 2139e5e54d1SPeter Maydell error_setg(errp, "memory property was not set"); 2149e5e54d1SPeter Maydell return; 2159e5e54d1SPeter Maydell } 2169e5e54d1SPeter Maydell 2179e5e54d1SPeter Maydell if (!s->mainclk_frq) { 2189e5e54d1SPeter Maydell error_setg(errp, "MAINCLK property was not set"); 2199e5e54d1SPeter Maydell return; 2209e5e54d1SPeter Maydell } 2219e5e54d1SPeter Maydell 2229e5e54d1SPeter Maydell /* Handling of which devices should be available only to secure 2239e5e54d1SPeter Maydell * code is usually done differently for M profile than for A profile. 2249e5e54d1SPeter Maydell * Instead of putting some devices only into the secure address space, 2259e5e54d1SPeter Maydell * devices exist in both address spaces but with hard-wired security 2269e5e54d1SPeter Maydell * permissions that will cause the CPU to fault for non-secure accesses. 2279e5e54d1SPeter Maydell * 22893dbd103SPeter Maydell * The ARMSSE has an IDAU (Implementation Defined Access Unit), 2299e5e54d1SPeter Maydell * which specifies hard-wired security permissions for different 23093dbd103SPeter Maydell * areas of the physical address space. For the ARMSSE IDAU, the 2319e5e54d1SPeter Maydell * top 4 bits of the physical address are the IDAU region ID, and 2329e5e54d1SPeter Maydell * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS 2339e5e54d1SPeter Maydell * region, otherwise it is an S region. 2349e5e54d1SPeter Maydell * 2359e5e54d1SPeter Maydell * The various devices and RAMs are generally all mapped twice, 2369e5e54d1SPeter Maydell * once into a region that the IDAU defines as secure and once 2379e5e54d1SPeter Maydell * into a non-secure region. They sit behind either a Memory 2389e5e54d1SPeter Maydell * Protection Controller (for RAM) or a Peripheral Protection 2399e5e54d1SPeter Maydell * Controller (for devices), which allow a more fine grained 2409e5e54d1SPeter Maydell * configuration of whether non-secure accesses are permitted. 2419e5e54d1SPeter Maydell * 2429e5e54d1SPeter Maydell * (The other place that guest software can configure security 2439e5e54d1SPeter Maydell * permissions is in the architected SAU (Security Attribution 2449e5e54d1SPeter Maydell * Unit), which is entirely inside the CPU. The IDAU can upgrade 2459e5e54d1SPeter Maydell * the security attributes for a region to more restrictive than 2469e5e54d1SPeter Maydell * the SAU specifies, but cannot downgrade them.) 2479e5e54d1SPeter Maydell * 2489e5e54d1SPeter Maydell * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff 2499e5e54d1SPeter Maydell * 0x20000000..0x2007ffff 32KB FPGA block RAM 2509e5e54d1SPeter Maydell * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff 2519e5e54d1SPeter Maydell * 0x40000000..0x4000ffff base peripheral region 1 25293dbd103SPeter Maydell * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE) 2539e5e54d1SPeter Maydell * 0x40020000..0x4002ffff system control element peripherals 2549e5e54d1SPeter Maydell * 0x40080000..0x400fffff base peripheral region 2 2559e5e54d1SPeter Maydell * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff 2569e5e54d1SPeter Maydell */ 2579e5e54d1SPeter Maydell 2589e5e54d1SPeter Maydell memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1); 2599e5e54d1SPeter Maydell 2609e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32); 2619e5e54d1SPeter Maydell /* In real hardware the initial Secure VTOR is set from the INITSVTOR0 2629e5e54d1SPeter Maydell * register in the IoT Kit System Control Register block, and the 2639e5e54d1SPeter Maydell * initial value of that is in turn specifiable by the FPGA that 2649e5e54d1SPeter Maydell * instantiates the IoT Kit. In QEMU we don't implement this wrinkle, 2659e5e54d1SPeter Maydell * and simply set the CPU's init-svtor to the IoT Kit default value. 2669e5e54d1SPeter Maydell */ 2679e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000); 2689e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container), 2699e5e54d1SPeter Maydell "memory", &err); 2709e5e54d1SPeter Maydell if (err) { 2719e5e54d1SPeter Maydell error_propagate(errp, err); 2729e5e54d1SPeter Maydell return; 2739e5e54d1SPeter Maydell } 2749e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err); 2759e5e54d1SPeter Maydell if (err) { 2769e5e54d1SPeter Maydell error_propagate(errp, err); 2779e5e54d1SPeter Maydell return; 2789e5e54d1SPeter Maydell } 2799e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); 2809e5e54d1SPeter Maydell if (err) { 2819e5e54d1SPeter Maydell error_propagate(errp, err); 2829e5e54d1SPeter Maydell return; 2839e5e54d1SPeter Maydell } 2849e5e54d1SPeter Maydell 2859e5e54d1SPeter Maydell /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */ 2869e5e54d1SPeter Maydell s->exp_irqs = g_new(qemu_irq, s->exp_numirq); 2879e5e54d1SPeter Maydell for (i = 0; i < s->exp_numirq; i++) { 2889e5e54d1SPeter Maydell s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32); 2899e5e54d1SPeter Maydell } 29013628891SPeter Maydell qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq); 2919e5e54d1SPeter Maydell 2929e5e54d1SPeter Maydell /* Set up the big aliases first */ 2939e5e54d1SPeter Maydell make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000); 2949e5e54d1SPeter Maydell make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000); 2959e5e54d1SPeter Maydell /* The 0x50000000..0x5fffffff region is not a pure alias: it has 2969e5e54d1SPeter Maydell * a few extra devices that only appear there (generally the 2979e5e54d1SPeter Maydell * control interfaces for the protection controllers). 2989e5e54d1SPeter Maydell * We implement this by mapping those devices over the top of this 2999e5e54d1SPeter Maydell * alias MR at a higher priority. 3009e5e54d1SPeter Maydell */ 3019e5e54d1SPeter Maydell make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000); 3029e5e54d1SPeter Maydell 3039e5e54d1SPeter Maydell 3049e5e54d1SPeter Maydell /* Security controller */ 3059e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err); 3069e5e54d1SPeter Maydell if (err) { 3079e5e54d1SPeter Maydell error_propagate(errp, err); 3089e5e54d1SPeter Maydell return; 3099e5e54d1SPeter Maydell } 3109e5e54d1SPeter Maydell sbd_secctl = SYS_BUS_DEVICE(&s->secctl); 3119e5e54d1SPeter Maydell dev_secctl = DEVICE(&s->secctl); 3129e5e54d1SPeter Maydell sysbus_mmio_map(sbd_secctl, 0, 0x50080000); 3139e5e54d1SPeter Maydell sysbus_mmio_map(sbd_secctl, 1, 0x40080000); 3149e5e54d1SPeter Maydell 3159e5e54d1SPeter Maydell s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1); 3169e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in); 3179e5e54d1SPeter Maydell 3189e5e54d1SPeter Maydell /* The sec_resp_cfg output from the security controller must be split into 31993dbd103SPeter Maydell * multiple lines, one for each of the PPCs within the ARMSSE and one 32093dbd103SPeter Maydell * that will be an output from the ARMSSE to the system. 3219e5e54d1SPeter Maydell */ 3229e5e54d1SPeter Maydell object_property_set_int(OBJECT(&s->sec_resp_splitter), 3, 3239e5e54d1SPeter Maydell "num-lines", &err); 3249e5e54d1SPeter Maydell if (err) { 3259e5e54d1SPeter Maydell error_propagate(errp, err); 3269e5e54d1SPeter Maydell return; 3279e5e54d1SPeter Maydell } 3289e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->sec_resp_splitter), true, 3299e5e54d1SPeter Maydell "realized", &err); 3309e5e54d1SPeter Maydell if (err) { 3319e5e54d1SPeter Maydell error_propagate(errp, err); 3329e5e54d1SPeter Maydell return; 3339e5e54d1SPeter Maydell } 3349e5e54d1SPeter Maydell dev_splitter = DEVICE(&s->sec_resp_splitter); 3359e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0, 3369e5e54d1SPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 3379e5e54d1SPeter Maydell 338af60b291SPeter Maydell /* This RAM lives behind the Memory Protection Controller */ 33913628891SPeter Maydell memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err); 340af60b291SPeter Maydell if (err) { 341af60b291SPeter Maydell error_propagate(errp, err); 342af60b291SPeter Maydell return; 343af60b291SPeter Maydell } 344af60b291SPeter Maydell object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0), 345af60b291SPeter Maydell "downstream", &err); 346af60b291SPeter Maydell if (err) { 347af60b291SPeter Maydell error_propagate(errp, err); 348af60b291SPeter Maydell return; 349af60b291SPeter Maydell } 350af60b291SPeter Maydell object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err); 351af60b291SPeter Maydell if (err) { 352af60b291SPeter Maydell error_propagate(errp, err); 353af60b291SPeter Maydell return; 354af60b291SPeter Maydell } 355af60b291SPeter Maydell /* Map the upstream end of the MPC into the right place... */ 356af60b291SPeter Maydell memory_region_add_subregion(&s->container, 0x20000000, 357af60b291SPeter Maydell sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc), 358af60b291SPeter Maydell 1)); 359af60b291SPeter Maydell /* ...and its register interface */ 360af60b291SPeter Maydell memory_region_add_subregion(&s->container, 0x50083000, 361af60b291SPeter Maydell sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc), 362af60b291SPeter Maydell 0)); 363af60b291SPeter Maydell 364bb75e16dSPeter Maydell /* We must OR together lines from the MPC splitters to go to the NVIC */ 365bb75e16dSPeter Maydell object_property_set_int(OBJECT(&s->mpc_irq_orgate), 366bb75e16dSPeter Maydell IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err); 367bb75e16dSPeter Maydell if (err) { 368bb75e16dSPeter Maydell error_propagate(errp, err); 369bb75e16dSPeter Maydell return; 370bb75e16dSPeter Maydell } 371bb75e16dSPeter Maydell object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true, 372bb75e16dSPeter Maydell "realized", &err); 373bb75e16dSPeter Maydell if (err) { 374bb75e16dSPeter Maydell error_propagate(errp, err); 375bb75e16dSPeter Maydell return; 376bb75e16dSPeter Maydell } 377bb75e16dSPeter Maydell qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0, 378bb75e16dSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 9)); 379bb75e16dSPeter Maydell 3809e5e54d1SPeter Maydell /* Devices behind APB PPC0: 3819e5e54d1SPeter Maydell * 0x40000000: timer0 3829e5e54d1SPeter Maydell * 0x40001000: timer1 3839e5e54d1SPeter Maydell * 0x40002000: dual timer 3849e5e54d1SPeter Maydell * We must configure and realize each downstream device and connect 3859e5e54d1SPeter Maydell * it to the appropriate PPC port; then we can realize the PPC and 3869e5e54d1SPeter Maydell * map its upstream ends to the right place in the container. 3879e5e54d1SPeter Maydell */ 3889e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq); 3899e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err); 3909e5e54d1SPeter Maydell if (err) { 3919e5e54d1SPeter Maydell error_propagate(errp, err); 3929e5e54d1SPeter Maydell return; 3939e5e54d1SPeter Maydell } 3949e5e54d1SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0, 3959e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 3)); 3969e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0); 3979e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err); 3989e5e54d1SPeter Maydell if (err) { 3999e5e54d1SPeter Maydell error_propagate(errp, err); 4009e5e54d1SPeter Maydell return; 4019e5e54d1SPeter Maydell } 4029e5e54d1SPeter Maydell 4039e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq); 4049e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err); 4059e5e54d1SPeter Maydell if (err) { 4069e5e54d1SPeter Maydell error_propagate(errp, err); 4079e5e54d1SPeter Maydell return; 4089e5e54d1SPeter Maydell } 4099e5e54d1SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0, 410984b0c10SPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 4)); 4119e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0); 4129e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err); 4139e5e54d1SPeter Maydell if (err) { 4149e5e54d1SPeter Maydell error_propagate(errp, err); 4159e5e54d1SPeter Maydell return; 4169e5e54d1SPeter Maydell } 4179e5e54d1SPeter Maydell 418017d069dSPeter Maydell 419017d069dSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq); 4209e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err); 4219e5e54d1SPeter Maydell if (err) { 4229e5e54d1SPeter Maydell error_propagate(errp, err); 4239e5e54d1SPeter Maydell return; 4249e5e54d1SPeter Maydell } 425017d069dSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0, 426017d069dSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 5)); 4279e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0); 4289e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err); 4299e5e54d1SPeter Maydell if (err) { 4309e5e54d1SPeter Maydell error_propagate(errp, err); 4319e5e54d1SPeter Maydell return; 4329e5e54d1SPeter Maydell } 4339e5e54d1SPeter Maydell 4349e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err); 4359e5e54d1SPeter Maydell if (err) { 4369e5e54d1SPeter Maydell error_propagate(errp, err); 4379e5e54d1SPeter Maydell return; 4389e5e54d1SPeter Maydell } 4399e5e54d1SPeter Maydell 4409e5e54d1SPeter Maydell sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0); 4419e5e54d1SPeter Maydell dev_apb_ppc0 = DEVICE(&s->apb_ppc0); 4429e5e54d1SPeter Maydell 4439e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0); 4449e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x40000000, mr); 4459e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1); 4469e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x40001000, mr); 4479e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2); 4489e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x40002000, mr); 4499e5e54d1SPeter Maydell for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) { 4509e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i, 4519e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4529e5e54d1SPeter Maydell "cfg_nonsec", i)); 4539e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i, 4549e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4559e5e54d1SPeter Maydell "cfg_ap", i)); 4569e5e54d1SPeter Maydell } 4579e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0, 4589e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4599e5e54d1SPeter Maydell "irq_enable", 0)); 4609e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0, 4619e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4629e5e54d1SPeter Maydell "irq_clear", 0)); 4639e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 4649e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4659e5e54d1SPeter Maydell "cfg_sec_resp", 0)); 4669e5e54d1SPeter Maydell 4679e5e54d1SPeter Maydell /* All the PPC irq lines (from the 2 internal PPCs and the 8 external 4689e5e54d1SPeter Maydell * ones) are sent individually to the security controller, and also 4699e5e54d1SPeter Maydell * ORed together to give a single combined PPC interrupt to the NVIC. 4709e5e54d1SPeter Maydell */ 4719e5e54d1SPeter Maydell object_property_set_int(OBJECT(&s->ppc_irq_orgate), 4729e5e54d1SPeter Maydell NUM_PPCS, "num-lines", &err); 4739e5e54d1SPeter Maydell if (err) { 4749e5e54d1SPeter Maydell error_propagate(errp, err); 4759e5e54d1SPeter Maydell return; 4769e5e54d1SPeter Maydell } 4779e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true, 4789e5e54d1SPeter Maydell "realized", &err); 4799e5e54d1SPeter Maydell if (err) { 4809e5e54d1SPeter Maydell error_propagate(errp, err); 4819e5e54d1SPeter Maydell return; 4829e5e54d1SPeter Maydell } 4839e5e54d1SPeter Maydell qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0, 4849e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 10)); 4859e5e54d1SPeter Maydell 4869e5e54d1SPeter Maydell /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */ 4879e5e54d1SPeter Maydell 48893dbd103SPeter Maydell /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */ 4899e5e54d1SPeter Maydell /* Devices behind APB PPC1: 4909e5e54d1SPeter Maydell * 0x4002f000: S32K timer 4919e5e54d1SPeter Maydell */ 492e2d203baSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK); 4939e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err); 4949e5e54d1SPeter Maydell if (err) { 4959e5e54d1SPeter Maydell error_propagate(errp, err); 4969e5e54d1SPeter Maydell return; 4979e5e54d1SPeter Maydell } 498e2d203baSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0, 499e2d203baSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 2)); 5009e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0); 5019e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err); 5029e5e54d1SPeter Maydell if (err) { 5039e5e54d1SPeter Maydell error_propagate(errp, err); 5049e5e54d1SPeter Maydell return; 5059e5e54d1SPeter Maydell } 5069e5e54d1SPeter Maydell 5079e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err); 5089e5e54d1SPeter Maydell if (err) { 5099e5e54d1SPeter Maydell error_propagate(errp, err); 5109e5e54d1SPeter Maydell return; 5119e5e54d1SPeter Maydell } 5129e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0); 5139e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x4002f000, mr); 5149e5e54d1SPeter Maydell 5159e5e54d1SPeter Maydell dev_apb_ppc1 = DEVICE(&s->apb_ppc1); 5169e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0, 5179e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5189e5e54d1SPeter Maydell "cfg_nonsec", 0)); 5199e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0, 5209e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5219e5e54d1SPeter Maydell "cfg_ap", 0)); 5229e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0, 5239e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5249e5e54d1SPeter Maydell "irq_enable", 0)); 5259e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0, 5269e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5279e5e54d1SPeter Maydell "irq_clear", 0)); 5289e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 1, 5299e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5309e5e54d1SPeter Maydell "cfg_sec_resp", 0)); 5319e5e54d1SPeter Maydell 53206e65af3SPeter Maydell object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err); 53306e65af3SPeter Maydell if (err) { 53406e65af3SPeter Maydell error_propagate(errp, err); 53506e65af3SPeter Maydell return; 53606e65af3SPeter Maydell } 53706e65af3SPeter Maydell /* System information registers */ 53806e65af3SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000); 53906e65af3SPeter Maydell /* System control registers */ 54006e65af3SPeter Maydell object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err); 54106e65af3SPeter Maydell if (err) { 54206e65af3SPeter Maydell error_propagate(errp, err); 54306e65af3SPeter Maydell return; 54406e65af3SPeter Maydell } 54506e65af3SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000); 546d61e4e1fSPeter Maydell 547d61e4e1fSPeter Maydell /* This OR gate wires together outputs from the secure watchdogs to NMI */ 548d61e4e1fSPeter Maydell object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err); 549d61e4e1fSPeter Maydell if (err) { 550d61e4e1fSPeter Maydell error_propagate(errp, err); 551d61e4e1fSPeter Maydell return; 552d61e4e1fSPeter Maydell } 553d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err); 554d61e4e1fSPeter Maydell if (err) { 555d61e4e1fSPeter Maydell error_propagate(errp, err); 556d61e4e1fSPeter Maydell return; 557d61e4e1fSPeter Maydell } 558d61e4e1fSPeter Maydell qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0, 559d61e4e1fSPeter Maydell qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0)); 560d61e4e1fSPeter Maydell 561d61e4e1fSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK); 562d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err); 563d61e4e1fSPeter Maydell if (err) { 564d61e4e1fSPeter Maydell error_propagate(errp, err); 565d61e4e1fSPeter Maydell return; 566d61e4e1fSPeter Maydell } 567d61e4e1fSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 568d61e4e1fSPeter Maydell qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0)); 569d61e4e1fSPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000); 5709e5e54d1SPeter Maydell 57193dbd103SPeter Maydell /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */ 5729e5e54d1SPeter Maydell 573d61e4e1fSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq); 574d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err); 575d61e4e1fSPeter Maydell if (err) { 576d61e4e1fSPeter Maydell error_propagate(errp, err); 577d61e4e1fSPeter Maydell return; 578d61e4e1fSPeter Maydell } 579d61e4e1fSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0, 580d61e4e1fSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 1)); 581d61e4e1fSPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000); 582d61e4e1fSPeter Maydell 583d61e4e1fSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq); 584d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err); 585d61e4e1fSPeter Maydell if (err) { 586d61e4e1fSPeter Maydell error_propagate(errp, err); 587d61e4e1fSPeter Maydell return; 588d61e4e1fSPeter Maydell } 589d61e4e1fSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0, 590d61e4e1fSPeter Maydell qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1)); 591d61e4e1fSPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000); 5929e5e54d1SPeter Maydell 5939e5e54d1SPeter Maydell for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { 5949e5e54d1SPeter Maydell Object *splitter = OBJECT(&s->ppc_irq_splitter[i]); 5959e5e54d1SPeter Maydell 5969e5e54d1SPeter Maydell object_property_set_int(splitter, 2, "num-lines", &err); 5979e5e54d1SPeter Maydell if (err) { 5989e5e54d1SPeter Maydell error_propagate(errp, err); 5999e5e54d1SPeter Maydell return; 6009e5e54d1SPeter Maydell } 6019e5e54d1SPeter Maydell object_property_set_bool(splitter, true, "realized", &err); 6029e5e54d1SPeter Maydell if (err) { 6039e5e54d1SPeter Maydell error_propagate(errp, err); 6049e5e54d1SPeter Maydell return; 6059e5e54d1SPeter Maydell } 6069e5e54d1SPeter Maydell } 6079e5e54d1SPeter Maydell 6089e5e54d1SPeter Maydell for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) { 6099e5e54d1SPeter Maydell char *ppcname = g_strdup_printf("ahb_ppcexp%d", i); 6109e5e54d1SPeter Maydell 61113628891SPeter Maydell armsse_forward_ppc(s, ppcname, i); 6129e5e54d1SPeter Maydell g_free(ppcname); 6139e5e54d1SPeter Maydell } 6149e5e54d1SPeter Maydell 6159e5e54d1SPeter Maydell for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) { 6169e5e54d1SPeter Maydell char *ppcname = g_strdup_printf("apb_ppcexp%d", i); 6179e5e54d1SPeter Maydell 61813628891SPeter Maydell armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC); 6199e5e54d1SPeter Maydell g_free(ppcname); 6209e5e54d1SPeter Maydell } 6219e5e54d1SPeter Maydell 6229e5e54d1SPeter Maydell for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) { 6239e5e54d1SPeter Maydell /* Wire up IRQ splitter for internal PPCs */ 6249e5e54d1SPeter Maydell DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]); 6259e5e54d1SPeter Maydell char *gpioname = g_strdup_printf("apb_ppc%d_irq_status", 6269e5e54d1SPeter Maydell i - NUM_EXTERNAL_PPCS); 6279e5e54d1SPeter Maydell TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1; 6289e5e54d1SPeter Maydell 6299e5e54d1SPeter Maydell qdev_connect_gpio_out(devs, 0, 6309e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_secctl, gpioname, 0)); 6319e5e54d1SPeter Maydell qdev_connect_gpio_out(devs, 1, 6329e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i)); 6339e5e54d1SPeter Maydell qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0, 6349e5e54d1SPeter Maydell qdev_get_gpio_in(devs, 0)); 6357a35383aSPeter Maydell g_free(gpioname); 6369e5e54d1SPeter Maydell } 6379e5e54d1SPeter Maydell 638bb75e16dSPeter Maydell /* Wire up the splitters for the MPC IRQs */ 639bb75e16dSPeter Maydell for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) { 640bb75e16dSPeter Maydell SplitIRQ *splitter = &s->mpc_irq_splitter[i]; 641bb75e16dSPeter Maydell DeviceState *dev_splitter = DEVICE(splitter); 642bb75e16dSPeter Maydell 643bb75e16dSPeter Maydell object_property_set_int(OBJECT(splitter), 2, "num-lines", &err); 644bb75e16dSPeter Maydell if (err) { 645bb75e16dSPeter Maydell error_propagate(errp, err); 646bb75e16dSPeter Maydell return; 647bb75e16dSPeter Maydell } 648bb75e16dSPeter Maydell object_property_set_bool(OBJECT(splitter), true, "realized", &err); 649bb75e16dSPeter Maydell if (err) { 650bb75e16dSPeter Maydell error_propagate(errp, err); 651bb75e16dSPeter Maydell return; 652bb75e16dSPeter Maydell } 653bb75e16dSPeter Maydell 654bb75e16dSPeter Maydell if (i < IOTS_NUM_EXP_MPC) { 655bb75e16dSPeter Maydell /* Splitter input is from GPIO input line */ 656bb75e16dSPeter Maydell s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0); 657bb75e16dSPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 658bb75e16dSPeter Maydell qdev_get_gpio_in_named(dev_secctl, 659bb75e16dSPeter Maydell "mpcexp_status", i)); 660bb75e16dSPeter Maydell } else { 661bb75e16dSPeter Maydell /* Splitter input is from our own MPC */ 662bb75e16dSPeter Maydell qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0, 663bb75e16dSPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 664bb75e16dSPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 665bb75e16dSPeter Maydell qdev_get_gpio_in_named(dev_secctl, 666bb75e16dSPeter Maydell "mpc_status", 0)); 667bb75e16dSPeter Maydell } 668bb75e16dSPeter Maydell 669bb75e16dSPeter Maydell qdev_connect_gpio_out(dev_splitter, 1, 670bb75e16dSPeter Maydell qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i)); 671bb75e16dSPeter Maydell } 672bb75e16dSPeter Maydell /* Create GPIO inputs which will pass the line state for our 673bb75e16dSPeter Maydell * mpcexp_irq inputs to the correct splitter devices. 674bb75e16dSPeter Maydell */ 67513628891SPeter Maydell qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status", 676bb75e16dSPeter Maydell IOTS_NUM_EXP_MPC); 677bb75e16dSPeter Maydell 67813628891SPeter Maydell armsse_forward_sec_resp_cfg(s); 6799e5e54d1SPeter Maydell 680132b475aSPeter Maydell /* Forward the MSC related signals */ 681132b475aSPeter Maydell qdev_pass_gpios(dev_secctl, dev, "mscexp_status"); 682132b475aSPeter Maydell qdev_pass_gpios(dev_secctl, dev, "mscexp_clear"); 683132b475aSPeter Maydell qdev_pass_gpios(dev_secctl, dev, "mscexp_ns"); 684132b475aSPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0, 685132b475aSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 11)); 686132b475aSPeter Maydell 687132b475aSPeter Maydell /* 688132b475aSPeter Maydell * Expose our container region to the board model; this corresponds 689132b475aSPeter Maydell * to the AHB Slave Expansion ports which allow bus master devices 690132b475aSPeter Maydell * (eg DMA controllers) in the board model to make transactions into 69193dbd103SPeter Maydell * devices in the ARMSSE. 692132b475aSPeter Maydell */ 693132b475aSPeter Maydell sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container); 694132b475aSPeter Maydell 6959e5e54d1SPeter Maydell system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq; 6969e5e54d1SPeter Maydell } 6979e5e54d1SPeter Maydell 69813628891SPeter Maydell static void armsse_idau_check(IDAUInterface *ii, uint32_t address, 6999e5e54d1SPeter Maydell int *iregion, bool *exempt, bool *ns, bool *nsc) 7009e5e54d1SPeter Maydell { 70193dbd103SPeter Maydell /* 70293dbd103SPeter Maydell * For ARMSSE systems the IDAU responses are simple logical functions 7039e5e54d1SPeter Maydell * of the address bits. The NSC attribute is guest-adjustable via the 7049e5e54d1SPeter Maydell * NSCCFG register in the security controller. 7059e5e54d1SPeter Maydell */ 70693dbd103SPeter Maydell ARMSSE *s = ARMSSE(ii); 7079e5e54d1SPeter Maydell int region = extract32(address, 28, 4); 7089e5e54d1SPeter Maydell 7099e5e54d1SPeter Maydell *ns = !(region & 1); 7109e5e54d1SPeter Maydell *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2)); 7119e5e54d1SPeter Maydell /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */ 7129e5e54d1SPeter Maydell *exempt = (address & 0xeff00000) == 0xe0000000; 7139e5e54d1SPeter Maydell *iregion = region; 7149e5e54d1SPeter Maydell } 7159e5e54d1SPeter Maydell 71613628891SPeter Maydell static const VMStateDescription armsse_vmstate = { 7179e5e54d1SPeter Maydell .name = "iotkit", 7189e5e54d1SPeter Maydell .version_id = 1, 7199e5e54d1SPeter Maydell .minimum_version_id = 1, 7209e5e54d1SPeter Maydell .fields = (VMStateField[]) { 72193dbd103SPeter Maydell VMSTATE_UINT32(nsccfg, ARMSSE), 7229e5e54d1SPeter Maydell VMSTATE_END_OF_LIST() 7239e5e54d1SPeter Maydell } 7249e5e54d1SPeter Maydell }; 7259e5e54d1SPeter Maydell 72613628891SPeter Maydell static Property armsse_properties[] = { 72793dbd103SPeter Maydell DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION, 7289e5e54d1SPeter Maydell MemoryRegion *), 72993dbd103SPeter Maydell DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64), 73093dbd103SPeter Maydell DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0), 7319e5e54d1SPeter Maydell DEFINE_PROP_END_OF_LIST() 7329e5e54d1SPeter Maydell }; 7339e5e54d1SPeter Maydell 73413628891SPeter Maydell static void armsse_reset(DeviceState *dev) 7359e5e54d1SPeter Maydell { 73693dbd103SPeter Maydell ARMSSE *s = ARMSSE(dev); 7379e5e54d1SPeter Maydell 7389e5e54d1SPeter Maydell s->nsccfg = 0; 7399e5e54d1SPeter Maydell } 7409e5e54d1SPeter Maydell 74113628891SPeter Maydell static void armsse_class_init(ObjectClass *klass, void *data) 7429e5e54d1SPeter Maydell { 7439e5e54d1SPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 7449e5e54d1SPeter Maydell IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass); 7454c3690b5SPeter Maydell ARMSSEClass *asc = ARMSSE_CLASS(klass); 7469e5e54d1SPeter Maydell 74713628891SPeter Maydell dc->realize = armsse_realize; 74813628891SPeter Maydell dc->vmsd = &armsse_vmstate; 74913628891SPeter Maydell dc->props = armsse_properties; 75013628891SPeter Maydell dc->reset = armsse_reset; 75113628891SPeter Maydell iic->check = armsse_idau_check; 7524c3690b5SPeter Maydell asc->info = data; 7539e5e54d1SPeter Maydell } 7549e5e54d1SPeter Maydell 7554c3690b5SPeter Maydell static const TypeInfo armsse_info = { 75693dbd103SPeter Maydell .name = TYPE_ARMSSE, 7579e5e54d1SPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 75893dbd103SPeter Maydell .instance_size = sizeof(ARMSSE), 75913628891SPeter Maydell .instance_init = armsse_init, 7604c3690b5SPeter Maydell .abstract = true, 7619e5e54d1SPeter Maydell .interfaces = (InterfaceInfo[]) { 7629e5e54d1SPeter Maydell { TYPE_IDAU_INTERFACE }, 7639e5e54d1SPeter Maydell { } 7649e5e54d1SPeter Maydell } 7659e5e54d1SPeter Maydell }; 7669e5e54d1SPeter Maydell 7674c3690b5SPeter Maydell static void armsse_register_types(void) 7689e5e54d1SPeter Maydell { 7694c3690b5SPeter Maydell int i; 7704c3690b5SPeter Maydell 7714c3690b5SPeter Maydell type_register_static(&armsse_info); 7724c3690b5SPeter Maydell 7734c3690b5SPeter Maydell for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) { 7744c3690b5SPeter Maydell TypeInfo ti = { 7754c3690b5SPeter Maydell .name = armsse_variants[i].name, 7764c3690b5SPeter Maydell .parent = TYPE_ARMSSE, 77713628891SPeter Maydell .class_init = armsse_class_init, 7784c3690b5SPeter Maydell .class_data = (void *)&armsse_variants[i], 7794c3690b5SPeter Maydell }; 7804c3690b5SPeter Maydell type_register(&ti); 7814c3690b5SPeter Maydell } 7829e5e54d1SPeter Maydell } 7839e5e54d1SPeter Maydell 7844c3690b5SPeter Maydell type_init(armsse_register_types); 785