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" 36db1015e9SEduardo Habkost #include "qom/object.h" 378f69a4c1SPeter Maydell 388f69a4c1SPeter Maydell #define MUSCA_NUMIRQ_MAX 96 39ae3bc714SPeter Maydell #define MUSCA_PPC_MAX 3 4033293e50SPeter Maydell #define MUSCA_MPC_MAX 5 4133293e50SPeter Maydell 4233293e50SPeter Maydell typedef struct MPCInfo MPCInfo; 438f69a4c1SPeter Maydell 448f69a4c1SPeter Maydell typedef enum MuscaType { 458f69a4c1SPeter Maydell MUSCA_A, 468f69a4c1SPeter Maydell MUSCA_B1, 478f69a4c1SPeter Maydell } MuscaType; 488f69a4c1SPeter Maydell 49db1015e9SEduardo Habkost struct MuscaMachineClass { 508f69a4c1SPeter Maydell MachineClass parent; 518f69a4c1SPeter Maydell MuscaType type; 528f69a4c1SPeter Maydell uint32_t init_svtor; 538f69a4c1SPeter Maydell int sram_addr_width; 548f69a4c1SPeter Maydell int num_irqs; 5533293e50SPeter Maydell const MPCInfo *mpc_info; 5633293e50SPeter Maydell int num_mpcs; 57db1015e9SEduardo Habkost }; 588f69a4c1SPeter Maydell 59db1015e9SEduardo Habkost struct MuscaMachineState { 608f69a4c1SPeter Maydell MachineState parent; 618f69a4c1SPeter Maydell 628f69a4c1SPeter Maydell ARMSSE sse; 6333293e50SPeter Maydell /* RAM and flash */ 6433293e50SPeter Maydell MemoryRegion ram[MUSCA_MPC_MAX]; 658f69a4c1SPeter Maydell SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX]; 66ae3bc714SPeter Maydell SplitIRQ sec_resp_splitter; 67ae3bc714SPeter Maydell TZPPC ppc[MUSCA_PPC_MAX]; 68ae3bc714SPeter Maydell MemoryRegion container; 69ae3bc714SPeter Maydell UnimplementedDeviceState eflash[2]; 70ae3bc714SPeter Maydell UnimplementedDeviceState qspi; 7133293e50SPeter Maydell TZMPC mpc[MUSCA_MPC_MAX]; 72ae3bc714SPeter Maydell UnimplementedDeviceState mhu[2]; 73ae3bc714SPeter Maydell UnimplementedDeviceState pwm[3]; 74ae3bc714SPeter Maydell UnimplementedDeviceState i2s; 751486f1baSPeter Maydell PL011State uart[2]; 76ae3bc714SPeter Maydell UnimplementedDeviceState i2c[2]; 77ae3bc714SPeter Maydell UnimplementedDeviceState spi; 78ae3bc714SPeter Maydell UnimplementedDeviceState scc; 79ae3bc714SPeter Maydell UnimplementedDeviceState timer; 804db6a761SPeter Maydell PL031State rtc; 81ae3bc714SPeter Maydell UnimplementedDeviceState pvt; 82ae3bc714SPeter Maydell UnimplementedDeviceState sdio; 83ae3bc714SPeter Maydell UnimplementedDeviceState gpio; 8433293e50SPeter Maydell UnimplementedDeviceState cryptoisland; 85db1015e9SEduardo Habkost }; 868f69a4c1SPeter Maydell 878f69a4c1SPeter Maydell #define TYPE_MUSCA_MACHINE "musca" 888f69a4c1SPeter Maydell #define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a") 898f69a4c1SPeter Maydell #define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1") 908f69a4c1SPeter Maydell 91*a489d195SEduardo Habkost OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE) 928f69a4c1SPeter Maydell 938f69a4c1SPeter Maydell /* 948f69a4c1SPeter Maydell * Main SYSCLK frequency in Hz 958f69a4c1SPeter Maydell * TODO this should really be different for the two cores, but we 968f69a4c1SPeter Maydell * don't model that in our SSE-200 model yet. 978f69a4c1SPeter Maydell */ 988f69a4c1SPeter Maydell #define SYSCLK_FRQ 40000000 998f69a4c1SPeter Maydell 1004db6a761SPeter Maydell static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno) 1014db6a761SPeter Maydell { 1024db6a761SPeter Maydell /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */ 1034db6a761SPeter Maydell assert(irqno < MUSCA_NUMIRQ_MAX); 1044db6a761SPeter Maydell 1054db6a761SPeter Maydell return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0); 1064db6a761SPeter Maydell } 1074db6a761SPeter Maydell 108ae3bc714SPeter Maydell /* 109ae3bc714SPeter Maydell * Most of the devices in the Musca board sit behind Peripheral Protection 110ae3bc714SPeter Maydell * Controllers. These data structures define the layout of which devices 111ae3bc714SPeter Maydell * sit behind which PPCs. 112ae3bc714SPeter Maydell * The devfn for each port is a function which creates, configures 113ae3bc714SPeter Maydell * and initializes the device, returning the MemoryRegion which 114ae3bc714SPeter Maydell * needs to be plugged into the downstream end of the PPC port. 115ae3bc714SPeter Maydell */ 116ae3bc714SPeter Maydell typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque, 117ae3bc714SPeter Maydell const char *name, hwaddr size); 118ae3bc714SPeter Maydell 119ae3bc714SPeter Maydell typedef struct PPCPortInfo { 120ae3bc714SPeter Maydell const char *name; 121ae3bc714SPeter Maydell MakeDevFn *devfn; 122ae3bc714SPeter Maydell void *opaque; 123ae3bc714SPeter Maydell hwaddr addr; 124ae3bc714SPeter Maydell hwaddr size; 125ae3bc714SPeter Maydell } PPCPortInfo; 126ae3bc714SPeter Maydell 127ae3bc714SPeter Maydell typedef struct PPCInfo { 128ae3bc714SPeter Maydell const char *name; 129ae3bc714SPeter Maydell PPCPortInfo ports[TZ_NUM_PORTS]; 130ae3bc714SPeter Maydell } PPCInfo; 131ae3bc714SPeter Maydell 132ae3bc714SPeter Maydell static MemoryRegion *make_unimp_dev(MuscaMachineState *mms, 133ae3bc714SPeter Maydell void *opaque, const char *name, hwaddr size) 134ae3bc714SPeter Maydell { 135ae3bc714SPeter Maydell /* 136ae3bc714SPeter Maydell * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE, 137ae3bc714SPeter Maydell * and return a pointer to its MemoryRegion. 138ae3bc714SPeter Maydell */ 139ae3bc714SPeter Maydell UnimplementedDeviceState *uds = opaque; 140ae3bc714SPeter Maydell 1410074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, TYPE_UNIMPLEMENTED_DEVICE); 142ae3bc714SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", name); 143ae3bc714SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", size); 1440074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); 145ae3bc714SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 146ae3bc714SPeter Maydell } 147ae3bc714SPeter Maydell 14833293e50SPeter Maydell typedef enum MPCInfoType { 14933293e50SPeter Maydell MPC_RAM, 15033293e50SPeter Maydell MPC_ROM, 15133293e50SPeter Maydell MPC_CRYPTOISLAND, 15233293e50SPeter Maydell } MPCInfoType; 15333293e50SPeter Maydell 15433293e50SPeter Maydell struct MPCInfo { 15533293e50SPeter Maydell const char *name; 15633293e50SPeter Maydell hwaddr addr; 15733293e50SPeter Maydell hwaddr size; 15833293e50SPeter Maydell MPCInfoType type; 15933293e50SPeter Maydell }; 16033293e50SPeter Maydell 16133293e50SPeter Maydell /* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */ 16233293e50SPeter Maydell static const MPCInfo a_mpc_info[] = { { 16333293e50SPeter Maydell .name = "qspi", 16433293e50SPeter Maydell .type = MPC_ROM, 16533293e50SPeter Maydell .addr = 0x00200000, 16633293e50SPeter Maydell .size = 0x00800000, 16733293e50SPeter Maydell }, { 16833293e50SPeter Maydell .name = "sram", 16933293e50SPeter Maydell .type = MPC_RAM, 17033293e50SPeter Maydell .addr = 0x00000000, 17133293e50SPeter Maydell .size = 0x00200000, 17233293e50SPeter Maydell } 17333293e50SPeter Maydell }; 17433293e50SPeter Maydell 17533293e50SPeter Maydell static const MPCInfo b1_mpc_info[] = { { 17633293e50SPeter Maydell .name = "qspi", 17733293e50SPeter Maydell .type = MPC_ROM, 17833293e50SPeter Maydell .addr = 0x00000000, 17933293e50SPeter Maydell .size = 0x02000000, 18033293e50SPeter Maydell }, { 18133293e50SPeter Maydell .name = "sram", 18233293e50SPeter Maydell .type = MPC_RAM, 18333293e50SPeter Maydell .addr = 0x0a400000, 18433293e50SPeter Maydell .size = 0x00080000, 18533293e50SPeter Maydell }, { 18633293e50SPeter Maydell .name = "eflash0", 18733293e50SPeter Maydell .type = MPC_ROM, 18833293e50SPeter Maydell .addr = 0x0a000000, 18933293e50SPeter Maydell .size = 0x00200000, 19033293e50SPeter Maydell }, { 19133293e50SPeter Maydell .name = "eflash1", 19233293e50SPeter Maydell .type = MPC_ROM, 19333293e50SPeter Maydell .addr = 0x0a200000, 19433293e50SPeter Maydell .size = 0x00200000, 19533293e50SPeter Maydell }, { 19633293e50SPeter Maydell .name = "cryptoisland", 19733293e50SPeter Maydell .type = MPC_CRYPTOISLAND, 19833293e50SPeter Maydell .addr = 0x0a000000, 19933293e50SPeter Maydell .size = 0x00200000, 20033293e50SPeter Maydell } 20133293e50SPeter Maydell }; 20233293e50SPeter Maydell 20333293e50SPeter Maydell static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque, 20433293e50SPeter Maydell const char *name, hwaddr size) 20533293e50SPeter Maydell { 20633293e50SPeter Maydell /* 20733293e50SPeter Maydell * Create an MPC and the RAM or flash behind it. 20833293e50SPeter Maydell * MPC 0: eFlash 0 20933293e50SPeter Maydell * MPC 1: eFlash 1 21033293e50SPeter Maydell * MPC 2: SRAM 21133293e50SPeter Maydell * MPC 3: QSPI flash 21233293e50SPeter Maydell * MPC 4: CryptoIsland 21333293e50SPeter Maydell * For now we implement the flash regions as ROM (ie not programmable) 21433293e50SPeter Maydell * (with their control interface memory regions being unimplemented 21533293e50SPeter Maydell * stubs behind the PPCs). 21633293e50SPeter Maydell * The whole CryptoIsland region behind its MPC is an unimplemented stub. 21733293e50SPeter Maydell */ 21833293e50SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 21933293e50SPeter Maydell TZMPC *mpc = opaque; 22033293e50SPeter Maydell int i = mpc - &mms->mpc[0]; 22133293e50SPeter Maydell MemoryRegion *downstream; 22233293e50SPeter Maydell MemoryRegion *upstream; 22333293e50SPeter Maydell UnimplementedDeviceState *uds; 22433293e50SPeter Maydell char *mpcname; 22533293e50SPeter Maydell const MPCInfo *mpcinfo = mmc->mpc_info; 22633293e50SPeter Maydell 22733293e50SPeter Maydell mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name); 22833293e50SPeter Maydell 22933293e50SPeter Maydell switch (mpcinfo[i].type) { 23033293e50SPeter Maydell case MPC_ROM: 23133293e50SPeter Maydell downstream = &mms->ram[i]; 23233293e50SPeter Maydell memory_region_init_rom(downstream, NULL, mpcinfo[i].name, 23333293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 23433293e50SPeter Maydell break; 23533293e50SPeter Maydell case MPC_RAM: 23633293e50SPeter Maydell downstream = &mms->ram[i]; 23733293e50SPeter Maydell memory_region_init_ram(downstream, NULL, mpcinfo[i].name, 23833293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 23933293e50SPeter Maydell break; 24033293e50SPeter Maydell case MPC_CRYPTOISLAND: 24133293e50SPeter Maydell /* We don't implement the CryptoIsland yet */ 24233293e50SPeter Maydell uds = &mms->cryptoisland; 2430074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, 24433293e50SPeter Maydell TYPE_UNIMPLEMENTED_DEVICE); 24533293e50SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name); 24633293e50SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size); 2470074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); 24833293e50SPeter Maydell downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 24933293e50SPeter Maydell break; 25033293e50SPeter Maydell default: 25133293e50SPeter Maydell g_assert_not_reached(); 25233293e50SPeter Maydell } 25333293e50SPeter Maydell 2540074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC); 2555325cc34SMarkus Armbruster object_property_set_link(OBJECT(mpc), "downstream", OBJECT(downstream), 2565325cc34SMarkus Armbruster &error_fatal); 2570074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal); 25833293e50SPeter Maydell /* Map the upstream end of the MPC into system memory */ 25933293e50SPeter Maydell upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); 26033293e50SPeter Maydell memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream); 26133293e50SPeter Maydell /* and connect its interrupt to the SSE-200 */ 26233293e50SPeter Maydell qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0, 26333293e50SPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->sse), 26433293e50SPeter Maydell "mpcexp_status", i)); 26533293e50SPeter Maydell 26633293e50SPeter Maydell g_free(mpcname); 26733293e50SPeter Maydell /* Return the register interface MR for our caller to map behind the PPC */ 26833293e50SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); 26933293e50SPeter Maydell } 27033293e50SPeter Maydell 2714db6a761SPeter Maydell static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque, 2724db6a761SPeter Maydell const char *name, hwaddr size) 2734db6a761SPeter Maydell { 2744db6a761SPeter Maydell PL031State *rtc = opaque; 2754db6a761SPeter Maydell 2760074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, rtc, TYPE_PL031); 2770074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(rtc), &error_fatal); 2784db6a761SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39)); 2794db6a761SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0); 2804db6a761SPeter Maydell } 2814db6a761SPeter Maydell 2821486f1baSPeter Maydell static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque, 2831486f1baSPeter Maydell const char *name, hwaddr size) 2841486f1baSPeter Maydell { 2851486f1baSPeter Maydell PL011State *uart = opaque; 2861486f1baSPeter Maydell int i = uart - &mms->uart[0]; 2871486f1baSPeter Maydell int irqbase = 7 + i * 6; 2881486f1baSPeter Maydell SysBusDevice *s; 2891486f1baSPeter Maydell 2900074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uart, TYPE_PL011); 2911486f1baSPeter Maydell qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); 2920074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal); 2931486f1baSPeter Maydell s = SYS_BUS_DEVICE(uart); 2941486f1baSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */ 2951486f1baSPeter Maydell sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */ 2961486f1baSPeter Maydell sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */ 2971486f1baSPeter Maydell sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */ 2981486f1baSPeter Maydell sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */ 2991486f1baSPeter Maydell sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */ 3001486f1baSPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0); 3011486f1baSPeter Maydell } 3021486f1baSPeter Maydell 303ae3bc714SPeter Maydell static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque, 304ae3bc714SPeter Maydell const char *name, hwaddr size) 305ae3bc714SPeter Maydell { 306ae3bc714SPeter Maydell /* 307ae3bc714SPeter Maydell * Create the container MemoryRegion for all the devices that live 308ae3bc714SPeter Maydell * behind the Musca-A PPC's single port. These devices don't have a PPC 309ae3bc714SPeter Maydell * port each, but we use the PPCPortInfo struct as a convenient way 310ae3bc714SPeter Maydell * to describe them. Note that addresses here are relative to the base 311ae3bc714SPeter Maydell * address of the PPC port region: 0x40100000, and devices appear both 312ae3bc714SPeter Maydell * at the 0x4... NS region and the 0x5... S region. 313ae3bc714SPeter Maydell */ 314ae3bc714SPeter Maydell int i; 315ae3bc714SPeter Maydell MemoryRegion *container = &mms->container; 316ae3bc714SPeter Maydell 317ae3bc714SPeter Maydell const PPCPortInfo devices[] = { 3181486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 }, 3191486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 }, 320ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 }, 321ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 }, 322ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 }, 323ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 }, 324ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 }, 3254db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 }, 326ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 }, 327ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 }, 328ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 }, 329ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 }, 330ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 }, 331ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 }, 33233293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 }, 33333293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 }, 334ae3bc714SPeter Maydell }; 335ae3bc714SPeter Maydell 336ae3bc714SPeter Maydell memory_region_init(container, OBJECT(mms), "musca-device-container", size); 337ae3bc714SPeter Maydell 338ae3bc714SPeter Maydell for (i = 0; i < ARRAY_SIZE(devices); i++) { 339ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &devices[i]; 340ae3bc714SPeter Maydell MemoryRegion *mr; 341ae3bc714SPeter Maydell 342ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 343ae3bc714SPeter Maydell memory_region_add_subregion(container, pinfo->addr, mr); 344ae3bc714SPeter Maydell } 345ae3bc714SPeter Maydell 346ae3bc714SPeter Maydell return &mms->container; 347ae3bc714SPeter Maydell } 348ae3bc714SPeter Maydell 3498f69a4c1SPeter Maydell static void musca_init(MachineState *machine) 3508f69a4c1SPeter Maydell { 3518f69a4c1SPeter Maydell MuscaMachineState *mms = MUSCA_MACHINE(machine); 3528f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 3538f69a4c1SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(machine); 3548f69a4c1SPeter Maydell MemoryRegion *system_memory = get_system_memory(); 3558f69a4c1SPeter Maydell DeviceState *ssedev; 356ae3bc714SPeter Maydell DeviceState *dev_splitter; 357ae3bc714SPeter Maydell const PPCInfo *ppcs; 358ae3bc714SPeter Maydell int num_ppcs; 3598f69a4c1SPeter Maydell int i; 3608f69a4c1SPeter Maydell 3618f69a4c1SPeter Maydell assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX); 36233293e50SPeter Maydell assert(mmc->num_mpcs <= MUSCA_MPC_MAX); 3638f69a4c1SPeter Maydell 3648f69a4c1SPeter Maydell if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { 3658f69a4c1SPeter Maydell error_report("This board can only be used with CPU %s", 3668f69a4c1SPeter Maydell mc->default_cpu_type); 3678f69a4c1SPeter Maydell exit(1); 3688f69a4c1SPeter Maydell } 3698f69a4c1SPeter Maydell 3700074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), "sse-200", &mms->sse, 3710074fce6SMarkus Armbruster TYPE_SSE200); 3728f69a4c1SPeter Maydell ssedev = DEVICE(&mms->sse); 3735325cc34SMarkus Armbruster object_property_set_link(OBJECT(&mms->sse), "memory", 3745325cc34SMarkus Armbruster OBJECT(system_memory), &error_fatal); 3758f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs); 3768f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor); 3778f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width); 3788f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ); 379a90a862bSPeter Maydell /* 380a90a862bSPeter Maydell * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for 381a90a862bSPeter Maydell * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0. 382a90a862bSPeter Maydell */ 383a90a862bSPeter Maydell if (mmc->type == MUSCA_B1) { 384a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_FPU", true); 385a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_DSP", true); 386a90a862bSPeter Maydell } 3870074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(&mms->sse), &error_fatal); 3888f69a4c1SPeter Maydell 3898f69a4c1SPeter Maydell /* 3908f69a4c1SPeter Maydell * We need to create splitters to feed the IRQ inputs 3918f69a4c1SPeter Maydell * for each CPU in the SSE-200 from each device in the board. 3928f69a4c1SPeter Maydell */ 3938f69a4c1SPeter Maydell for (i = 0; i < mmc->num_irqs; i++) { 3948f69a4c1SPeter Maydell char *name = g_strdup_printf("musca-irq-splitter%d", i); 3958f69a4c1SPeter Maydell SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; 3968f69a4c1SPeter Maydell 3979fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), name, splitter, 3989fc7fc4dSMarkus Armbruster sizeof(*splitter), TYPE_SPLIT_IRQ, 3999fc7fc4dSMarkus Armbruster &error_fatal, NULL); 4008f69a4c1SPeter Maydell g_free(name); 4018f69a4c1SPeter Maydell 4025325cc34SMarkus Armbruster object_property_set_int(OBJECT(splitter), "num-lines", 2, 4038f69a4c1SPeter Maydell &error_fatal); 404ce189ab2SMarkus Armbruster qdev_realize(DEVICE(splitter), NULL, &error_fatal); 4058f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 0, 4068f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i)); 4078f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 1, 4088f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, 4098f69a4c1SPeter Maydell "EXP_CPU1_IRQ", i)); 4108f69a4c1SPeter Maydell } 4118f69a4c1SPeter Maydell 412ae3bc714SPeter Maydell /* 413ae3bc714SPeter Maydell * The sec_resp_cfg output from the SSE-200 must be split into multiple 414ae3bc714SPeter Maydell * lines, one for each of the PPCs we create here. 415ae3bc714SPeter Maydell */ 4169fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), "sec-resp-splitter", 4177840938eSPhilippe Mathieu-Daudé &mms->sec_resp_splitter, 4187840938eSPhilippe Mathieu-Daudé sizeof(mms->sec_resp_splitter), 4197840938eSPhilippe Mathieu-Daudé TYPE_SPLIT_IRQ, &error_fatal, NULL); 4207840938eSPhilippe Mathieu-Daudé 4215325cc34SMarkus Armbruster object_property_set_int(OBJECT(&mms->sec_resp_splitter), "num-lines", 4225325cc34SMarkus Armbruster ARRAY_SIZE(mms->ppc), &error_fatal); 423ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&mms->sec_resp_splitter), NULL, &error_fatal); 424ae3bc714SPeter Maydell dev_splitter = DEVICE(&mms->sec_resp_splitter); 425ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0, 426ae3bc714SPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 427ae3bc714SPeter Maydell 428ae3bc714SPeter Maydell /* 429ae3bc714SPeter Maydell * Most of the devices in the board are behind Peripheral Protection 430ae3bc714SPeter Maydell * Controllers. The required order for initializing things is: 431ae3bc714SPeter Maydell * + initialize the PPC 432ae3bc714SPeter Maydell * + initialize, configure and realize downstream devices 433ae3bc714SPeter Maydell * + connect downstream device MemoryRegions to the PPC 434ae3bc714SPeter Maydell * + realize the PPC 435ae3bc714SPeter Maydell * + map the PPC's MemoryRegions to the places in the address map 436ae3bc714SPeter Maydell * where the downstream devices should appear 437ae3bc714SPeter Maydell * + wire up the PPC's control lines to the SSE object 438ae3bc714SPeter Maydell * 439ae3bc714SPeter Maydell * The PPC mapping differs for the -A and -B1 variants; the -A version 440ae3bc714SPeter Maydell * is much simpler, using only a single port of a single PPC and putting 441ae3bc714SPeter Maydell * all the devices behind that. 442ae3bc714SPeter Maydell */ 443ae3bc714SPeter Maydell const PPCInfo a_ppcs[] = { { 444ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 445ae3bc714SPeter Maydell .ports = { 446ae3bc714SPeter Maydell { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 }, 447ae3bc714SPeter Maydell }, 448ae3bc714SPeter Maydell }, 449ae3bc714SPeter Maydell }; 450ae3bc714SPeter Maydell 451ae3bc714SPeter Maydell /* 452ae3bc714SPeter Maydell * Devices listed with an 0x4.. address appear in both the NS 0x4.. region 453ae3bc714SPeter Maydell * and the 0x5.. S region. Devices listed with an 0x5.. address appear 454ae3bc714SPeter Maydell * only in the S region. 455ae3bc714SPeter Maydell */ 456ae3bc714SPeter Maydell const PPCInfo b1_ppcs[] = { { 457ae3bc714SPeter Maydell .name = "apb_ppcexp0", 458ae3bc714SPeter Maydell .ports = { 459ae3bc714SPeter Maydell { "eflash0", make_unimp_dev, &mms->eflash[0], 460ae3bc714SPeter Maydell 0x52400000, 0x1000 }, 461ae3bc714SPeter Maydell { "eflash1", make_unimp_dev, &mms->eflash[1], 462ae3bc714SPeter Maydell 0x52500000, 0x1000 }, 463ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 }, 46433293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 }, 46533293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 }, 46633293e50SPeter Maydell { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 }, 46733293e50SPeter Maydell { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 }, 468ae3bc714SPeter Maydell { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 }, 469ae3bc714SPeter Maydell { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 }, 470ae3bc714SPeter Maydell { }, /* port 9: unused */ 471ae3bc714SPeter Maydell { }, /* port 10: unused */ 472ae3bc714SPeter Maydell { }, /* port 11: unused */ 473ae3bc714SPeter Maydell { }, /* port 12: unused */ 474ae3bc714SPeter Maydell { }, /* port 13: unused */ 47533293e50SPeter Maydell { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 }, 476ae3bc714SPeter Maydell }, 477ae3bc714SPeter Maydell }, { 478ae3bc714SPeter Maydell .name = "apb_ppcexp1", 479ae3bc714SPeter Maydell .ports = { 480ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 }, 481ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 }, 482ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 }, 483ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 }, 4841486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 }, 4851486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 }, 486ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 }, 487ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 }, 488ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 }, 489ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 }, 490ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 }, 4914db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 }, 492ae3bc714SPeter Maydell { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 }, 493ae3bc714SPeter Maydell { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 }, 494ae3bc714SPeter Maydell }, 495ae3bc714SPeter Maydell }, { 496ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 497ae3bc714SPeter Maydell .ports = { 498ae3bc714SPeter Maydell { }, /* port 0: unused */ 499ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 }, 500ae3bc714SPeter Maydell }, 501ae3bc714SPeter Maydell }, 502ae3bc714SPeter Maydell }; 503ae3bc714SPeter Maydell 504ae3bc714SPeter Maydell switch (mmc->type) { 505ae3bc714SPeter Maydell case MUSCA_A: 506ae3bc714SPeter Maydell ppcs = a_ppcs; 507ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(a_ppcs); 508ae3bc714SPeter Maydell break; 509ae3bc714SPeter Maydell case MUSCA_B1: 510ae3bc714SPeter Maydell ppcs = b1_ppcs; 511ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(b1_ppcs); 512ae3bc714SPeter Maydell break; 513ae3bc714SPeter Maydell default: 514ae3bc714SPeter Maydell g_assert_not_reached(); 515ae3bc714SPeter Maydell } 516ae3bc714SPeter Maydell assert(num_ppcs <= MUSCA_PPC_MAX); 517ae3bc714SPeter Maydell 518ae3bc714SPeter Maydell for (i = 0; i < num_ppcs; i++) { 519ae3bc714SPeter Maydell const PPCInfo *ppcinfo = &ppcs[i]; 520ae3bc714SPeter Maydell TZPPC *ppc = &mms->ppc[i]; 521ae3bc714SPeter Maydell DeviceState *ppcdev; 522ae3bc714SPeter Maydell int port; 523ae3bc714SPeter Maydell char *gpioname; 524ae3bc714SPeter Maydell 5250074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), ppcinfo->name, ppc, 5260074fce6SMarkus Armbruster TYPE_TZ_PPC); 527ae3bc714SPeter Maydell ppcdev = DEVICE(ppc); 528ae3bc714SPeter Maydell 529ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 530ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 531ae3bc714SPeter Maydell MemoryRegion *mr; 532ae3bc714SPeter Maydell char *portname; 533ae3bc714SPeter Maydell 534ae3bc714SPeter Maydell if (!pinfo->devfn) { 535ae3bc714SPeter Maydell continue; 536ae3bc714SPeter Maydell } 537ae3bc714SPeter Maydell 538ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 539ae3bc714SPeter Maydell portname = g_strdup_printf("port[%d]", port); 5405325cc34SMarkus Armbruster object_property_set_link(OBJECT(ppc), portname, OBJECT(mr), 5415325cc34SMarkus Armbruster &error_fatal); 542ae3bc714SPeter Maydell g_free(portname); 543ae3bc714SPeter Maydell } 544ae3bc714SPeter Maydell 5450074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(ppc), &error_fatal); 546ae3bc714SPeter Maydell 547ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 548ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 549ae3bc714SPeter Maydell 550ae3bc714SPeter Maydell if (!pinfo->devfn) { 551ae3bc714SPeter Maydell continue; 552ae3bc714SPeter Maydell } 553ae3bc714SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr); 554ae3bc714SPeter Maydell 555ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name); 556ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 557ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 558ae3bc714SPeter Maydell "cfg_nonsec", 559ae3bc714SPeter Maydell port)); 560ae3bc714SPeter Maydell g_free(gpioname); 561ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_ap", ppcinfo->name); 562ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 563ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 564ae3bc714SPeter Maydell "cfg_ap", port)); 565ae3bc714SPeter Maydell g_free(gpioname); 566ae3bc714SPeter Maydell } 567ae3bc714SPeter Maydell 568ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name); 569ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 570ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 571ae3bc714SPeter Maydell "irq_enable", 0)); 572ae3bc714SPeter Maydell g_free(gpioname); 573ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name); 574ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 575ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 576ae3bc714SPeter Maydell "irq_clear", 0)); 577ae3bc714SPeter Maydell g_free(gpioname); 578ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name); 579ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ppcdev, "irq", 0, 580ae3bc714SPeter Maydell qdev_get_gpio_in_named(ssedev, 581ae3bc714SPeter Maydell gpioname, 0)); 582ae3bc714SPeter Maydell g_free(gpioname); 583ae3bc714SPeter Maydell 584ae3bc714SPeter Maydell qdev_connect_gpio_out(dev_splitter, i, 585ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 586ae3bc714SPeter Maydell "cfg_sec_resp", 0)); 587ae3bc714SPeter Maydell } 588ae3bc714SPeter Maydell 5898f69a4c1SPeter Maydell armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000); 5908f69a4c1SPeter Maydell } 5918f69a4c1SPeter Maydell 5928f69a4c1SPeter Maydell static void musca_class_init(ObjectClass *oc, void *data) 5938f69a4c1SPeter Maydell { 5948f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 5958f69a4c1SPeter Maydell 5968f69a4c1SPeter Maydell mc->default_cpus = 2; 5978f69a4c1SPeter Maydell mc->min_cpus = mc->default_cpus; 5988f69a4c1SPeter Maydell mc->max_cpus = mc->default_cpus; 5998f69a4c1SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"); 6008f69a4c1SPeter Maydell mc->init = musca_init; 6018f69a4c1SPeter Maydell } 6028f69a4c1SPeter Maydell 6038f69a4c1SPeter Maydell static void musca_a_class_init(ObjectClass *oc, void *data) 6048f69a4c1SPeter Maydell { 6058f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6068f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6078f69a4c1SPeter Maydell 6088f69a4c1SPeter Maydell mc->desc = "ARM Musca-A board (dual Cortex-M33)"; 6098f69a4c1SPeter Maydell mmc->type = MUSCA_A; 6108f69a4c1SPeter Maydell mmc->init_svtor = 0x10200000; 6118f69a4c1SPeter Maydell mmc->sram_addr_width = 15; 6128f69a4c1SPeter Maydell mmc->num_irqs = 64; 61333293e50SPeter Maydell mmc->mpc_info = a_mpc_info; 61433293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(a_mpc_info); 6158f69a4c1SPeter Maydell } 6168f69a4c1SPeter Maydell 6178f69a4c1SPeter Maydell static void musca_b1_class_init(ObjectClass *oc, void *data) 6188f69a4c1SPeter Maydell { 6198f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6208f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6218f69a4c1SPeter Maydell 6228f69a4c1SPeter Maydell mc->desc = "ARM Musca-B1 board (dual Cortex-M33)"; 6238f69a4c1SPeter Maydell mmc->type = MUSCA_B1; 6248f69a4c1SPeter Maydell /* 6258f69a4c1SPeter Maydell * This matches the DAPlink firmware which boots from QSPI. There 6268f69a4c1SPeter Maydell * is also a firmware blob which boots from the eFlash, which 6278f69a4c1SPeter Maydell * uses init_svtor = 0x1A000000. QEMU doesn't currently support that, 6288f69a4c1SPeter Maydell * though we could in theory expose a machine property on the command 6298f69a4c1SPeter Maydell * line to allow the user to request eFlash boot. 6308f69a4c1SPeter Maydell */ 6318f69a4c1SPeter Maydell mmc->init_svtor = 0x10000000; 6328f69a4c1SPeter Maydell mmc->sram_addr_width = 17; 6338f69a4c1SPeter Maydell mmc->num_irqs = 96; 63433293e50SPeter Maydell mmc->mpc_info = b1_mpc_info; 63533293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info); 6368f69a4c1SPeter Maydell } 6378f69a4c1SPeter Maydell 6388f69a4c1SPeter Maydell static const TypeInfo musca_info = { 6398f69a4c1SPeter Maydell .name = TYPE_MUSCA_MACHINE, 6408f69a4c1SPeter Maydell .parent = TYPE_MACHINE, 6418f69a4c1SPeter Maydell .abstract = true, 6428f69a4c1SPeter Maydell .instance_size = sizeof(MuscaMachineState), 6438f69a4c1SPeter Maydell .class_size = sizeof(MuscaMachineClass), 6448f69a4c1SPeter Maydell .class_init = musca_class_init, 6458f69a4c1SPeter Maydell }; 6468f69a4c1SPeter Maydell 6478f69a4c1SPeter Maydell static const TypeInfo musca_a_info = { 6488f69a4c1SPeter Maydell .name = TYPE_MUSCA_A_MACHINE, 6498f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6508f69a4c1SPeter Maydell .class_init = musca_a_class_init, 6518f69a4c1SPeter Maydell }; 6528f69a4c1SPeter Maydell 6538f69a4c1SPeter Maydell static const TypeInfo musca_b1_info = { 6548f69a4c1SPeter Maydell .name = TYPE_MUSCA_B1_MACHINE, 6558f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6568f69a4c1SPeter Maydell .class_init = musca_b1_class_init, 6578f69a4c1SPeter Maydell }; 6588f69a4c1SPeter Maydell 6598f69a4c1SPeter Maydell static void musca_machine_init(void) 6608f69a4c1SPeter Maydell { 6618f69a4c1SPeter Maydell type_register_static(&musca_info); 6628f69a4c1SPeter Maydell type_register_static(&musca_a_info); 6638f69a4c1SPeter Maydell type_register_static(&musca_b1_info); 6648f69a4c1SPeter Maydell } 6658f69a4c1SPeter Maydell 6668f69a4c1SPeter Maydell type_init(musca_machine_init); 667