18f69a4c1SPeter Maydell /* 28f69a4c1SPeter Maydell * Arm Musca-B1 test chip board emulation 38f69a4c1SPeter Maydell * 48f69a4c1SPeter Maydell * Copyright (c) 2019 Linaro Limited 58f69a4c1SPeter Maydell * Written by Peter Maydell 68f69a4c1SPeter Maydell * 78f69a4c1SPeter Maydell * This program is free software; you can redistribute it and/or modify 88f69a4c1SPeter Maydell * it under the terms of the GNU General Public License version 2 or 98f69a4c1SPeter Maydell * (at your option) any later version. 108f69a4c1SPeter Maydell */ 118f69a4c1SPeter Maydell 128f69a4c1SPeter Maydell /* 138f69a4c1SPeter Maydell * The Musca boards are a reference implementation of a system using 148f69a4c1SPeter Maydell * the SSE-200 subsystem for embedded: 158f69a4c1SPeter Maydell * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board 168f69a4c1SPeter Maydell * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board 178f69a4c1SPeter Maydell * We model the A and B1 variants of this board, as described in the TRMs: 188f69a4c1SPeter Maydell * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html 198f69a4c1SPeter Maydell * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html 208f69a4c1SPeter Maydell */ 218f69a4c1SPeter Maydell 228f69a4c1SPeter Maydell #include "qemu/osdep.h" 238f69a4c1SPeter Maydell #include "qemu/error-report.h" 248f69a4c1SPeter Maydell #include "qapi/error.h" 258f69a4c1SPeter Maydell #include "exec/address-spaces.h" 261486f1baSPeter Maydell #include "sysemu/sysemu.h" 2712ec8bd5SPeter Maydell #include "hw/arm/boot.h" 288f69a4c1SPeter Maydell #include "hw/arm/armsse.h" 298f69a4c1SPeter Maydell #include "hw/boards.h" 301486f1baSPeter Maydell #include "hw/char/pl011.h" 318f69a4c1SPeter Maydell #include "hw/core/split-irq.h" 3233293e50SPeter Maydell #include "hw/misc/tz-mpc.h" 33ae3bc714SPeter Maydell #include "hw/misc/tz-ppc.h" 34ae3bc714SPeter Maydell #include "hw/misc/unimp.h" 35877c181cSPhilippe Mathieu-Daudé #include "hw/rtc/pl031.h" 368f69a4c1SPeter Maydell 378f69a4c1SPeter Maydell #define MUSCA_NUMIRQ_MAX 96 38ae3bc714SPeter Maydell #define MUSCA_PPC_MAX 3 3933293e50SPeter Maydell #define MUSCA_MPC_MAX 5 4033293e50SPeter Maydell 4133293e50SPeter Maydell typedef struct MPCInfo MPCInfo; 428f69a4c1SPeter Maydell 438f69a4c1SPeter Maydell typedef enum MuscaType { 448f69a4c1SPeter Maydell MUSCA_A, 458f69a4c1SPeter Maydell MUSCA_B1, 468f69a4c1SPeter Maydell } MuscaType; 478f69a4c1SPeter Maydell 488f69a4c1SPeter Maydell typedef struct { 498f69a4c1SPeter Maydell MachineClass parent; 508f69a4c1SPeter Maydell MuscaType type; 518f69a4c1SPeter Maydell uint32_t init_svtor; 528f69a4c1SPeter Maydell int sram_addr_width; 538f69a4c1SPeter Maydell int num_irqs; 5433293e50SPeter Maydell const MPCInfo *mpc_info; 5533293e50SPeter Maydell int num_mpcs; 568f69a4c1SPeter Maydell } MuscaMachineClass; 578f69a4c1SPeter Maydell 588f69a4c1SPeter Maydell typedef struct { 598f69a4c1SPeter Maydell MachineState parent; 608f69a4c1SPeter Maydell 618f69a4c1SPeter Maydell ARMSSE sse; 6233293e50SPeter Maydell /* RAM and flash */ 6333293e50SPeter Maydell MemoryRegion ram[MUSCA_MPC_MAX]; 648f69a4c1SPeter Maydell SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX]; 65ae3bc714SPeter Maydell SplitIRQ sec_resp_splitter; 66ae3bc714SPeter Maydell TZPPC ppc[MUSCA_PPC_MAX]; 67ae3bc714SPeter Maydell MemoryRegion container; 68ae3bc714SPeter Maydell UnimplementedDeviceState eflash[2]; 69ae3bc714SPeter Maydell UnimplementedDeviceState qspi; 7033293e50SPeter Maydell TZMPC mpc[MUSCA_MPC_MAX]; 71ae3bc714SPeter Maydell UnimplementedDeviceState mhu[2]; 72ae3bc714SPeter Maydell UnimplementedDeviceState pwm[3]; 73ae3bc714SPeter Maydell UnimplementedDeviceState i2s; 741486f1baSPeter Maydell PL011State uart[2]; 75ae3bc714SPeter Maydell UnimplementedDeviceState i2c[2]; 76ae3bc714SPeter Maydell UnimplementedDeviceState spi; 77ae3bc714SPeter Maydell UnimplementedDeviceState scc; 78ae3bc714SPeter Maydell UnimplementedDeviceState timer; 794db6a761SPeter Maydell PL031State rtc; 80ae3bc714SPeter Maydell UnimplementedDeviceState pvt; 81ae3bc714SPeter Maydell UnimplementedDeviceState sdio; 82ae3bc714SPeter Maydell UnimplementedDeviceState gpio; 8333293e50SPeter Maydell UnimplementedDeviceState cryptoisland; 848f69a4c1SPeter Maydell } MuscaMachineState; 858f69a4c1SPeter Maydell 868f69a4c1SPeter Maydell #define TYPE_MUSCA_MACHINE "musca" 878f69a4c1SPeter Maydell #define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a") 888f69a4c1SPeter Maydell #define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1") 898f69a4c1SPeter Maydell 908f69a4c1SPeter Maydell #define MUSCA_MACHINE(obj) \ 918f69a4c1SPeter Maydell OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE) 928f69a4c1SPeter Maydell #define MUSCA_MACHINE_GET_CLASS(obj) \ 938f69a4c1SPeter Maydell OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE) 948f69a4c1SPeter Maydell #define MUSCA_MACHINE_CLASS(klass) \ 958f69a4c1SPeter Maydell OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE) 968f69a4c1SPeter Maydell 978f69a4c1SPeter Maydell /* 988f69a4c1SPeter Maydell * Main SYSCLK frequency in Hz 998f69a4c1SPeter Maydell * TODO this should really be different for the two cores, but we 1008f69a4c1SPeter Maydell * don't model that in our SSE-200 model yet. 1018f69a4c1SPeter Maydell */ 1028f69a4c1SPeter Maydell #define SYSCLK_FRQ 40000000 1038f69a4c1SPeter Maydell 1044db6a761SPeter Maydell static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno) 1054db6a761SPeter Maydell { 1064db6a761SPeter Maydell /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */ 1074db6a761SPeter Maydell assert(irqno < MUSCA_NUMIRQ_MAX); 1084db6a761SPeter Maydell 1094db6a761SPeter Maydell return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0); 1104db6a761SPeter Maydell } 1114db6a761SPeter Maydell 112ae3bc714SPeter Maydell /* 113ae3bc714SPeter Maydell * Most of the devices in the Musca board sit behind Peripheral Protection 114ae3bc714SPeter Maydell * Controllers. These data structures define the layout of which devices 115ae3bc714SPeter Maydell * sit behind which PPCs. 116ae3bc714SPeter Maydell * The devfn for each port is a function which creates, configures 117ae3bc714SPeter Maydell * and initializes the device, returning the MemoryRegion which 118ae3bc714SPeter Maydell * needs to be plugged into the downstream end of the PPC port. 119ae3bc714SPeter Maydell */ 120ae3bc714SPeter Maydell typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque, 121ae3bc714SPeter Maydell const char *name, hwaddr size); 122ae3bc714SPeter Maydell 123ae3bc714SPeter Maydell typedef struct PPCPortInfo { 124ae3bc714SPeter Maydell const char *name; 125ae3bc714SPeter Maydell MakeDevFn *devfn; 126ae3bc714SPeter Maydell void *opaque; 127ae3bc714SPeter Maydell hwaddr addr; 128ae3bc714SPeter Maydell hwaddr size; 129ae3bc714SPeter Maydell } PPCPortInfo; 130ae3bc714SPeter Maydell 131ae3bc714SPeter Maydell typedef struct PPCInfo { 132ae3bc714SPeter Maydell const char *name; 133ae3bc714SPeter Maydell PPCPortInfo ports[TZ_NUM_PORTS]; 134ae3bc714SPeter Maydell } PPCInfo; 135ae3bc714SPeter Maydell 136ae3bc714SPeter Maydell static MemoryRegion *make_unimp_dev(MuscaMachineState *mms, 137ae3bc714SPeter Maydell void *opaque, const char *name, hwaddr size) 138ae3bc714SPeter Maydell { 139ae3bc714SPeter Maydell /* 140ae3bc714SPeter Maydell * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE, 141ae3bc714SPeter Maydell * and return a pointer to its MemoryRegion. 142ae3bc714SPeter Maydell */ 143ae3bc714SPeter Maydell UnimplementedDeviceState *uds = opaque; 144ae3bc714SPeter Maydell 145*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, TYPE_UNIMPLEMENTED_DEVICE); 146ae3bc714SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", name); 147ae3bc714SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", size); 148*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); 149ae3bc714SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 150ae3bc714SPeter Maydell } 151ae3bc714SPeter Maydell 15233293e50SPeter Maydell typedef enum MPCInfoType { 15333293e50SPeter Maydell MPC_RAM, 15433293e50SPeter Maydell MPC_ROM, 15533293e50SPeter Maydell MPC_CRYPTOISLAND, 15633293e50SPeter Maydell } MPCInfoType; 15733293e50SPeter Maydell 15833293e50SPeter Maydell struct MPCInfo { 15933293e50SPeter Maydell const char *name; 16033293e50SPeter Maydell hwaddr addr; 16133293e50SPeter Maydell hwaddr size; 16233293e50SPeter Maydell MPCInfoType type; 16333293e50SPeter Maydell }; 16433293e50SPeter Maydell 16533293e50SPeter Maydell /* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */ 16633293e50SPeter Maydell static const MPCInfo a_mpc_info[] = { { 16733293e50SPeter Maydell .name = "qspi", 16833293e50SPeter Maydell .type = MPC_ROM, 16933293e50SPeter Maydell .addr = 0x00200000, 17033293e50SPeter Maydell .size = 0x00800000, 17133293e50SPeter Maydell }, { 17233293e50SPeter Maydell .name = "sram", 17333293e50SPeter Maydell .type = MPC_RAM, 17433293e50SPeter Maydell .addr = 0x00000000, 17533293e50SPeter Maydell .size = 0x00200000, 17633293e50SPeter Maydell } 17733293e50SPeter Maydell }; 17833293e50SPeter Maydell 17933293e50SPeter Maydell static const MPCInfo b1_mpc_info[] = { { 18033293e50SPeter Maydell .name = "qspi", 18133293e50SPeter Maydell .type = MPC_ROM, 18233293e50SPeter Maydell .addr = 0x00000000, 18333293e50SPeter Maydell .size = 0x02000000, 18433293e50SPeter Maydell }, { 18533293e50SPeter Maydell .name = "sram", 18633293e50SPeter Maydell .type = MPC_RAM, 18733293e50SPeter Maydell .addr = 0x0a400000, 18833293e50SPeter Maydell .size = 0x00080000, 18933293e50SPeter Maydell }, { 19033293e50SPeter Maydell .name = "eflash0", 19133293e50SPeter Maydell .type = MPC_ROM, 19233293e50SPeter Maydell .addr = 0x0a000000, 19333293e50SPeter Maydell .size = 0x00200000, 19433293e50SPeter Maydell }, { 19533293e50SPeter Maydell .name = "eflash1", 19633293e50SPeter Maydell .type = MPC_ROM, 19733293e50SPeter Maydell .addr = 0x0a200000, 19833293e50SPeter Maydell .size = 0x00200000, 19933293e50SPeter Maydell }, { 20033293e50SPeter Maydell .name = "cryptoisland", 20133293e50SPeter Maydell .type = MPC_CRYPTOISLAND, 20233293e50SPeter Maydell .addr = 0x0a000000, 20333293e50SPeter Maydell .size = 0x00200000, 20433293e50SPeter Maydell } 20533293e50SPeter Maydell }; 20633293e50SPeter Maydell 20733293e50SPeter Maydell static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque, 20833293e50SPeter Maydell const char *name, hwaddr size) 20933293e50SPeter Maydell { 21033293e50SPeter Maydell /* 21133293e50SPeter Maydell * Create an MPC and the RAM or flash behind it. 21233293e50SPeter Maydell * MPC 0: eFlash 0 21333293e50SPeter Maydell * MPC 1: eFlash 1 21433293e50SPeter Maydell * MPC 2: SRAM 21533293e50SPeter Maydell * MPC 3: QSPI flash 21633293e50SPeter Maydell * MPC 4: CryptoIsland 21733293e50SPeter Maydell * For now we implement the flash regions as ROM (ie not programmable) 21833293e50SPeter Maydell * (with their control interface memory regions being unimplemented 21933293e50SPeter Maydell * stubs behind the PPCs). 22033293e50SPeter Maydell * The whole CryptoIsland region behind its MPC is an unimplemented stub. 22133293e50SPeter Maydell */ 22233293e50SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 22333293e50SPeter Maydell TZMPC *mpc = opaque; 22433293e50SPeter Maydell int i = mpc - &mms->mpc[0]; 22533293e50SPeter Maydell MemoryRegion *downstream; 22633293e50SPeter Maydell MemoryRegion *upstream; 22733293e50SPeter Maydell UnimplementedDeviceState *uds; 22833293e50SPeter Maydell char *mpcname; 22933293e50SPeter Maydell const MPCInfo *mpcinfo = mmc->mpc_info; 23033293e50SPeter Maydell 23133293e50SPeter Maydell mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name); 23233293e50SPeter Maydell 23333293e50SPeter Maydell switch (mpcinfo[i].type) { 23433293e50SPeter Maydell case MPC_ROM: 23533293e50SPeter Maydell downstream = &mms->ram[i]; 23633293e50SPeter Maydell memory_region_init_rom(downstream, NULL, mpcinfo[i].name, 23733293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 23833293e50SPeter Maydell break; 23933293e50SPeter Maydell case MPC_RAM: 24033293e50SPeter Maydell downstream = &mms->ram[i]; 24133293e50SPeter Maydell memory_region_init_ram(downstream, NULL, mpcinfo[i].name, 24233293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 24333293e50SPeter Maydell break; 24433293e50SPeter Maydell case MPC_CRYPTOISLAND: 24533293e50SPeter Maydell /* We don't implement the CryptoIsland yet */ 24633293e50SPeter Maydell uds = &mms->cryptoisland; 247*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, 24833293e50SPeter Maydell TYPE_UNIMPLEMENTED_DEVICE); 24933293e50SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name); 25033293e50SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size); 251*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); 25233293e50SPeter Maydell downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 25333293e50SPeter Maydell break; 25433293e50SPeter Maydell default: 25533293e50SPeter Maydell g_assert_not_reached(); 25633293e50SPeter Maydell } 25733293e50SPeter Maydell 258*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC); 25933293e50SPeter Maydell object_property_set_link(OBJECT(mpc), OBJECT(downstream), 26033293e50SPeter Maydell "downstream", &error_fatal); 261*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal); 26233293e50SPeter Maydell /* Map the upstream end of the MPC into system memory */ 26333293e50SPeter Maydell upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); 26433293e50SPeter Maydell memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream); 26533293e50SPeter Maydell /* and connect its interrupt to the SSE-200 */ 26633293e50SPeter Maydell qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0, 26733293e50SPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->sse), 26833293e50SPeter Maydell "mpcexp_status", i)); 26933293e50SPeter Maydell 27033293e50SPeter Maydell g_free(mpcname); 27133293e50SPeter Maydell /* Return the register interface MR for our caller to map behind the PPC */ 27233293e50SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); 27333293e50SPeter Maydell } 27433293e50SPeter Maydell 2754db6a761SPeter Maydell static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque, 2764db6a761SPeter Maydell const char *name, hwaddr size) 2774db6a761SPeter Maydell { 2784db6a761SPeter Maydell PL031State *rtc = opaque; 2794db6a761SPeter Maydell 280*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, rtc, TYPE_PL031); 281*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(rtc), &error_fatal); 2824db6a761SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39)); 2834db6a761SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0); 2844db6a761SPeter Maydell } 2854db6a761SPeter Maydell 2861486f1baSPeter Maydell static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque, 2871486f1baSPeter Maydell const char *name, hwaddr size) 2881486f1baSPeter Maydell { 2891486f1baSPeter Maydell PL011State *uart = opaque; 2901486f1baSPeter Maydell int i = uart - &mms->uart[0]; 2911486f1baSPeter Maydell int irqbase = 7 + i * 6; 2921486f1baSPeter Maydell SysBusDevice *s; 2931486f1baSPeter Maydell 294*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uart, TYPE_PL011); 2951486f1baSPeter Maydell qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); 296*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal); 2971486f1baSPeter Maydell s = SYS_BUS_DEVICE(uart); 2981486f1baSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */ 2991486f1baSPeter Maydell sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */ 3001486f1baSPeter Maydell sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */ 3011486f1baSPeter Maydell sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */ 3021486f1baSPeter Maydell sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */ 3031486f1baSPeter Maydell sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */ 3041486f1baSPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0); 3051486f1baSPeter Maydell } 3061486f1baSPeter Maydell 307ae3bc714SPeter Maydell static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque, 308ae3bc714SPeter Maydell const char *name, hwaddr size) 309ae3bc714SPeter Maydell { 310ae3bc714SPeter Maydell /* 311ae3bc714SPeter Maydell * Create the container MemoryRegion for all the devices that live 312ae3bc714SPeter Maydell * behind the Musca-A PPC's single port. These devices don't have a PPC 313ae3bc714SPeter Maydell * port each, but we use the PPCPortInfo struct as a convenient way 314ae3bc714SPeter Maydell * to describe them. Note that addresses here are relative to the base 315ae3bc714SPeter Maydell * address of the PPC port region: 0x40100000, and devices appear both 316ae3bc714SPeter Maydell * at the 0x4... NS region and the 0x5... S region. 317ae3bc714SPeter Maydell */ 318ae3bc714SPeter Maydell int i; 319ae3bc714SPeter Maydell MemoryRegion *container = &mms->container; 320ae3bc714SPeter Maydell 321ae3bc714SPeter Maydell const PPCPortInfo devices[] = { 3221486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 }, 3231486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 }, 324ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 }, 325ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 }, 326ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 }, 327ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 }, 328ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 }, 3294db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 }, 330ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 }, 331ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 }, 332ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 }, 333ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 }, 334ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 }, 335ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 }, 33633293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 }, 33733293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 }, 338ae3bc714SPeter Maydell }; 339ae3bc714SPeter Maydell 340ae3bc714SPeter Maydell memory_region_init(container, OBJECT(mms), "musca-device-container", size); 341ae3bc714SPeter Maydell 342ae3bc714SPeter Maydell for (i = 0; i < ARRAY_SIZE(devices); i++) { 343ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &devices[i]; 344ae3bc714SPeter Maydell MemoryRegion *mr; 345ae3bc714SPeter Maydell 346ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 347ae3bc714SPeter Maydell memory_region_add_subregion(container, pinfo->addr, mr); 348ae3bc714SPeter Maydell } 349ae3bc714SPeter Maydell 350ae3bc714SPeter Maydell return &mms->container; 351ae3bc714SPeter Maydell } 352ae3bc714SPeter Maydell 3538f69a4c1SPeter Maydell static void musca_init(MachineState *machine) 3548f69a4c1SPeter Maydell { 3558f69a4c1SPeter Maydell MuscaMachineState *mms = MUSCA_MACHINE(machine); 3568f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 3578f69a4c1SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(machine); 3588f69a4c1SPeter Maydell MemoryRegion *system_memory = get_system_memory(); 3598f69a4c1SPeter Maydell DeviceState *ssedev; 360ae3bc714SPeter Maydell DeviceState *dev_splitter; 361ae3bc714SPeter Maydell const PPCInfo *ppcs; 362ae3bc714SPeter Maydell int num_ppcs; 3638f69a4c1SPeter Maydell int i; 3648f69a4c1SPeter Maydell 3658f69a4c1SPeter Maydell assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX); 36633293e50SPeter Maydell assert(mmc->num_mpcs <= MUSCA_MPC_MAX); 3678f69a4c1SPeter Maydell 3688f69a4c1SPeter Maydell if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { 3698f69a4c1SPeter Maydell error_report("This board can only be used with CPU %s", 3708f69a4c1SPeter Maydell mc->default_cpu_type); 3718f69a4c1SPeter Maydell exit(1); 3728f69a4c1SPeter Maydell } 3738f69a4c1SPeter Maydell 374*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), "sse-200", &mms->sse, 375*0074fce6SMarkus Armbruster TYPE_SSE200); 3768f69a4c1SPeter Maydell ssedev = DEVICE(&mms->sse); 3778f69a4c1SPeter Maydell object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory), 3788f69a4c1SPeter Maydell "memory", &error_fatal); 3798f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs); 3808f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor); 3818f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width); 3828f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ); 383a90a862bSPeter Maydell /* 384a90a862bSPeter Maydell * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for 385a90a862bSPeter Maydell * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0. 386a90a862bSPeter Maydell */ 387a90a862bSPeter Maydell if (mmc->type == MUSCA_B1) { 388a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_FPU", true); 389a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_DSP", true); 390a90a862bSPeter Maydell } 391*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(&mms->sse), &error_fatal); 3928f69a4c1SPeter Maydell 3938f69a4c1SPeter Maydell /* 3948f69a4c1SPeter Maydell * We need to create splitters to feed the IRQ inputs 3958f69a4c1SPeter Maydell * for each CPU in the SSE-200 from each device in the board. 3968f69a4c1SPeter Maydell */ 3978f69a4c1SPeter Maydell for (i = 0; i < mmc->num_irqs; i++) { 3988f69a4c1SPeter Maydell char *name = g_strdup_printf("musca-irq-splitter%d", i); 3998f69a4c1SPeter Maydell SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; 4008f69a4c1SPeter Maydell 4019fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), name, splitter, 4029fc7fc4dSMarkus Armbruster sizeof(*splitter), TYPE_SPLIT_IRQ, 4039fc7fc4dSMarkus Armbruster &error_fatal, NULL); 4048f69a4c1SPeter Maydell g_free(name); 4058f69a4c1SPeter Maydell 4068f69a4c1SPeter Maydell object_property_set_int(OBJECT(splitter), 2, "num-lines", 4078f69a4c1SPeter Maydell &error_fatal); 4088f69a4c1SPeter Maydell object_property_set_bool(OBJECT(splitter), true, "realized", 4098f69a4c1SPeter Maydell &error_fatal); 4108f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 0, 4118f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i)); 4128f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 1, 4138f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, 4148f69a4c1SPeter Maydell "EXP_CPU1_IRQ", i)); 4158f69a4c1SPeter Maydell } 4168f69a4c1SPeter Maydell 417ae3bc714SPeter Maydell /* 418ae3bc714SPeter Maydell * The sec_resp_cfg output from the SSE-200 must be split into multiple 419ae3bc714SPeter Maydell * lines, one for each of the PPCs we create here. 420ae3bc714SPeter Maydell */ 4219fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), "sec-resp-splitter", 4227840938eSPhilippe Mathieu-Daudé &mms->sec_resp_splitter, 4237840938eSPhilippe Mathieu-Daudé sizeof(mms->sec_resp_splitter), 4247840938eSPhilippe Mathieu-Daudé TYPE_SPLIT_IRQ, &error_fatal, NULL); 4257840938eSPhilippe Mathieu-Daudé 426ae3bc714SPeter Maydell object_property_set_int(OBJECT(&mms->sec_resp_splitter), 427ae3bc714SPeter Maydell ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal); 428ae3bc714SPeter Maydell object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true, 429ae3bc714SPeter Maydell "realized", &error_fatal); 430ae3bc714SPeter Maydell dev_splitter = DEVICE(&mms->sec_resp_splitter); 431ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0, 432ae3bc714SPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 433ae3bc714SPeter Maydell 434ae3bc714SPeter Maydell /* 435ae3bc714SPeter Maydell * Most of the devices in the board are behind Peripheral Protection 436ae3bc714SPeter Maydell * Controllers. The required order for initializing things is: 437ae3bc714SPeter Maydell * + initialize the PPC 438ae3bc714SPeter Maydell * + initialize, configure and realize downstream devices 439ae3bc714SPeter Maydell * + connect downstream device MemoryRegions to the PPC 440ae3bc714SPeter Maydell * + realize the PPC 441ae3bc714SPeter Maydell * + map the PPC's MemoryRegions to the places in the address map 442ae3bc714SPeter Maydell * where the downstream devices should appear 443ae3bc714SPeter Maydell * + wire up the PPC's control lines to the SSE object 444ae3bc714SPeter Maydell * 445ae3bc714SPeter Maydell * The PPC mapping differs for the -A and -B1 variants; the -A version 446ae3bc714SPeter Maydell * is much simpler, using only a single port of a single PPC and putting 447ae3bc714SPeter Maydell * all the devices behind that. 448ae3bc714SPeter Maydell */ 449ae3bc714SPeter Maydell const PPCInfo a_ppcs[] = { { 450ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 451ae3bc714SPeter Maydell .ports = { 452ae3bc714SPeter Maydell { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 }, 453ae3bc714SPeter Maydell }, 454ae3bc714SPeter Maydell }, 455ae3bc714SPeter Maydell }; 456ae3bc714SPeter Maydell 457ae3bc714SPeter Maydell /* 458ae3bc714SPeter Maydell * Devices listed with an 0x4.. address appear in both the NS 0x4.. region 459ae3bc714SPeter Maydell * and the 0x5.. S region. Devices listed with an 0x5.. address appear 460ae3bc714SPeter Maydell * only in the S region. 461ae3bc714SPeter Maydell */ 462ae3bc714SPeter Maydell const PPCInfo b1_ppcs[] = { { 463ae3bc714SPeter Maydell .name = "apb_ppcexp0", 464ae3bc714SPeter Maydell .ports = { 465ae3bc714SPeter Maydell { "eflash0", make_unimp_dev, &mms->eflash[0], 466ae3bc714SPeter Maydell 0x52400000, 0x1000 }, 467ae3bc714SPeter Maydell { "eflash1", make_unimp_dev, &mms->eflash[1], 468ae3bc714SPeter Maydell 0x52500000, 0x1000 }, 469ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 }, 47033293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 }, 47133293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 }, 47233293e50SPeter Maydell { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 }, 47333293e50SPeter Maydell { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 }, 474ae3bc714SPeter Maydell { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 }, 475ae3bc714SPeter Maydell { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 }, 476ae3bc714SPeter Maydell { }, /* port 9: unused */ 477ae3bc714SPeter Maydell { }, /* port 10: unused */ 478ae3bc714SPeter Maydell { }, /* port 11: unused */ 479ae3bc714SPeter Maydell { }, /* port 12: unused */ 480ae3bc714SPeter Maydell { }, /* port 13: unused */ 48133293e50SPeter Maydell { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 }, 482ae3bc714SPeter Maydell }, 483ae3bc714SPeter Maydell }, { 484ae3bc714SPeter Maydell .name = "apb_ppcexp1", 485ae3bc714SPeter Maydell .ports = { 486ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 }, 487ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 }, 488ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 }, 489ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 }, 4901486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 }, 4911486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 }, 492ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 }, 493ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 }, 494ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 }, 495ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 }, 496ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 }, 4974db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 }, 498ae3bc714SPeter Maydell { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 }, 499ae3bc714SPeter Maydell { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 }, 500ae3bc714SPeter Maydell }, 501ae3bc714SPeter Maydell }, { 502ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 503ae3bc714SPeter Maydell .ports = { 504ae3bc714SPeter Maydell { }, /* port 0: unused */ 505ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 }, 506ae3bc714SPeter Maydell }, 507ae3bc714SPeter Maydell }, 508ae3bc714SPeter Maydell }; 509ae3bc714SPeter Maydell 510ae3bc714SPeter Maydell switch (mmc->type) { 511ae3bc714SPeter Maydell case MUSCA_A: 512ae3bc714SPeter Maydell ppcs = a_ppcs; 513ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(a_ppcs); 514ae3bc714SPeter Maydell break; 515ae3bc714SPeter Maydell case MUSCA_B1: 516ae3bc714SPeter Maydell ppcs = b1_ppcs; 517ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(b1_ppcs); 518ae3bc714SPeter Maydell break; 519ae3bc714SPeter Maydell default: 520ae3bc714SPeter Maydell g_assert_not_reached(); 521ae3bc714SPeter Maydell } 522ae3bc714SPeter Maydell assert(num_ppcs <= MUSCA_PPC_MAX); 523ae3bc714SPeter Maydell 524ae3bc714SPeter Maydell for (i = 0; i < num_ppcs; i++) { 525ae3bc714SPeter Maydell const PPCInfo *ppcinfo = &ppcs[i]; 526ae3bc714SPeter Maydell TZPPC *ppc = &mms->ppc[i]; 527ae3bc714SPeter Maydell DeviceState *ppcdev; 528ae3bc714SPeter Maydell int port; 529ae3bc714SPeter Maydell char *gpioname; 530ae3bc714SPeter Maydell 531*0074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), ppcinfo->name, ppc, 532*0074fce6SMarkus Armbruster TYPE_TZ_PPC); 533ae3bc714SPeter Maydell ppcdev = DEVICE(ppc); 534ae3bc714SPeter Maydell 535ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 536ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 537ae3bc714SPeter Maydell MemoryRegion *mr; 538ae3bc714SPeter Maydell char *portname; 539ae3bc714SPeter Maydell 540ae3bc714SPeter Maydell if (!pinfo->devfn) { 541ae3bc714SPeter Maydell continue; 542ae3bc714SPeter Maydell } 543ae3bc714SPeter Maydell 544ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 545ae3bc714SPeter Maydell portname = g_strdup_printf("port[%d]", port); 546ae3bc714SPeter Maydell object_property_set_link(OBJECT(ppc), OBJECT(mr), 547ae3bc714SPeter Maydell portname, &error_fatal); 548ae3bc714SPeter Maydell g_free(portname); 549ae3bc714SPeter Maydell } 550ae3bc714SPeter Maydell 551*0074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(ppc), &error_fatal); 552ae3bc714SPeter Maydell 553ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 554ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 555ae3bc714SPeter Maydell 556ae3bc714SPeter Maydell if (!pinfo->devfn) { 557ae3bc714SPeter Maydell continue; 558ae3bc714SPeter Maydell } 559ae3bc714SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr); 560ae3bc714SPeter Maydell 561ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name); 562ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 563ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 564ae3bc714SPeter Maydell "cfg_nonsec", 565ae3bc714SPeter Maydell port)); 566ae3bc714SPeter Maydell g_free(gpioname); 567ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_ap", ppcinfo->name); 568ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 569ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 570ae3bc714SPeter Maydell "cfg_ap", port)); 571ae3bc714SPeter Maydell g_free(gpioname); 572ae3bc714SPeter Maydell } 573ae3bc714SPeter Maydell 574ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name); 575ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 576ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 577ae3bc714SPeter Maydell "irq_enable", 0)); 578ae3bc714SPeter Maydell g_free(gpioname); 579ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name); 580ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 581ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 582ae3bc714SPeter Maydell "irq_clear", 0)); 583ae3bc714SPeter Maydell g_free(gpioname); 584ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name); 585ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ppcdev, "irq", 0, 586ae3bc714SPeter Maydell qdev_get_gpio_in_named(ssedev, 587ae3bc714SPeter Maydell gpioname, 0)); 588ae3bc714SPeter Maydell g_free(gpioname); 589ae3bc714SPeter Maydell 590ae3bc714SPeter Maydell qdev_connect_gpio_out(dev_splitter, i, 591ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 592ae3bc714SPeter Maydell "cfg_sec_resp", 0)); 593ae3bc714SPeter Maydell } 594ae3bc714SPeter Maydell 5958f69a4c1SPeter Maydell armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000); 5968f69a4c1SPeter Maydell } 5978f69a4c1SPeter Maydell 5988f69a4c1SPeter Maydell static void musca_class_init(ObjectClass *oc, void *data) 5998f69a4c1SPeter Maydell { 6008f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6018f69a4c1SPeter Maydell 6028f69a4c1SPeter Maydell mc->default_cpus = 2; 6038f69a4c1SPeter Maydell mc->min_cpus = mc->default_cpus; 6048f69a4c1SPeter Maydell mc->max_cpus = mc->default_cpus; 6058f69a4c1SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"); 6068f69a4c1SPeter Maydell mc->init = musca_init; 6078f69a4c1SPeter Maydell } 6088f69a4c1SPeter Maydell 6098f69a4c1SPeter Maydell static void musca_a_class_init(ObjectClass *oc, void *data) 6108f69a4c1SPeter Maydell { 6118f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6128f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6138f69a4c1SPeter Maydell 6148f69a4c1SPeter Maydell mc->desc = "ARM Musca-A board (dual Cortex-M33)"; 6158f69a4c1SPeter Maydell mmc->type = MUSCA_A; 6168f69a4c1SPeter Maydell mmc->init_svtor = 0x10200000; 6178f69a4c1SPeter Maydell mmc->sram_addr_width = 15; 6188f69a4c1SPeter Maydell mmc->num_irqs = 64; 61933293e50SPeter Maydell mmc->mpc_info = a_mpc_info; 62033293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(a_mpc_info); 6218f69a4c1SPeter Maydell } 6228f69a4c1SPeter Maydell 6238f69a4c1SPeter Maydell static void musca_b1_class_init(ObjectClass *oc, void *data) 6248f69a4c1SPeter Maydell { 6258f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6268f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6278f69a4c1SPeter Maydell 6288f69a4c1SPeter Maydell mc->desc = "ARM Musca-B1 board (dual Cortex-M33)"; 6298f69a4c1SPeter Maydell mmc->type = MUSCA_B1; 6308f69a4c1SPeter Maydell /* 6318f69a4c1SPeter Maydell * This matches the DAPlink firmware which boots from QSPI. There 6328f69a4c1SPeter Maydell * is also a firmware blob which boots from the eFlash, which 6338f69a4c1SPeter Maydell * uses init_svtor = 0x1A000000. QEMU doesn't currently support that, 6348f69a4c1SPeter Maydell * though we could in theory expose a machine property on the command 6358f69a4c1SPeter Maydell * line to allow the user to request eFlash boot. 6368f69a4c1SPeter Maydell */ 6378f69a4c1SPeter Maydell mmc->init_svtor = 0x10000000; 6388f69a4c1SPeter Maydell mmc->sram_addr_width = 17; 6398f69a4c1SPeter Maydell mmc->num_irqs = 96; 64033293e50SPeter Maydell mmc->mpc_info = b1_mpc_info; 64133293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info); 6428f69a4c1SPeter Maydell } 6438f69a4c1SPeter Maydell 6448f69a4c1SPeter Maydell static const TypeInfo musca_info = { 6458f69a4c1SPeter Maydell .name = TYPE_MUSCA_MACHINE, 6468f69a4c1SPeter Maydell .parent = TYPE_MACHINE, 6478f69a4c1SPeter Maydell .abstract = true, 6488f69a4c1SPeter Maydell .instance_size = sizeof(MuscaMachineState), 6498f69a4c1SPeter Maydell .class_size = sizeof(MuscaMachineClass), 6508f69a4c1SPeter Maydell .class_init = musca_class_init, 6518f69a4c1SPeter Maydell }; 6528f69a4c1SPeter Maydell 6538f69a4c1SPeter Maydell static const TypeInfo musca_a_info = { 6548f69a4c1SPeter Maydell .name = TYPE_MUSCA_A_MACHINE, 6558f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6568f69a4c1SPeter Maydell .class_init = musca_a_class_init, 6578f69a4c1SPeter Maydell }; 6588f69a4c1SPeter Maydell 6598f69a4c1SPeter Maydell static const TypeInfo musca_b1_info = { 6608f69a4c1SPeter Maydell .name = TYPE_MUSCA_B1_MACHINE, 6618f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6628f69a4c1SPeter Maydell .class_init = musca_b1_class_init, 6638f69a4c1SPeter Maydell }; 6648f69a4c1SPeter Maydell 6658f69a4c1SPeter Maydell static void musca_machine_init(void) 6668f69a4c1SPeter Maydell { 6678f69a4c1SPeter Maydell type_register_static(&musca_info); 6688f69a4c1SPeter Maydell type_register_static(&musca_a_info); 6698f69a4c1SPeter Maydell type_register_static(&musca_b1_info); 6708f69a4c1SPeter Maydell } 6718f69a4c1SPeter Maydell 6728f69a4c1SPeter Maydell type_init(musca_machine_init); 673