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" 354db6a761SPeter Maydell #include "hw/timer/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 145ae3bc714SPeter Maydell sysbus_init_child_obj(OBJECT(mms), name, uds, 146ae3bc714SPeter Maydell sizeof(UnimplementedDeviceState), 147ae3bc714SPeter Maydell TYPE_UNIMPLEMENTED_DEVICE); 148ae3bc714SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", name); 149ae3bc714SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", size); 150ae3bc714SPeter Maydell object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal); 151ae3bc714SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 152ae3bc714SPeter Maydell } 153ae3bc714SPeter Maydell 15433293e50SPeter Maydell typedef enum MPCInfoType { 15533293e50SPeter Maydell MPC_RAM, 15633293e50SPeter Maydell MPC_ROM, 15733293e50SPeter Maydell MPC_CRYPTOISLAND, 15833293e50SPeter Maydell } MPCInfoType; 15933293e50SPeter Maydell 16033293e50SPeter Maydell struct MPCInfo { 16133293e50SPeter Maydell const char *name; 16233293e50SPeter Maydell hwaddr addr; 16333293e50SPeter Maydell hwaddr size; 16433293e50SPeter Maydell MPCInfoType type; 16533293e50SPeter Maydell }; 16633293e50SPeter Maydell 16733293e50SPeter Maydell /* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */ 16833293e50SPeter Maydell static const MPCInfo a_mpc_info[] = { { 16933293e50SPeter Maydell .name = "qspi", 17033293e50SPeter Maydell .type = MPC_ROM, 17133293e50SPeter Maydell .addr = 0x00200000, 17233293e50SPeter Maydell .size = 0x00800000, 17333293e50SPeter Maydell }, { 17433293e50SPeter Maydell .name = "sram", 17533293e50SPeter Maydell .type = MPC_RAM, 17633293e50SPeter Maydell .addr = 0x00000000, 17733293e50SPeter Maydell .size = 0x00200000, 17833293e50SPeter Maydell } 17933293e50SPeter Maydell }; 18033293e50SPeter Maydell 18133293e50SPeter Maydell static const MPCInfo b1_mpc_info[] = { { 18233293e50SPeter Maydell .name = "qspi", 18333293e50SPeter Maydell .type = MPC_ROM, 18433293e50SPeter Maydell .addr = 0x00000000, 18533293e50SPeter Maydell .size = 0x02000000, 18633293e50SPeter Maydell }, { 18733293e50SPeter Maydell .name = "sram", 18833293e50SPeter Maydell .type = MPC_RAM, 18933293e50SPeter Maydell .addr = 0x0a400000, 19033293e50SPeter Maydell .size = 0x00080000, 19133293e50SPeter Maydell }, { 19233293e50SPeter Maydell .name = "eflash0", 19333293e50SPeter Maydell .type = MPC_ROM, 19433293e50SPeter Maydell .addr = 0x0a000000, 19533293e50SPeter Maydell .size = 0x00200000, 19633293e50SPeter Maydell }, { 19733293e50SPeter Maydell .name = "eflash1", 19833293e50SPeter Maydell .type = MPC_ROM, 19933293e50SPeter Maydell .addr = 0x0a200000, 20033293e50SPeter Maydell .size = 0x00200000, 20133293e50SPeter Maydell }, { 20233293e50SPeter Maydell .name = "cryptoisland", 20333293e50SPeter Maydell .type = MPC_CRYPTOISLAND, 20433293e50SPeter Maydell .addr = 0x0a000000, 20533293e50SPeter Maydell .size = 0x00200000, 20633293e50SPeter Maydell } 20733293e50SPeter Maydell }; 20833293e50SPeter Maydell 20933293e50SPeter Maydell static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque, 21033293e50SPeter Maydell const char *name, hwaddr size) 21133293e50SPeter Maydell { 21233293e50SPeter Maydell /* 21333293e50SPeter Maydell * Create an MPC and the RAM or flash behind it. 21433293e50SPeter Maydell * MPC 0: eFlash 0 21533293e50SPeter Maydell * MPC 1: eFlash 1 21633293e50SPeter Maydell * MPC 2: SRAM 21733293e50SPeter Maydell * MPC 3: QSPI flash 21833293e50SPeter Maydell * MPC 4: CryptoIsland 21933293e50SPeter Maydell * For now we implement the flash regions as ROM (ie not programmable) 22033293e50SPeter Maydell * (with their control interface memory regions being unimplemented 22133293e50SPeter Maydell * stubs behind the PPCs). 22233293e50SPeter Maydell * The whole CryptoIsland region behind its MPC is an unimplemented stub. 22333293e50SPeter Maydell */ 22433293e50SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 22533293e50SPeter Maydell TZMPC *mpc = opaque; 22633293e50SPeter Maydell int i = mpc - &mms->mpc[0]; 22733293e50SPeter Maydell MemoryRegion *downstream; 22833293e50SPeter Maydell MemoryRegion *upstream; 22933293e50SPeter Maydell UnimplementedDeviceState *uds; 23033293e50SPeter Maydell char *mpcname; 23133293e50SPeter Maydell const MPCInfo *mpcinfo = mmc->mpc_info; 23233293e50SPeter Maydell 23333293e50SPeter Maydell mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name); 23433293e50SPeter Maydell 23533293e50SPeter Maydell switch (mpcinfo[i].type) { 23633293e50SPeter Maydell case MPC_ROM: 23733293e50SPeter Maydell downstream = &mms->ram[i]; 23833293e50SPeter Maydell memory_region_init_rom(downstream, NULL, mpcinfo[i].name, 23933293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 24033293e50SPeter Maydell break; 24133293e50SPeter Maydell case MPC_RAM: 24233293e50SPeter Maydell downstream = &mms->ram[i]; 24333293e50SPeter Maydell memory_region_init_ram(downstream, NULL, mpcinfo[i].name, 24433293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 24533293e50SPeter Maydell break; 24633293e50SPeter Maydell case MPC_CRYPTOISLAND: 24733293e50SPeter Maydell /* We don't implement the CryptoIsland yet */ 24833293e50SPeter Maydell uds = &mms->cryptoisland; 24933293e50SPeter Maydell sysbus_init_child_obj(OBJECT(mms), name, uds, 25033293e50SPeter Maydell sizeof(UnimplementedDeviceState), 25133293e50SPeter Maydell TYPE_UNIMPLEMENTED_DEVICE); 25233293e50SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name); 25333293e50SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size); 25433293e50SPeter Maydell object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal); 25533293e50SPeter Maydell downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 25633293e50SPeter Maydell break; 25733293e50SPeter Maydell default: 25833293e50SPeter Maydell g_assert_not_reached(); 25933293e50SPeter Maydell } 26033293e50SPeter Maydell 26133293e50SPeter Maydell sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]), 26233293e50SPeter Maydell TYPE_TZ_MPC); 26333293e50SPeter Maydell object_property_set_link(OBJECT(mpc), OBJECT(downstream), 26433293e50SPeter Maydell "downstream", &error_fatal); 26533293e50SPeter Maydell object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal); 26633293e50SPeter Maydell /* Map the upstream end of the MPC into system memory */ 26733293e50SPeter Maydell upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); 26833293e50SPeter Maydell memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream); 26933293e50SPeter Maydell /* and connect its interrupt to the SSE-200 */ 27033293e50SPeter Maydell qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0, 27133293e50SPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->sse), 27233293e50SPeter Maydell "mpcexp_status", i)); 27333293e50SPeter Maydell 27433293e50SPeter Maydell g_free(mpcname); 27533293e50SPeter Maydell /* Return the register interface MR for our caller to map behind the PPC */ 27633293e50SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); 27733293e50SPeter Maydell } 27833293e50SPeter Maydell 2794db6a761SPeter Maydell static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque, 2804db6a761SPeter Maydell const char *name, hwaddr size) 2814db6a761SPeter Maydell { 2824db6a761SPeter Maydell PL031State *rtc = opaque; 2834db6a761SPeter Maydell 2844db6a761SPeter Maydell sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031); 2854db6a761SPeter Maydell object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal); 2864db6a761SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39)); 2874db6a761SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0); 2884db6a761SPeter Maydell } 2894db6a761SPeter Maydell 2901486f1baSPeter Maydell static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque, 2911486f1baSPeter Maydell const char *name, hwaddr size) 2921486f1baSPeter Maydell { 2931486f1baSPeter Maydell PL011State *uart = opaque; 2941486f1baSPeter Maydell int i = uart - &mms->uart[0]; 2951486f1baSPeter Maydell int irqbase = 7 + i * 6; 2961486f1baSPeter Maydell SysBusDevice *s; 2971486f1baSPeter Maydell 2981486f1baSPeter Maydell sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]), 2991486f1baSPeter Maydell TYPE_PL011); 3001486f1baSPeter Maydell qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); 3011486f1baSPeter Maydell object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal); 3021486f1baSPeter Maydell s = SYS_BUS_DEVICE(uart); 3031486f1baSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */ 3041486f1baSPeter Maydell sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */ 3051486f1baSPeter Maydell sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */ 3061486f1baSPeter Maydell sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */ 3071486f1baSPeter Maydell sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */ 3081486f1baSPeter Maydell sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */ 3091486f1baSPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0); 3101486f1baSPeter Maydell } 3111486f1baSPeter Maydell 312ae3bc714SPeter Maydell static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque, 313ae3bc714SPeter Maydell const char *name, hwaddr size) 314ae3bc714SPeter Maydell { 315ae3bc714SPeter Maydell /* 316ae3bc714SPeter Maydell * Create the container MemoryRegion for all the devices that live 317ae3bc714SPeter Maydell * behind the Musca-A PPC's single port. These devices don't have a PPC 318ae3bc714SPeter Maydell * port each, but we use the PPCPortInfo struct as a convenient way 319ae3bc714SPeter Maydell * to describe them. Note that addresses here are relative to the base 320ae3bc714SPeter Maydell * address of the PPC port region: 0x40100000, and devices appear both 321ae3bc714SPeter Maydell * at the 0x4... NS region and the 0x5... S region. 322ae3bc714SPeter Maydell */ 323ae3bc714SPeter Maydell int i; 324ae3bc714SPeter Maydell MemoryRegion *container = &mms->container; 325ae3bc714SPeter Maydell 326ae3bc714SPeter Maydell const PPCPortInfo devices[] = { 3271486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 }, 3281486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 }, 329ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 }, 330ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 }, 331ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 }, 332ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 }, 333ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 }, 3344db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 }, 335ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 }, 336ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 }, 337ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 }, 338ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 }, 339ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 }, 340ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 }, 34133293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 }, 34233293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 }, 343ae3bc714SPeter Maydell }; 344ae3bc714SPeter Maydell 345ae3bc714SPeter Maydell memory_region_init(container, OBJECT(mms), "musca-device-container", size); 346ae3bc714SPeter Maydell 347ae3bc714SPeter Maydell for (i = 0; i < ARRAY_SIZE(devices); i++) { 348ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &devices[i]; 349ae3bc714SPeter Maydell MemoryRegion *mr; 350ae3bc714SPeter Maydell 351ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 352ae3bc714SPeter Maydell memory_region_add_subregion(container, pinfo->addr, mr); 353ae3bc714SPeter Maydell } 354ae3bc714SPeter Maydell 355ae3bc714SPeter Maydell return &mms->container; 356ae3bc714SPeter Maydell } 357ae3bc714SPeter Maydell 3588f69a4c1SPeter Maydell static void musca_init(MachineState *machine) 3598f69a4c1SPeter Maydell { 3608f69a4c1SPeter Maydell MuscaMachineState *mms = MUSCA_MACHINE(machine); 3618f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 3628f69a4c1SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(machine); 3638f69a4c1SPeter Maydell MemoryRegion *system_memory = get_system_memory(); 3648f69a4c1SPeter Maydell DeviceState *ssedev; 365ae3bc714SPeter Maydell DeviceState *dev_splitter; 366ae3bc714SPeter Maydell const PPCInfo *ppcs; 367ae3bc714SPeter Maydell int num_ppcs; 3688f69a4c1SPeter Maydell int i; 3698f69a4c1SPeter Maydell 3708f69a4c1SPeter Maydell assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX); 37133293e50SPeter Maydell assert(mmc->num_mpcs <= MUSCA_MPC_MAX); 3728f69a4c1SPeter Maydell 3738f69a4c1SPeter Maydell if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { 3748f69a4c1SPeter Maydell error_report("This board can only be used with CPU %s", 3758f69a4c1SPeter Maydell mc->default_cpu_type); 3768f69a4c1SPeter Maydell exit(1); 3778f69a4c1SPeter Maydell } 3788f69a4c1SPeter Maydell 3798f69a4c1SPeter Maydell sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse, 3808f69a4c1SPeter Maydell sizeof(mms->sse), TYPE_SSE200); 3818f69a4c1SPeter Maydell ssedev = DEVICE(&mms->sse); 3828f69a4c1SPeter Maydell object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory), 3838f69a4c1SPeter Maydell "memory", &error_fatal); 3848f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs); 3858f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor); 3868f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width); 3878f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ); 388*a90a862bSPeter Maydell /* 389*a90a862bSPeter Maydell * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for 390*a90a862bSPeter Maydell * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0. 391*a90a862bSPeter Maydell */ 392*a90a862bSPeter Maydell if (mmc->type == MUSCA_B1) { 393*a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_FPU", true); 394*a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_DSP", true); 395*a90a862bSPeter Maydell } 3968f69a4c1SPeter Maydell object_property_set_bool(OBJECT(&mms->sse), true, "realized", 3978f69a4c1SPeter Maydell &error_fatal); 3988f69a4c1SPeter Maydell 3998f69a4c1SPeter Maydell /* 4008f69a4c1SPeter Maydell * We need to create splitters to feed the IRQ inputs 4018f69a4c1SPeter Maydell * for each CPU in the SSE-200 from each device in the board. 4028f69a4c1SPeter Maydell */ 4038f69a4c1SPeter Maydell for (i = 0; i < mmc->num_irqs; i++) { 4048f69a4c1SPeter Maydell char *name = g_strdup_printf("musca-irq-splitter%d", i); 4058f69a4c1SPeter Maydell SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; 4068f69a4c1SPeter Maydell 4078f69a4c1SPeter Maydell object_initialize_child(OBJECT(machine), name, 4088f69a4c1SPeter Maydell splitter, sizeof(*splitter), 4098f69a4c1SPeter Maydell TYPE_SPLIT_IRQ, &error_fatal, NULL); 4108f69a4c1SPeter Maydell g_free(name); 4118f69a4c1SPeter Maydell 4128f69a4c1SPeter Maydell object_property_set_int(OBJECT(splitter), 2, "num-lines", 4138f69a4c1SPeter Maydell &error_fatal); 4148f69a4c1SPeter Maydell object_property_set_bool(OBJECT(splitter), true, "realized", 4158f69a4c1SPeter Maydell &error_fatal); 4168f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 0, 4178f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i)); 4188f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 1, 4198f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, 4208f69a4c1SPeter Maydell "EXP_CPU1_IRQ", i)); 4218f69a4c1SPeter Maydell } 4228f69a4c1SPeter Maydell 423ae3bc714SPeter Maydell /* 424ae3bc714SPeter Maydell * The sec_resp_cfg output from the SSE-200 must be split into multiple 425ae3bc714SPeter Maydell * lines, one for each of the PPCs we create here. 426ae3bc714SPeter Maydell */ 427ae3bc714SPeter Maydell object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter), 428ae3bc714SPeter Maydell TYPE_SPLIT_IRQ); 429ae3bc714SPeter Maydell object_property_add_child(OBJECT(machine), "sec-resp-splitter", 430ae3bc714SPeter Maydell OBJECT(&mms->sec_resp_splitter), &error_fatal); 431ae3bc714SPeter Maydell object_property_set_int(OBJECT(&mms->sec_resp_splitter), 432ae3bc714SPeter Maydell ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal); 433ae3bc714SPeter Maydell object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true, 434ae3bc714SPeter Maydell "realized", &error_fatal); 435ae3bc714SPeter Maydell dev_splitter = DEVICE(&mms->sec_resp_splitter); 436ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0, 437ae3bc714SPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 438ae3bc714SPeter Maydell 439ae3bc714SPeter Maydell /* 440ae3bc714SPeter Maydell * Most of the devices in the board are behind Peripheral Protection 441ae3bc714SPeter Maydell * Controllers. The required order for initializing things is: 442ae3bc714SPeter Maydell * + initialize the PPC 443ae3bc714SPeter Maydell * + initialize, configure and realize downstream devices 444ae3bc714SPeter Maydell * + connect downstream device MemoryRegions to the PPC 445ae3bc714SPeter Maydell * + realize the PPC 446ae3bc714SPeter Maydell * + map the PPC's MemoryRegions to the places in the address map 447ae3bc714SPeter Maydell * where the downstream devices should appear 448ae3bc714SPeter Maydell * + wire up the PPC's control lines to the SSE object 449ae3bc714SPeter Maydell * 450ae3bc714SPeter Maydell * The PPC mapping differs for the -A and -B1 variants; the -A version 451ae3bc714SPeter Maydell * is much simpler, using only a single port of a single PPC and putting 452ae3bc714SPeter Maydell * all the devices behind that. 453ae3bc714SPeter Maydell */ 454ae3bc714SPeter Maydell const PPCInfo a_ppcs[] = { { 455ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 456ae3bc714SPeter Maydell .ports = { 457ae3bc714SPeter Maydell { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 }, 458ae3bc714SPeter Maydell }, 459ae3bc714SPeter Maydell }, 460ae3bc714SPeter Maydell }; 461ae3bc714SPeter Maydell 462ae3bc714SPeter Maydell /* 463ae3bc714SPeter Maydell * Devices listed with an 0x4.. address appear in both the NS 0x4.. region 464ae3bc714SPeter Maydell * and the 0x5.. S region. Devices listed with an 0x5.. address appear 465ae3bc714SPeter Maydell * only in the S region. 466ae3bc714SPeter Maydell */ 467ae3bc714SPeter Maydell const PPCInfo b1_ppcs[] = { { 468ae3bc714SPeter Maydell .name = "apb_ppcexp0", 469ae3bc714SPeter Maydell .ports = { 470ae3bc714SPeter Maydell { "eflash0", make_unimp_dev, &mms->eflash[0], 471ae3bc714SPeter Maydell 0x52400000, 0x1000 }, 472ae3bc714SPeter Maydell { "eflash1", make_unimp_dev, &mms->eflash[1], 473ae3bc714SPeter Maydell 0x52500000, 0x1000 }, 474ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 }, 47533293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 }, 47633293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 }, 47733293e50SPeter Maydell { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 }, 47833293e50SPeter Maydell { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 }, 479ae3bc714SPeter Maydell { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 }, 480ae3bc714SPeter Maydell { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 }, 481ae3bc714SPeter Maydell { }, /* port 9: unused */ 482ae3bc714SPeter Maydell { }, /* port 10: unused */ 483ae3bc714SPeter Maydell { }, /* port 11: unused */ 484ae3bc714SPeter Maydell { }, /* port 12: unused */ 485ae3bc714SPeter Maydell { }, /* port 13: unused */ 48633293e50SPeter Maydell { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 }, 487ae3bc714SPeter Maydell }, 488ae3bc714SPeter Maydell }, { 489ae3bc714SPeter Maydell .name = "apb_ppcexp1", 490ae3bc714SPeter Maydell .ports = { 491ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 }, 492ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 }, 493ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 }, 494ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 }, 4951486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 }, 4961486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 }, 497ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 }, 498ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 }, 499ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 }, 500ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 }, 501ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 }, 5024db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 }, 503ae3bc714SPeter Maydell { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 }, 504ae3bc714SPeter Maydell { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 }, 505ae3bc714SPeter Maydell }, 506ae3bc714SPeter Maydell }, { 507ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 508ae3bc714SPeter Maydell .ports = { 509ae3bc714SPeter Maydell { }, /* port 0: unused */ 510ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 }, 511ae3bc714SPeter Maydell }, 512ae3bc714SPeter Maydell }, 513ae3bc714SPeter Maydell }; 514ae3bc714SPeter Maydell 515ae3bc714SPeter Maydell switch (mmc->type) { 516ae3bc714SPeter Maydell case MUSCA_A: 517ae3bc714SPeter Maydell ppcs = a_ppcs; 518ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(a_ppcs); 519ae3bc714SPeter Maydell break; 520ae3bc714SPeter Maydell case MUSCA_B1: 521ae3bc714SPeter Maydell ppcs = b1_ppcs; 522ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(b1_ppcs); 523ae3bc714SPeter Maydell break; 524ae3bc714SPeter Maydell default: 525ae3bc714SPeter Maydell g_assert_not_reached(); 526ae3bc714SPeter Maydell } 527ae3bc714SPeter Maydell assert(num_ppcs <= MUSCA_PPC_MAX); 528ae3bc714SPeter Maydell 529ae3bc714SPeter Maydell for (i = 0; i < num_ppcs; i++) { 530ae3bc714SPeter Maydell const PPCInfo *ppcinfo = &ppcs[i]; 531ae3bc714SPeter Maydell TZPPC *ppc = &mms->ppc[i]; 532ae3bc714SPeter Maydell DeviceState *ppcdev; 533ae3bc714SPeter Maydell int port; 534ae3bc714SPeter Maydell char *gpioname; 535ae3bc714SPeter Maydell 536ae3bc714SPeter Maydell sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc, 537ae3bc714SPeter Maydell sizeof(TZPPC), TYPE_TZ_PPC); 538ae3bc714SPeter Maydell ppcdev = DEVICE(ppc); 539ae3bc714SPeter Maydell 540ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 541ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 542ae3bc714SPeter Maydell MemoryRegion *mr; 543ae3bc714SPeter Maydell char *portname; 544ae3bc714SPeter Maydell 545ae3bc714SPeter Maydell if (!pinfo->devfn) { 546ae3bc714SPeter Maydell continue; 547ae3bc714SPeter Maydell } 548ae3bc714SPeter Maydell 549ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 550ae3bc714SPeter Maydell portname = g_strdup_printf("port[%d]", port); 551ae3bc714SPeter Maydell object_property_set_link(OBJECT(ppc), OBJECT(mr), 552ae3bc714SPeter Maydell portname, &error_fatal); 553ae3bc714SPeter Maydell g_free(portname); 554ae3bc714SPeter Maydell } 555ae3bc714SPeter Maydell 556ae3bc714SPeter Maydell object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal); 557ae3bc714SPeter Maydell 558ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 559ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 560ae3bc714SPeter Maydell 561ae3bc714SPeter Maydell if (!pinfo->devfn) { 562ae3bc714SPeter Maydell continue; 563ae3bc714SPeter Maydell } 564ae3bc714SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr); 565ae3bc714SPeter Maydell 566ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name); 567ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 568ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 569ae3bc714SPeter Maydell "cfg_nonsec", 570ae3bc714SPeter Maydell port)); 571ae3bc714SPeter Maydell g_free(gpioname); 572ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_ap", ppcinfo->name); 573ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 574ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 575ae3bc714SPeter Maydell "cfg_ap", port)); 576ae3bc714SPeter Maydell g_free(gpioname); 577ae3bc714SPeter Maydell } 578ae3bc714SPeter Maydell 579ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name); 580ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 581ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 582ae3bc714SPeter Maydell "irq_enable", 0)); 583ae3bc714SPeter Maydell g_free(gpioname); 584ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name); 585ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 586ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 587ae3bc714SPeter Maydell "irq_clear", 0)); 588ae3bc714SPeter Maydell g_free(gpioname); 589ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name); 590ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ppcdev, "irq", 0, 591ae3bc714SPeter Maydell qdev_get_gpio_in_named(ssedev, 592ae3bc714SPeter Maydell gpioname, 0)); 593ae3bc714SPeter Maydell g_free(gpioname); 594ae3bc714SPeter Maydell 595ae3bc714SPeter Maydell qdev_connect_gpio_out(dev_splitter, i, 596ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 597ae3bc714SPeter Maydell "cfg_sec_resp", 0)); 598ae3bc714SPeter Maydell } 599ae3bc714SPeter Maydell 6008f69a4c1SPeter Maydell armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000); 6018f69a4c1SPeter Maydell } 6028f69a4c1SPeter Maydell 6038f69a4c1SPeter Maydell static void musca_class_init(ObjectClass *oc, void *data) 6048f69a4c1SPeter Maydell { 6058f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6068f69a4c1SPeter Maydell 6078f69a4c1SPeter Maydell mc->default_cpus = 2; 6088f69a4c1SPeter Maydell mc->min_cpus = mc->default_cpus; 6098f69a4c1SPeter Maydell mc->max_cpus = mc->default_cpus; 6108f69a4c1SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"); 6118f69a4c1SPeter Maydell mc->init = musca_init; 6128f69a4c1SPeter Maydell } 6138f69a4c1SPeter Maydell 6148f69a4c1SPeter Maydell static void musca_a_class_init(ObjectClass *oc, void *data) 6158f69a4c1SPeter Maydell { 6168f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6178f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6188f69a4c1SPeter Maydell 6198f69a4c1SPeter Maydell mc->desc = "ARM Musca-A board (dual Cortex-M33)"; 6208f69a4c1SPeter Maydell mmc->type = MUSCA_A; 6218f69a4c1SPeter Maydell mmc->init_svtor = 0x10200000; 6228f69a4c1SPeter Maydell mmc->sram_addr_width = 15; 6238f69a4c1SPeter Maydell mmc->num_irqs = 64; 62433293e50SPeter Maydell mmc->mpc_info = a_mpc_info; 62533293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(a_mpc_info); 6268f69a4c1SPeter Maydell } 6278f69a4c1SPeter Maydell 6288f69a4c1SPeter Maydell static void musca_b1_class_init(ObjectClass *oc, void *data) 6298f69a4c1SPeter Maydell { 6308f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6318f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6328f69a4c1SPeter Maydell 6338f69a4c1SPeter Maydell mc->desc = "ARM Musca-B1 board (dual Cortex-M33)"; 6348f69a4c1SPeter Maydell mmc->type = MUSCA_B1; 6358f69a4c1SPeter Maydell /* 6368f69a4c1SPeter Maydell * This matches the DAPlink firmware which boots from QSPI. There 6378f69a4c1SPeter Maydell * is also a firmware blob which boots from the eFlash, which 6388f69a4c1SPeter Maydell * uses init_svtor = 0x1A000000. QEMU doesn't currently support that, 6398f69a4c1SPeter Maydell * though we could in theory expose a machine property on the command 6408f69a4c1SPeter Maydell * line to allow the user to request eFlash boot. 6418f69a4c1SPeter Maydell */ 6428f69a4c1SPeter Maydell mmc->init_svtor = 0x10000000; 6438f69a4c1SPeter Maydell mmc->sram_addr_width = 17; 6448f69a4c1SPeter Maydell mmc->num_irqs = 96; 64533293e50SPeter Maydell mmc->mpc_info = b1_mpc_info; 64633293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info); 6478f69a4c1SPeter Maydell } 6488f69a4c1SPeter Maydell 6498f69a4c1SPeter Maydell static const TypeInfo musca_info = { 6508f69a4c1SPeter Maydell .name = TYPE_MUSCA_MACHINE, 6518f69a4c1SPeter Maydell .parent = TYPE_MACHINE, 6528f69a4c1SPeter Maydell .abstract = true, 6538f69a4c1SPeter Maydell .instance_size = sizeof(MuscaMachineState), 6548f69a4c1SPeter Maydell .class_size = sizeof(MuscaMachineClass), 6558f69a4c1SPeter Maydell .class_init = musca_class_init, 6568f69a4c1SPeter Maydell }; 6578f69a4c1SPeter Maydell 6588f69a4c1SPeter Maydell static const TypeInfo musca_a_info = { 6598f69a4c1SPeter Maydell .name = TYPE_MUSCA_A_MACHINE, 6608f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6618f69a4c1SPeter Maydell .class_init = musca_a_class_init, 6628f69a4c1SPeter Maydell }; 6638f69a4c1SPeter Maydell 6648f69a4c1SPeter Maydell static const TypeInfo musca_b1_info = { 6658f69a4c1SPeter Maydell .name = TYPE_MUSCA_B1_MACHINE, 6668f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6678f69a4c1SPeter Maydell .class_init = musca_b1_class_init, 6688f69a4c1SPeter Maydell }; 6698f69a4c1SPeter Maydell 6708f69a4c1SPeter Maydell static void musca_machine_init(void) 6718f69a4c1SPeter Maydell { 6728f69a4c1SPeter Maydell type_register_static(&musca_info); 6738f69a4c1SPeter Maydell type_register_static(&musca_a_info); 6748f69a4c1SPeter Maydell type_register_static(&musca_b1_info); 6758f69a4c1SPeter Maydell } 6768f69a4c1SPeter Maydell 6778f69a4c1SPeter Maydell type_init(musca_machine_init); 678