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" 186eee5d24SPeter Maydell #include "hw/arm/armsse.h" 199e5e54d1SPeter Maydell #include "hw/arm/arm.h" 209e5e54d1SPeter Maydell 214c3690b5SPeter Maydell struct ARMSSEInfo { 224c3690b5SPeter Maydell const char *name; 23*f0cab7feSPeter Maydell int sram_banks; 244c3690b5SPeter Maydell }; 254c3690b5SPeter Maydell 264c3690b5SPeter Maydell static const ARMSSEInfo armsse_variants[] = { 274c3690b5SPeter Maydell { 284c3690b5SPeter Maydell .name = TYPE_IOTKIT, 29*f0cab7feSPeter Maydell .sram_banks = 1, 304c3690b5SPeter Maydell }, 314c3690b5SPeter Maydell }; 324c3690b5SPeter Maydell 33d61e4e1fSPeter Maydell /* Clock frequency in HZ of the 32KHz "slow clock" */ 34d61e4e1fSPeter Maydell #define S32KCLK (32 * 1000) 35d61e4e1fSPeter Maydell 369e5e54d1SPeter Maydell /* Create an alias region of @size bytes starting at @base 379e5e54d1SPeter Maydell * which mirrors the memory starting at @orig. 389e5e54d1SPeter Maydell */ 3993dbd103SPeter Maydell static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name, 409e5e54d1SPeter Maydell hwaddr base, hwaddr size, hwaddr orig) 419e5e54d1SPeter Maydell { 429e5e54d1SPeter Maydell memory_region_init_alias(mr, NULL, name, &s->container, orig, size); 439e5e54d1SPeter Maydell /* The alias is even lower priority than unimplemented_device regions */ 449e5e54d1SPeter Maydell memory_region_add_subregion_overlap(&s->container, base, mr, -1500); 459e5e54d1SPeter Maydell } 469e5e54d1SPeter Maydell 479e5e54d1SPeter Maydell static void irq_status_forwarder(void *opaque, int n, int level) 489e5e54d1SPeter Maydell { 499e5e54d1SPeter Maydell qemu_irq destirq = opaque; 509e5e54d1SPeter Maydell 519e5e54d1SPeter Maydell qemu_set_irq(destirq, level); 529e5e54d1SPeter Maydell } 539e5e54d1SPeter Maydell 549e5e54d1SPeter Maydell static void nsccfg_handler(void *opaque, int n, int level) 559e5e54d1SPeter Maydell { 5693dbd103SPeter Maydell ARMSSE *s = ARMSSE(opaque); 579e5e54d1SPeter Maydell 589e5e54d1SPeter Maydell s->nsccfg = level; 599e5e54d1SPeter Maydell } 609e5e54d1SPeter Maydell 6113628891SPeter Maydell static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum) 629e5e54d1SPeter Maydell { 639e5e54d1SPeter Maydell /* Each of the 4 AHB and 4 APB PPCs that might be present in a 6493dbd103SPeter Maydell * system using the ARMSSE has a collection of control lines which 659e5e54d1SPeter Maydell * are provided by the security controller and which we want to 6693dbd103SPeter Maydell * expose as control lines on the ARMSSE device itself, so the 6793dbd103SPeter Maydell * code using the ARMSSE can wire them up to the PPCs. 689e5e54d1SPeter Maydell */ 699e5e54d1SPeter Maydell SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum]; 7013628891SPeter Maydell DeviceState *armssedev = DEVICE(s); 719e5e54d1SPeter Maydell DeviceState *dev_secctl = DEVICE(&s->secctl); 729e5e54d1SPeter Maydell DeviceState *dev_splitter = DEVICE(splitter); 739e5e54d1SPeter Maydell char *name; 749e5e54d1SPeter Maydell 759e5e54d1SPeter Maydell name = g_strdup_printf("%s_nonsec", ppcname); 7613628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 779e5e54d1SPeter Maydell g_free(name); 789e5e54d1SPeter Maydell name = g_strdup_printf("%s_ap", ppcname); 7913628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 809e5e54d1SPeter Maydell g_free(name); 819e5e54d1SPeter Maydell name = g_strdup_printf("%s_irq_enable", ppcname); 8213628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 839e5e54d1SPeter Maydell g_free(name); 849e5e54d1SPeter Maydell name = g_strdup_printf("%s_irq_clear", ppcname); 8513628891SPeter Maydell qdev_pass_gpios(dev_secctl, armssedev, name); 869e5e54d1SPeter Maydell g_free(name); 879e5e54d1SPeter Maydell 889e5e54d1SPeter Maydell /* irq_status is a little more tricky, because we need to 899e5e54d1SPeter Maydell * split it so we can send it both to the security controller 909e5e54d1SPeter Maydell * and to our OR gate for the NVIC interrupt line. 919e5e54d1SPeter Maydell * Connect up the splitter's outputs, and create a GPIO input 929e5e54d1SPeter Maydell * which will pass the line state to the input splitter. 939e5e54d1SPeter Maydell */ 949e5e54d1SPeter Maydell name = g_strdup_printf("%s_irq_status", ppcname); 959e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 969e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_secctl, 979e5e54d1SPeter Maydell name, 0)); 989e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 1, 999e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum)); 1009e5e54d1SPeter Maydell s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0); 10113628891SPeter Maydell qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder, 1029e5e54d1SPeter Maydell s->irq_status_in[ppcnum], name, 1); 1039e5e54d1SPeter Maydell g_free(name); 1049e5e54d1SPeter Maydell } 1059e5e54d1SPeter Maydell 10613628891SPeter Maydell static void armsse_forward_sec_resp_cfg(ARMSSE *s) 1079e5e54d1SPeter Maydell { 1089e5e54d1SPeter Maydell /* Forward the 3rd output from the splitter device as a 10913628891SPeter Maydell * named GPIO output of the armsse object. 1109e5e54d1SPeter Maydell */ 1119e5e54d1SPeter Maydell DeviceState *dev = DEVICE(s); 1129e5e54d1SPeter Maydell DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter); 1139e5e54d1SPeter Maydell 1149e5e54d1SPeter Maydell qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1); 1159e5e54d1SPeter Maydell s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder, 1169e5e54d1SPeter Maydell s->sec_resp_cfg, 1); 1179e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in); 1189e5e54d1SPeter Maydell } 1199e5e54d1SPeter Maydell 12013628891SPeter Maydell static void armsse_init(Object *obj) 1219e5e54d1SPeter Maydell { 12293dbd103SPeter Maydell ARMSSE *s = ARMSSE(obj); 123*f0cab7feSPeter Maydell ARMSSEClass *asc = ARMSSE_GET_CLASS(obj); 124*f0cab7feSPeter Maydell const ARMSSEInfo *info = asc->info; 1259e5e54d1SPeter Maydell int i; 1269e5e54d1SPeter Maydell 127*f0cab7feSPeter Maydell assert(info->sram_banks <= MAX_SRAM_BANKS); 128*f0cab7feSPeter Maydell 12913628891SPeter Maydell memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX); 1309e5e54d1SPeter Maydell 131955cbc6bSThomas Huth sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), 1329e5e54d1SPeter Maydell TYPE_ARMV7M); 1339e5e54d1SPeter Maydell qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type", 1349e5e54d1SPeter Maydell ARM_CPU_TYPE_NAME("cortex-m33")); 1359e5e54d1SPeter Maydell 136955cbc6bSThomas Huth sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl), 1379e5e54d1SPeter Maydell TYPE_IOTKIT_SECCTL); 138955cbc6bSThomas Huth sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0), 1399e5e54d1SPeter Maydell TYPE_TZ_PPC); 140955cbc6bSThomas Huth sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1), 1419e5e54d1SPeter Maydell TYPE_TZ_PPC); 142*f0cab7feSPeter Maydell for (i = 0; i < info->sram_banks; i++) { 143*f0cab7feSPeter Maydell char *name = g_strdup_printf("mpc%d", i); 144*f0cab7feSPeter Maydell sysbus_init_child_obj(obj, name, &s->mpc[i], 145*f0cab7feSPeter Maydell sizeof(s->mpc[i]), TYPE_TZ_MPC); 146*f0cab7feSPeter Maydell g_free(name); 147*f0cab7feSPeter Maydell } 148955cbc6bSThomas Huth object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate, 149955cbc6bSThomas Huth sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ, 150955cbc6bSThomas Huth &error_abort, NULL); 151955cbc6bSThomas Huth 152*f0cab7feSPeter Maydell for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) { 153bb75e16dSPeter Maydell char *name = g_strdup_printf("mpc-irq-splitter-%d", i); 154bb75e16dSPeter Maydell SplitIRQ *splitter = &s->mpc_irq_splitter[i]; 155bb75e16dSPeter Maydell 156955cbc6bSThomas Huth object_initialize_child(obj, name, splitter, sizeof(*splitter), 157955cbc6bSThomas Huth TYPE_SPLIT_IRQ, &error_abort, NULL); 158bb75e16dSPeter Maydell g_free(name); 159bb75e16dSPeter Maydell } 160955cbc6bSThomas Huth sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0), 1619e5e54d1SPeter Maydell TYPE_CMSDK_APB_TIMER); 162955cbc6bSThomas Huth sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1), 1639e5e54d1SPeter Maydell TYPE_CMSDK_APB_TIMER); 164e2d203baSPeter Maydell sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer), 165e2d203baSPeter Maydell TYPE_CMSDK_APB_TIMER); 166955cbc6bSThomas Huth sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer), 167017d069dSPeter Maydell TYPE_CMSDK_APB_DUALTIMER); 168d61e4e1fSPeter Maydell sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog, 169d61e4e1fSPeter Maydell sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG); 170d61e4e1fSPeter Maydell sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog, 171d61e4e1fSPeter Maydell sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG); 172d61e4e1fSPeter Maydell sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog, 173d61e4e1fSPeter Maydell sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG); 17413628891SPeter Maydell sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl, 17506e65af3SPeter Maydell sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL); 17613628891SPeter Maydell sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo, 17706e65af3SPeter Maydell sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO); 178d61e4e1fSPeter Maydell object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, 179d61e4e1fSPeter Maydell sizeof(s->nmi_orgate), TYPE_OR_IRQ, 180d61e4e1fSPeter Maydell &error_abort, NULL); 181955cbc6bSThomas Huth object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate, 182955cbc6bSThomas Huth sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ, 183955cbc6bSThomas Huth &error_abort, NULL); 184955cbc6bSThomas Huth object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter, 185955cbc6bSThomas Huth sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ, 186955cbc6bSThomas Huth &error_abort, NULL); 1879e5e54d1SPeter Maydell for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { 1889e5e54d1SPeter Maydell char *name = g_strdup_printf("ppc-irq-splitter-%d", i); 1899e5e54d1SPeter Maydell SplitIRQ *splitter = &s->ppc_irq_splitter[i]; 1909e5e54d1SPeter Maydell 191955cbc6bSThomas Huth object_initialize_child(obj, name, splitter, sizeof(*splitter), 192955cbc6bSThomas Huth TYPE_SPLIT_IRQ, &error_abort, NULL); 193955cbc6bSThomas Huth g_free(name); 1949e5e54d1SPeter Maydell } 1959e5e54d1SPeter Maydell } 1969e5e54d1SPeter Maydell 19713628891SPeter Maydell static void armsse_exp_irq(void *opaque, int n, int level) 1989e5e54d1SPeter Maydell { 19993dbd103SPeter Maydell ARMSSE *s = ARMSSE(opaque); 2009e5e54d1SPeter Maydell 2019e5e54d1SPeter Maydell qemu_set_irq(s->exp_irqs[n], level); 2029e5e54d1SPeter Maydell } 2039e5e54d1SPeter Maydell 20413628891SPeter Maydell static void armsse_mpcexp_status(void *opaque, int n, int level) 205bb75e16dSPeter Maydell { 20693dbd103SPeter Maydell ARMSSE *s = ARMSSE(opaque); 207bb75e16dSPeter Maydell qemu_set_irq(s->mpcexp_status_in[n], level); 208bb75e16dSPeter Maydell } 209bb75e16dSPeter Maydell 21013628891SPeter Maydell static void armsse_realize(DeviceState *dev, Error **errp) 2119e5e54d1SPeter Maydell { 21293dbd103SPeter Maydell ARMSSE *s = ARMSSE(dev); 213*f0cab7feSPeter Maydell ARMSSEClass *asc = ARMSSE_GET_CLASS(dev); 214*f0cab7feSPeter Maydell const ARMSSEInfo *info = asc->info; 2159e5e54d1SPeter Maydell int i; 2169e5e54d1SPeter Maydell MemoryRegion *mr; 2179e5e54d1SPeter Maydell Error *err = NULL; 2189e5e54d1SPeter Maydell SysBusDevice *sbd_apb_ppc0; 2199e5e54d1SPeter Maydell SysBusDevice *sbd_secctl; 2209e5e54d1SPeter Maydell DeviceState *dev_apb_ppc0; 2219e5e54d1SPeter Maydell DeviceState *dev_apb_ppc1; 2229e5e54d1SPeter Maydell DeviceState *dev_secctl; 2239e5e54d1SPeter Maydell DeviceState *dev_splitter; 2249e5e54d1SPeter Maydell 2259e5e54d1SPeter Maydell if (!s->board_memory) { 2269e5e54d1SPeter Maydell error_setg(errp, "memory property was not set"); 2279e5e54d1SPeter Maydell return; 2289e5e54d1SPeter Maydell } 2299e5e54d1SPeter Maydell 2309e5e54d1SPeter Maydell if (!s->mainclk_frq) { 2319e5e54d1SPeter Maydell error_setg(errp, "MAINCLK property was not set"); 2329e5e54d1SPeter Maydell return; 2339e5e54d1SPeter Maydell } 2349e5e54d1SPeter Maydell 2359e5e54d1SPeter Maydell /* Handling of which devices should be available only to secure 2369e5e54d1SPeter Maydell * code is usually done differently for M profile than for A profile. 2379e5e54d1SPeter Maydell * Instead of putting some devices only into the secure address space, 2389e5e54d1SPeter Maydell * devices exist in both address spaces but with hard-wired security 2399e5e54d1SPeter Maydell * permissions that will cause the CPU to fault for non-secure accesses. 2409e5e54d1SPeter Maydell * 24193dbd103SPeter Maydell * The ARMSSE has an IDAU (Implementation Defined Access Unit), 2429e5e54d1SPeter Maydell * which specifies hard-wired security permissions for different 24393dbd103SPeter Maydell * areas of the physical address space. For the ARMSSE IDAU, the 2449e5e54d1SPeter Maydell * top 4 bits of the physical address are the IDAU region ID, and 2459e5e54d1SPeter Maydell * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS 2469e5e54d1SPeter Maydell * region, otherwise it is an S region. 2479e5e54d1SPeter Maydell * 2489e5e54d1SPeter Maydell * The various devices and RAMs are generally all mapped twice, 2499e5e54d1SPeter Maydell * once into a region that the IDAU defines as secure and once 2509e5e54d1SPeter Maydell * into a non-secure region. They sit behind either a Memory 2519e5e54d1SPeter Maydell * Protection Controller (for RAM) or a Peripheral Protection 2529e5e54d1SPeter Maydell * Controller (for devices), which allow a more fine grained 2539e5e54d1SPeter Maydell * configuration of whether non-secure accesses are permitted. 2549e5e54d1SPeter Maydell * 2559e5e54d1SPeter Maydell * (The other place that guest software can configure security 2569e5e54d1SPeter Maydell * permissions is in the architected SAU (Security Attribution 2579e5e54d1SPeter Maydell * Unit), which is entirely inside the CPU. The IDAU can upgrade 2589e5e54d1SPeter Maydell * the security attributes for a region to more restrictive than 2599e5e54d1SPeter Maydell * the SAU specifies, but cannot downgrade them.) 2609e5e54d1SPeter Maydell * 2619e5e54d1SPeter Maydell * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff 2629e5e54d1SPeter Maydell * 0x20000000..0x2007ffff 32KB FPGA block RAM 2639e5e54d1SPeter Maydell * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff 2649e5e54d1SPeter Maydell * 0x40000000..0x4000ffff base peripheral region 1 26593dbd103SPeter Maydell * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE) 2669e5e54d1SPeter Maydell * 0x40020000..0x4002ffff system control element peripherals 2679e5e54d1SPeter Maydell * 0x40080000..0x400fffff base peripheral region 2 2689e5e54d1SPeter Maydell * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff 2699e5e54d1SPeter Maydell */ 2709e5e54d1SPeter Maydell 2719e5e54d1SPeter Maydell memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1); 2729e5e54d1SPeter Maydell 2739e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32); 2749e5e54d1SPeter Maydell /* In real hardware the initial Secure VTOR is set from the INITSVTOR0 2759e5e54d1SPeter Maydell * register in the IoT Kit System Control Register block, and the 2769e5e54d1SPeter Maydell * initial value of that is in turn specifiable by the FPGA that 2779e5e54d1SPeter Maydell * instantiates the IoT Kit. In QEMU we don't implement this wrinkle, 2789e5e54d1SPeter Maydell * and simply set the CPU's init-svtor to the IoT Kit default value. 2799e5e54d1SPeter Maydell */ 2809e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000); 2819e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container), 2829e5e54d1SPeter Maydell "memory", &err); 2839e5e54d1SPeter Maydell if (err) { 2849e5e54d1SPeter Maydell error_propagate(errp, err); 2859e5e54d1SPeter Maydell return; 2869e5e54d1SPeter Maydell } 2879e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err); 2889e5e54d1SPeter Maydell if (err) { 2899e5e54d1SPeter Maydell error_propagate(errp, err); 2909e5e54d1SPeter Maydell return; 2919e5e54d1SPeter Maydell } 2929e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); 2939e5e54d1SPeter Maydell if (err) { 2949e5e54d1SPeter Maydell error_propagate(errp, err); 2959e5e54d1SPeter Maydell return; 2969e5e54d1SPeter Maydell } 2979e5e54d1SPeter Maydell 2989e5e54d1SPeter Maydell /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */ 2999e5e54d1SPeter Maydell s->exp_irqs = g_new(qemu_irq, s->exp_numirq); 3009e5e54d1SPeter Maydell for (i = 0; i < s->exp_numirq; i++) { 3019e5e54d1SPeter Maydell s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32); 3029e5e54d1SPeter Maydell } 30313628891SPeter Maydell qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq); 3049e5e54d1SPeter Maydell 3059e5e54d1SPeter Maydell /* Set up the big aliases first */ 3069e5e54d1SPeter Maydell make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000); 3079e5e54d1SPeter Maydell make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000); 3089e5e54d1SPeter Maydell /* The 0x50000000..0x5fffffff region is not a pure alias: it has 3099e5e54d1SPeter Maydell * a few extra devices that only appear there (generally the 3109e5e54d1SPeter Maydell * control interfaces for the protection controllers). 3119e5e54d1SPeter Maydell * We implement this by mapping those devices over the top of this 3129e5e54d1SPeter Maydell * alias MR at a higher priority. 3139e5e54d1SPeter Maydell */ 3149e5e54d1SPeter Maydell make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000); 3159e5e54d1SPeter Maydell 3169e5e54d1SPeter Maydell 3179e5e54d1SPeter Maydell /* Security controller */ 3189e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err); 3199e5e54d1SPeter Maydell if (err) { 3209e5e54d1SPeter Maydell error_propagate(errp, err); 3219e5e54d1SPeter Maydell return; 3229e5e54d1SPeter Maydell } 3239e5e54d1SPeter Maydell sbd_secctl = SYS_BUS_DEVICE(&s->secctl); 3249e5e54d1SPeter Maydell dev_secctl = DEVICE(&s->secctl); 3259e5e54d1SPeter Maydell sysbus_mmio_map(sbd_secctl, 0, 0x50080000); 3269e5e54d1SPeter Maydell sysbus_mmio_map(sbd_secctl, 1, 0x40080000); 3279e5e54d1SPeter Maydell 3289e5e54d1SPeter Maydell s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1); 3299e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in); 3309e5e54d1SPeter Maydell 3319e5e54d1SPeter Maydell /* The sec_resp_cfg output from the security controller must be split into 33293dbd103SPeter Maydell * multiple lines, one for each of the PPCs within the ARMSSE and one 33393dbd103SPeter Maydell * that will be an output from the ARMSSE to the system. 3349e5e54d1SPeter Maydell */ 3359e5e54d1SPeter Maydell object_property_set_int(OBJECT(&s->sec_resp_splitter), 3, 3369e5e54d1SPeter Maydell "num-lines", &err); 3379e5e54d1SPeter Maydell if (err) { 3389e5e54d1SPeter Maydell error_propagate(errp, err); 3399e5e54d1SPeter Maydell return; 3409e5e54d1SPeter Maydell } 3419e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->sec_resp_splitter), true, 3429e5e54d1SPeter Maydell "realized", &err); 3439e5e54d1SPeter Maydell if (err) { 3449e5e54d1SPeter Maydell error_propagate(errp, err); 3459e5e54d1SPeter Maydell return; 3469e5e54d1SPeter Maydell } 3479e5e54d1SPeter Maydell dev_splitter = DEVICE(&s->sec_resp_splitter); 3489e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0, 3499e5e54d1SPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 3509e5e54d1SPeter Maydell 351*f0cab7feSPeter Maydell /* Each SRAM bank lives behind its own Memory Protection Controller */ 352*f0cab7feSPeter Maydell for (i = 0; i < info->sram_banks; i++) { 353*f0cab7feSPeter Maydell char *ramname = g_strdup_printf("armsse.sram%d", i); 354*f0cab7feSPeter Maydell SysBusDevice *sbd_mpc; 355*f0cab7feSPeter Maydell 356*f0cab7feSPeter Maydell memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err); 357*f0cab7feSPeter Maydell g_free(ramname); 358af60b291SPeter Maydell if (err) { 359af60b291SPeter Maydell error_propagate(errp, err); 360af60b291SPeter Maydell return; 361af60b291SPeter Maydell } 362*f0cab7feSPeter Maydell object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]), 363af60b291SPeter Maydell "downstream", &err); 364af60b291SPeter Maydell if (err) { 365af60b291SPeter Maydell error_propagate(errp, err); 366af60b291SPeter Maydell return; 367af60b291SPeter Maydell } 368*f0cab7feSPeter Maydell object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err); 369af60b291SPeter Maydell if (err) { 370af60b291SPeter Maydell error_propagate(errp, err); 371af60b291SPeter Maydell return; 372af60b291SPeter Maydell } 373af60b291SPeter Maydell /* Map the upstream end of the MPC into the right place... */ 374*f0cab7feSPeter Maydell sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]); 375*f0cab7feSPeter Maydell memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000, 376*f0cab7feSPeter Maydell sysbus_mmio_get_region(sbd_mpc, 1)); 377af60b291SPeter Maydell /* ...and its register interface */ 378*f0cab7feSPeter Maydell memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000, 379*f0cab7feSPeter Maydell sysbus_mmio_get_region(sbd_mpc, 0)); 380*f0cab7feSPeter Maydell } 381af60b291SPeter Maydell 382bb75e16dSPeter Maydell /* We must OR together lines from the MPC splitters to go to the NVIC */ 383bb75e16dSPeter Maydell object_property_set_int(OBJECT(&s->mpc_irq_orgate), 384*f0cab7feSPeter Maydell IOTS_NUM_EXP_MPC + info->sram_banks, 385*f0cab7feSPeter Maydell "num-lines", &err); 386bb75e16dSPeter Maydell if (err) { 387bb75e16dSPeter Maydell error_propagate(errp, err); 388bb75e16dSPeter Maydell return; 389bb75e16dSPeter Maydell } 390bb75e16dSPeter Maydell object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true, 391bb75e16dSPeter Maydell "realized", &err); 392bb75e16dSPeter Maydell if (err) { 393bb75e16dSPeter Maydell error_propagate(errp, err); 394bb75e16dSPeter Maydell return; 395bb75e16dSPeter Maydell } 396bb75e16dSPeter Maydell qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0, 397bb75e16dSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 9)); 398bb75e16dSPeter Maydell 3999e5e54d1SPeter Maydell /* Devices behind APB PPC0: 4009e5e54d1SPeter Maydell * 0x40000000: timer0 4019e5e54d1SPeter Maydell * 0x40001000: timer1 4029e5e54d1SPeter Maydell * 0x40002000: dual timer 4039e5e54d1SPeter Maydell * We must configure and realize each downstream device and connect 4049e5e54d1SPeter Maydell * it to the appropriate PPC port; then we can realize the PPC and 4059e5e54d1SPeter Maydell * map its upstream ends to the right place in the container. 4069e5e54d1SPeter Maydell */ 4079e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq); 4089e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err); 4099e5e54d1SPeter Maydell if (err) { 4109e5e54d1SPeter Maydell error_propagate(errp, err); 4119e5e54d1SPeter Maydell return; 4129e5e54d1SPeter Maydell } 4139e5e54d1SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0, 4149e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 3)); 4159e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0); 4169e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err); 4179e5e54d1SPeter Maydell if (err) { 4189e5e54d1SPeter Maydell error_propagate(errp, err); 4199e5e54d1SPeter Maydell return; 4209e5e54d1SPeter Maydell } 4219e5e54d1SPeter Maydell 4229e5e54d1SPeter Maydell qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq); 4239e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err); 4249e5e54d1SPeter Maydell if (err) { 4259e5e54d1SPeter Maydell error_propagate(errp, err); 4269e5e54d1SPeter Maydell return; 4279e5e54d1SPeter Maydell } 4289e5e54d1SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0, 429984b0c10SPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 4)); 4309e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0); 4319e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err); 4329e5e54d1SPeter Maydell if (err) { 4339e5e54d1SPeter Maydell error_propagate(errp, err); 4349e5e54d1SPeter Maydell return; 4359e5e54d1SPeter Maydell } 4369e5e54d1SPeter Maydell 437017d069dSPeter Maydell 438017d069dSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq); 4399e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err); 4409e5e54d1SPeter Maydell if (err) { 4419e5e54d1SPeter Maydell error_propagate(errp, err); 4429e5e54d1SPeter Maydell return; 4439e5e54d1SPeter Maydell } 444017d069dSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0, 445017d069dSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 5)); 4469e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0); 4479e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err); 4489e5e54d1SPeter Maydell if (err) { 4499e5e54d1SPeter Maydell error_propagate(errp, err); 4509e5e54d1SPeter Maydell return; 4519e5e54d1SPeter Maydell } 4529e5e54d1SPeter Maydell 4539e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err); 4549e5e54d1SPeter Maydell if (err) { 4559e5e54d1SPeter Maydell error_propagate(errp, err); 4569e5e54d1SPeter Maydell return; 4579e5e54d1SPeter Maydell } 4589e5e54d1SPeter Maydell 4599e5e54d1SPeter Maydell sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0); 4609e5e54d1SPeter Maydell dev_apb_ppc0 = DEVICE(&s->apb_ppc0); 4619e5e54d1SPeter Maydell 4629e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0); 4639e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x40000000, mr); 4649e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1); 4659e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x40001000, mr); 4669e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2); 4679e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x40002000, mr); 4689e5e54d1SPeter Maydell for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) { 4699e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i, 4709e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4719e5e54d1SPeter Maydell "cfg_nonsec", i)); 4729e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i, 4739e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4749e5e54d1SPeter Maydell "cfg_ap", i)); 4759e5e54d1SPeter Maydell } 4769e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0, 4779e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4789e5e54d1SPeter Maydell "irq_enable", 0)); 4799e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0, 4809e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4819e5e54d1SPeter Maydell "irq_clear", 0)); 4829e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 4839e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc0, 4849e5e54d1SPeter Maydell "cfg_sec_resp", 0)); 4859e5e54d1SPeter Maydell 4869e5e54d1SPeter Maydell /* All the PPC irq lines (from the 2 internal PPCs and the 8 external 4879e5e54d1SPeter Maydell * ones) are sent individually to the security controller, and also 4889e5e54d1SPeter Maydell * ORed together to give a single combined PPC interrupt to the NVIC. 4899e5e54d1SPeter Maydell */ 4909e5e54d1SPeter Maydell object_property_set_int(OBJECT(&s->ppc_irq_orgate), 4919e5e54d1SPeter Maydell NUM_PPCS, "num-lines", &err); 4929e5e54d1SPeter Maydell if (err) { 4939e5e54d1SPeter Maydell error_propagate(errp, err); 4949e5e54d1SPeter Maydell return; 4959e5e54d1SPeter Maydell } 4969e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true, 4979e5e54d1SPeter Maydell "realized", &err); 4989e5e54d1SPeter Maydell if (err) { 4999e5e54d1SPeter Maydell error_propagate(errp, err); 5009e5e54d1SPeter Maydell return; 5019e5e54d1SPeter Maydell } 5029e5e54d1SPeter Maydell qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0, 5039e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 10)); 5049e5e54d1SPeter Maydell 5059e5e54d1SPeter Maydell /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */ 5069e5e54d1SPeter Maydell 50793dbd103SPeter Maydell /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */ 5089e5e54d1SPeter Maydell /* Devices behind APB PPC1: 5099e5e54d1SPeter Maydell * 0x4002f000: S32K timer 5109e5e54d1SPeter Maydell */ 511e2d203baSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK); 5129e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err); 5139e5e54d1SPeter Maydell if (err) { 5149e5e54d1SPeter Maydell error_propagate(errp, err); 5159e5e54d1SPeter Maydell return; 5169e5e54d1SPeter Maydell } 517e2d203baSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0, 518e2d203baSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 2)); 5199e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0); 5209e5e54d1SPeter Maydell object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err); 5219e5e54d1SPeter Maydell if (err) { 5229e5e54d1SPeter Maydell error_propagate(errp, err); 5239e5e54d1SPeter Maydell return; 5249e5e54d1SPeter Maydell } 5259e5e54d1SPeter Maydell 5269e5e54d1SPeter Maydell object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err); 5279e5e54d1SPeter Maydell if (err) { 5289e5e54d1SPeter Maydell error_propagate(errp, err); 5299e5e54d1SPeter Maydell return; 5309e5e54d1SPeter Maydell } 5319e5e54d1SPeter Maydell mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0); 5329e5e54d1SPeter Maydell memory_region_add_subregion(&s->container, 0x4002f000, mr); 5339e5e54d1SPeter Maydell 5349e5e54d1SPeter Maydell dev_apb_ppc1 = DEVICE(&s->apb_ppc1); 5359e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0, 5369e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5379e5e54d1SPeter Maydell "cfg_nonsec", 0)); 5389e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0, 5399e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5409e5e54d1SPeter Maydell "cfg_ap", 0)); 5419e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0, 5429e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5439e5e54d1SPeter Maydell "irq_enable", 0)); 5449e5e54d1SPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0, 5459e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5469e5e54d1SPeter Maydell "irq_clear", 0)); 5479e5e54d1SPeter Maydell qdev_connect_gpio_out(dev_splitter, 1, 5489e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_apb_ppc1, 5499e5e54d1SPeter Maydell "cfg_sec_resp", 0)); 5509e5e54d1SPeter Maydell 55106e65af3SPeter Maydell object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err); 55206e65af3SPeter Maydell if (err) { 55306e65af3SPeter Maydell error_propagate(errp, err); 55406e65af3SPeter Maydell return; 55506e65af3SPeter Maydell } 55606e65af3SPeter Maydell /* System information registers */ 55706e65af3SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000); 55806e65af3SPeter Maydell /* System control registers */ 55906e65af3SPeter Maydell object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err); 56006e65af3SPeter Maydell if (err) { 56106e65af3SPeter Maydell error_propagate(errp, err); 56206e65af3SPeter Maydell return; 56306e65af3SPeter Maydell } 56406e65af3SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000); 565d61e4e1fSPeter Maydell 566d61e4e1fSPeter Maydell /* This OR gate wires together outputs from the secure watchdogs to NMI */ 567d61e4e1fSPeter Maydell object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err); 568d61e4e1fSPeter Maydell if (err) { 569d61e4e1fSPeter Maydell error_propagate(errp, err); 570d61e4e1fSPeter Maydell return; 571d61e4e1fSPeter Maydell } 572d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err); 573d61e4e1fSPeter Maydell if (err) { 574d61e4e1fSPeter Maydell error_propagate(errp, err); 575d61e4e1fSPeter Maydell return; 576d61e4e1fSPeter Maydell } 577d61e4e1fSPeter Maydell qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0, 578d61e4e1fSPeter Maydell qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0)); 579d61e4e1fSPeter Maydell 580d61e4e1fSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK); 581d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err); 582d61e4e1fSPeter Maydell if (err) { 583d61e4e1fSPeter Maydell error_propagate(errp, err); 584d61e4e1fSPeter Maydell return; 585d61e4e1fSPeter Maydell } 586d61e4e1fSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 587d61e4e1fSPeter Maydell qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0)); 588d61e4e1fSPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000); 5899e5e54d1SPeter Maydell 59093dbd103SPeter Maydell /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */ 5919e5e54d1SPeter Maydell 592d61e4e1fSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq); 593d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err); 594d61e4e1fSPeter Maydell if (err) { 595d61e4e1fSPeter Maydell error_propagate(errp, err); 596d61e4e1fSPeter Maydell return; 597d61e4e1fSPeter Maydell } 598d61e4e1fSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0, 599d61e4e1fSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 1)); 600d61e4e1fSPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000); 601d61e4e1fSPeter Maydell 602d61e4e1fSPeter Maydell qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq); 603d61e4e1fSPeter Maydell object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err); 604d61e4e1fSPeter Maydell if (err) { 605d61e4e1fSPeter Maydell error_propagate(errp, err); 606d61e4e1fSPeter Maydell return; 607d61e4e1fSPeter Maydell } 608d61e4e1fSPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0, 609d61e4e1fSPeter Maydell qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1)); 610d61e4e1fSPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000); 6119e5e54d1SPeter Maydell 6129e5e54d1SPeter Maydell for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { 6139e5e54d1SPeter Maydell Object *splitter = OBJECT(&s->ppc_irq_splitter[i]); 6149e5e54d1SPeter Maydell 6159e5e54d1SPeter Maydell object_property_set_int(splitter, 2, "num-lines", &err); 6169e5e54d1SPeter Maydell if (err) { 6179e5e54d1SPeter Maydell error_propagate(errp, err); 6189e5e54d1SPeter Maydell return; 6199e5e54d1SPeter Maydell } 6209e5e54d1SPeter Maydell object_property_set_bool(splitter, true, "realized", &err); 6219e5e54d1SPeter Maydell if (err) { 6229e5e54d1SPeter Maydell error_propagate(errp, err); 6239e5e54d1SPeter Maydell return; 6249e5e54d1SPeter Maydell } 6259e5e54d1SPeter Maydell } 6269e5e54d1SPeter Maydell 6279e5e54d1SPeter Maydell for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) { 6289e5e54d1SPeter Maydell char *ppcname = g_strdup_printf("ahb_ppcexp%d", i); 6299e5e54d1SPeter Maydell 63013628891SPeter Maydell armsse_forward_ppc(s, ppcname, i); 6319e5e54d1SPeter Maydell g_free(ppcname); 6329e5e54d1SPeter Maydell } 6339e5e54d1SPeter Maydell 6349e5e54d1SPeter Maydell for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) { 6359e5e54d1SPeter Maydell char *ppcname = g_strdup_printf("apb_ppcexp%d", i); 6369e5e54d1SPeter Maydell 63713628891SPeter Maydell armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC); 6389e5e54d1SPeter Maydell g_free(ppcname); 6399e5e54d1SPeter Maydell } 6409e5e54d1SPeter Maydell 6419e5e54d1SPeter Maydell for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) { 6429e5e54d1SPeter Maydell /* Wire up IRQ splitter for internal PPCs */ 6439e5e54d1SPeter Maydell DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]); 6449e5e54d1SPeter Maydell char *gpioname = g_strdup_printf("apb_ppc%d_irq_status", 6459e5e54d1SPeter Maydell i - NUM_EXTERNAL_PPCS); 6469e5e54d1SPeter Maydell TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1; 6479e5e54d1SPeter Maydell 6489e5e54d1SPeter Maydell qdev_connect_gpio_out(devs, 0, 6499e5e54d1SPeter Maydell qdev_get_gpio_in_named(dev_secctl, gpioname, 0)); 6509e5e54d1SPeter Maydell qdev_connect_gpio_out(devs, 1, 6519e5e54d1SPeter Maydell qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i)); 6529e5e54d1SPeter Maydell qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0, 6539e5e54d1SPeter Maydell qdev_get_gpio_in(devs, 0)); 6547a35383aSPeter Maydell g_free(gpioname); 6559e5e54d1SPeter Maydell } 6569e5e54d1SPeter Maydell 657bb75e16dSPeter Maydell /* Wire up the splitters for the MPC IRQs */ 658*f0cab7feSPeter Maydell for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) { 659bb75e16dSPeter Maydell SplitIRQ *splitter = &s->mpc_irq_splitter[i]; 660bb75e16dSPeter Maydell DeviceState *dev_splitter = DEVICE(splitter); 661bb75e16dSPeter Maydell 662bb75e16dSPeter Maydell object_property_set_int(OBJECT(splitter), 2, "num-lines", &err); 663bb75e16dSPeter Maydell if (err) { 664bb75e16dSPeter Maydell error_propagate(errp, err); 665bb75e16dSPeter Maydell return; 666bb75e16dSPeter Maydell } 667bb75e16dSPeter Maydell object_property_set_bool(OBJECT(splitter), true, "realized", &err); 668bb75e16dSPeter Maydell if (err) { 669bb75e16dSPeter Maydell error_propagate(errp, err); 670bb75e16dSPeter Maydell return; 671bb75e16dSPeter Maydell } 672bb75e16dSPeter Maydell 673bb75e16dSPeter Maydell if (i < IOTS_NUM_EXP_MPC) { 674bb75e16dSPeter Maydell /* Splitter input is from GPIO input line */ 675bb75e16dSPeter Maydell s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0); 676bb75e16dSPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 677bb75e16dSPeter Maydell qdev_get_gpio_in_named(dev_secctl, 678bb75e16dSPeter Maydell "mpcexp_status", i)); 679bb75e16dSPeter Maydell } else { 680bb75e16dSPeter Maydell /* Splitter input is from our own MPC */ 681*f0cab7feSPeter Maydell qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]), 682*f0cab7feSPeter Maydell "irq", 0, 683bb75e16dSPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 684bb75e16dSPeter Maydell qdev_connect_gpio_out(dev_splitter, 0, 685bb75e16dSPeter Maydell qdev_get_gpio_in_named(dev_secctl, 686bb75e16dSPeter Maydell "mpc_status", 0)); 687bb75e16dSPeter Maydell } 688bb75e16dSPeter Maydell 689bb75e16dSPeter Maydell qdev_connect_gpio_out(dev_splitter, 1, 690bb75e16dSPeter Maydell qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i)); 691bb75e16dSPeter Maydell } 692bb75e16dSPeter Maydell /* Create GPIO inputs which will pass the line state for our 693bb75e16dSPeter Maydell * mpcexp_irq inputs to the correct splitter devices. 694bb75e16dSPeter Maydell */ 69513628891SPeter Maydell qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status", 696bb75e16dSPeter Maydell IOTS_NUM_EXP_MPC); 697bb75e16dSPeter Maydell 69813628891SPeter Maydell armsse_forward_sec_resp_cfg(s); 6999e5e54d1SPeter Maydell 700132b475aSPeter Maydell /* Forward the MSC related signals */ 701132b475aSPeter Maydell qdev_pass_gpios(dev_secctl, dev, "mscexp_status"); 702132b475aSPeter Maydell qdev_pass_gpios(dev_secctl, dev, "mscexp_clear"); 703132b475aSPeter Maydell qdev_pass_gpios(dev_secctl, dev, "mscexp_ns"); 704132b475aSPeter Maydell qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0, 705132b475aSPeter Maydell qdev_get_gpio_in(DEVICE(&s->armv7m), 11)); 706132b475aSPeter Maydell 707132b475aSPeter Maydell /* 708132b475aSPeter Maydell * Expose our container region to the board model; this corresponds 709132b475aSPeter Maydell * to the AHB Slave Expansion ports which allow bus master devices 710132b475aSPeter Maydell * (eg DMA controllers) in the board model to make transactions into 71193dbd103SPeter Maydell * devices in the ARMSSE. 712132b475aSPeter Maydell */ 713132b475aSPeter Maydell sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container); 714132b475aSPeter Maydell 7159e5e54d1SPeter Maydell system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq; 7169e5e54d1SPeter Maydell } 7179e5e54d1SPeter Maydell 71813628891SPeter Maydell static void armsse_idau_check(IDAUInterface *ii, uint32_t address, 7199e5e54d1SPeter Maydell int *iregion, bool *exempt, bool *ns, bool *nsc) 7209e5e54d1SPeter Maydell { 72193dbd103SPeter Maydell /* 72293dbd103SPeter Maydell * For ARMSSE systems the IDAU responses are simple logical functions 7239e5e54d1SPeter Maydell * of the address bits. The NSC attribute is guest-adjustable via the 7249e5e54d1SPeter Maydell * NSCCFG register in the security controller. 7259e5e54d1SPeter Maydell */ 72693dbd103SPeter Maydell ARMSSE *s = ARMSSE(ii); 7279e5e54d1SPeter Maydell int region = extract32(address, 28, 4); 7289e5e54d1SPeter Maydell 7299e5e54d1SPeter Maydell *ns = !(region & 1); 7309e5e54d1SPeter Maydell *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2)); 7319e5e54d1SPeter Maydell /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */ 7329e5e54d1SPeter Maydell *exempt = (address & 0xeff00000) == 0xe0000000; 7339e5e54d1SPeter Maydell *iregion = region; 7349e5e54d1SPeter Maydell } 7359e5e54d1SPeter Maydell 73613628891SPeter Maydell static const VMStateDescription armsse_vmstate = { 7379e5e54d1SPeter Maydell .name = "iotkit", 7389e5e54d1SPeter Maydell .version_id = 1, 7399e5e54d1SPeter Maydell .minimum_version_id = 1, 7409e5e54d1SPeter Maydell .fields = (VMStateField[]) { 74193dbd103SPeter Maydell VMSTATE_UINT32(nsccfg, ARMSSE), 7429e5e54d1SPeter Maydell VMSTATE_END_OF_LIST() 7439e5e54d1SPeter Maydell } 7449e5e54d1SPeter Maydell }; 7459e5e54d1SPeter Maydell 74613628891SPeter Maydell static Property armsse_properties[] = { 74793dbd103SPeter Maydell DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION, 7489e5e54d1SPeter Maydell MemoryRegion *), 74993dbd103SPeter Maydell DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64), 75093dbd103SPeter Maydell DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0), 7519e5e54d1SPeter Maydell DEFINE_PROP_END_OF_LIST() 7529e5e54d1SPeter Maydell }; 7539e5e54d1SPeter Maydell 75413628891SPeter Maydell static void armsse_reset(DeviceState *dev) 7559e5e54d1SPeter Maydell { 75693dbd103SPeter Maydell ARMSSE *s = ARMSSE(dev); 7579e5e54d1SPeter Maydell 7589e5e54d1SPeter Maydell s->nsccfg = 0; 7599e5e54d1SPeter Maydell } 7609e5e54d1SPeter Maydell 76113628891SPeter Maydell static void armsse_class_init(ObjectClass *klass, void *data) 7629e5e54d1SPeter Maydell { 7639e5e54d1SPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 7649e5e54d1SPeter Maydell IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass); 7654c3690b5SPeter Maydell ARMSSEClass *asc = ARMSSE_CLASS(klass); 7669e5e54d1SPeter Maydell 76713628891SPeter Maydell dc->realize = armsse_realize; 76813628891SPeter Maydell dc->vmsd = &armsse_vmstate; 76913628891SPeter Maydell dc->props = armsse_properties; 77013628891SPeter Maydell dc->reset = armsse_reset; 77113628891SPeter Maydell iic->check = armsse_idau_check; 7724c3690b5SPeter Maydell asc->info = data; 7739e5e54d1SPeter Maydell } 7749e5e54d1SPeter Maydell 7754c3690b5SPeter Maydell static const TypeInfo armsse_info = { 77693dbd103SPeter Maydell .name = TYPE_ARMSSE, 7779e5e54d1SPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 77893dbd103SPeter Maydell .instance_size = sizeof(ARMSSE), 77913628891SPeter Maydell .instance_init = armsse_init, 7804c3690b5SPeter Maydell .abstract = true, 7819e5e54d1SPeter Maydell .interfaces = (InterfaceInfo[]) { 7829e5e54d1SPeter Maydell { TYPE_IDAU_INTERFACE }, 7839e5e54d1SPeter Maydell { } 7849e5e54d1SPeter Maydell } 7859e5e54d1SPeter Maydell }; 7869e5e54d1SPeter Maydell 7874c3690b5SPeter Maydell static void armsse_register_types(void) 7889e5e54d1SPeter Maydell { 7894c3690b5SPeter Maydell int i; 7904c3690b5SPeter Maydell 7914c3690b5SPeter Maydell type_register_static(&armsse_info); 7924c3690b5SPeter Maydell 7934c3690b5SPeter Maydell for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) { 7944c3690b5SPeter Maydell TypeInfo ti = { 7954c3690b5SPeter Maydell .name = armsse_variants[i].name, 7964c3690b5SPeter Maydell .parent = TYPE_ARMSSE, 79713628891SPeter Maydell .class_init = armsse_class_init, 7984c3690b5SPeter Maydell .class_data = (void *)&armsse_variants[i], 7994c3690b5SPeter Maydell }; 8004c3690b5SPeter Maydell type_register(&ti); 8014c3690b5SPeter Maydell } 8029e5e54d1SPeter Maydell } 8039e5e54d1SPeter Maydell 8044c3690b5SPeter Maydell type_init(armsse_register_types); 805