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" 36*fd630cdaSPeter Maydell #include "hw/qdev-clock.h" 37db1015e9SEduardo Habkost #include "qom/object.h" 388f69a4c1SPeter Maydell 398f69a4c1SPeter Maydell #define MUSCA_NUMIRQ_MAX 96 40ae3bc714SPeter Maydell #define MUSCA_PPC_MAX 3 4133293e50SPeter Maydell #define MUSCA_MPC_MAX 5 4233293e50SPeter Maydell 4333293e50SPeter Maydell typedef struct MPCInfo MPCInfo; 448f69a4c1SPeter Maydell 458f69a4c1SPeter Maydell typedef enum MuscaType { 468f69a4c1SPeter Maydell MUSCA_A, 478f69a4c1SPeter Maydell MUSCA_B1, 488f69a4c1SPeter Maydell } MuscaType; 498f69a4c1SPeter Maydell 50db1015e9SEduardo Habkost struct MuscaMachineClass { 518f69a4c1SPeter Maydell MachineClass parent; 528f69a4c1SPeter Maydell MuscaType type; 538f69a4c1SPeter Maydell uint32_t init_svtor; 548f69a4c1SPeter Maydell int sram_addr_width; 558f69a4c1SPeter Maydell int num_irqs; 5633293e50SPeter Maydell const MPCInfo *mpc_info; 5733293e50SPeter Maydell int num_mpcs; 58db1015e9SEduardo Habkost }; 598f69a4c1SPeter Maydell 60db1015e9SEduardo Habkost struct MuscaMachineState { 618f69a4c1SPeter Maydell MachineState parent; 628f69a4c1SPeter Maydell 638f69a4c1SPeter Maydell ARMSSE sse; 6433293e50SPeter Maydell /* RAM and flash */ 6533293e50SPeter Maydell MemoryRegion ram[MUSCA_MPC_MAX]; 668f69a4c1SPeter Maydell SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX]; 67ae3bc714SPeter Maydell SplitIRQ sec_resp_splitter; 68ae3bc714SPeter Maydell TZPPC ppc[MUSCA_PPC_MAX]; 69ae3bc714SPeter Maydell MemoryRegion container; 70ae3bc714SPeter Maydell UnimplementedDeviceState eflash[2]; 71ae3bc714SPeter Maydell UnimplementedDeviceState qspi; 7233293e50SPeter Maydell TZMPC mpc[MUSCA_MPC_MAX]; 73ae3bc714SPeter Maydell UnimplementedDeviceState mhu[2]; 74ae3bc714SPeter Maydell UnimplementedDeviceState pwm[3]; 75ae3bc714SPeter Maydell UnimplementedDeviceState i2s; 761486f1baSPeter Maydell PL011State uart[2]; 77ae3bc714SPeter Maydell UnimplementedDeviceState i2c[2]; 78ae3bc714SPeter Maydell UnimplementedDeviceState spi; 79ae3bc714SPeter Maydell UnimplementedDeviceState scc; 80ae3bc714SPeter Maydell UnimplementedDeviceState timer; 814db6a761SPeter Maydell PL031State rtc; 82ae3bc714SPeter Maydell UnimplementedDeviceState pvt; 83ae3bc714SPeter Maydell UnimplementedDeviceState sdio; 84ae3bc714SPeter Maydell UnimplementedDeviceState gpio; 8533293e50SPeter Maydell UnimplementedDeviceState cryptoisland; 86*fd630cdaSPeter Maydell Clock *sysclk; 87*fd630cdaSPeter Maydell Clock *s32kclk; 88db1015e9SEduardo Habkost }; 898f69a4c1SPeter Maydell 908f69a4c1SPeter Maydell #define TYPE_MUSCA_MACHINE "musca" 918f69a4c1SPeter Maydell #define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a") 928f69a4c1SPeter Maydell #define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1") 938f69a4c1SPeter Maydell 94a489d195SEduardo Habkost OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE) 958f69a4c1SPeter Maydell 968f69a4c1SPeter Maydell /* 978f69a4c1SPeter Maydell * Main SYSCLK frequency in Hz 988f69a4c1SPeter Maydell * TODO this should really be different for the two cores, but we 998f69a4c1SPeter Maydell * don't model that in our SSE-200 model yet. 1008f69a4c1SPeter Maydell */ 1018f69a4c1SPeter Maydell #define SYSCLK_FRQ 40000000 102*fd630cdaSPeter Maydell /* Slow 32Khz S32KCLK frequency in Hz */ 103*fd630cdaSPeter Maydell #define S32KCLK_FRQ (32 * 1000) 1048f69a4c1SPeter Maydell 1054db6a761SPeter Maydell static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno) 1064db6a761SPeter Maydell { 1074db6a761SPeter Maydell /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */ 1084db6a761SPeter Maydell assert(irqno < MUSCA_NUMIRQ_MAX); 1094db6a761SPeter Maydell 1104db6a761SPeter Maydell return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0); 1114db6a761SPeter Maydell } 1124db6a761SPeter Maydell 113ae3bc714SPeter Maydell /* 114ae3bc714SPeter Maydell * Most of the devices in the Musca board sit behind Peripheral Protection 115ae3bc714SPeter Maydell * Controllers. These data structures define the layout of which devices 116ae3bc714SPeter Maydell * sit behind which PPCs. 117ae3bc714SPeter Maydell * The devfn for each port is a function which creates, configures 118ae3bc714SPeter Maydell * and initializes the device, returning the MemoryRegion which 119ae3bc714SPeter Maydell * needs to be plugged into the downstream end of the PPC port. 120ae3bc714SPeter Maydell */ 121ae3bc714SPeter Maydell typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque, 122ae3bc714SPeter Maydell const char *name, hwaddr size); 123ae3bc714SPeter Maydell 124ae3bc714SPeter Maydell typedef struct PPCPortInfo { 125ae3bc714SPeter Maydell const char *name; 126ae3bc714SPeter Maydell MakeDevFn *devfn; 127ae3bc714SPeter Maydell void *opaque; 128ae3bc714SPeter Maydell hwaddr addr; 129ae3bc714SPeter Maydell hwaddr size; 130ae3bc714SPeter Maydell } PPCPortInfo; 131ae3bc714SPeter Maydell 132ae3bc714SPeter Maydell typedef struct PPCInfo { 133ae3bc714SPeter Maydell const char *name; 134ae3bc714SPeter Maydell PPCPortInfo ports[TZ_NUM_PORTS]; 135ae3bc714SPeter Maydell } PPCInfo; 136ae3bc714SPeter Maydell 137ae3bc714SPeter Maydell static MemoryRegion *make_unimp_dev(MuscaMachineState *mms, 138ae3bc714SPeter Maydell void *opaque, const char *name, hwaddr size) 139ae3bc714SPeter Maydell { 140ae3bc714SPeter Maydell /* 141ae3bc714SPeter Maydell * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE, 142ae3bc714SPeter Maydell * and return a pointer to its MemoryRegion. 143ae3bc714SPeter Maydell */ 144ae3bc714SPeter Maydell UnimplementedDeviceState *uds = opaque; 145ae3bc714SPeter Maydell 1460074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, TYPE_UNIMPLEMENTED_DEVICE); 147ae3bc714SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", name); 148ae3bc714SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", size); 1490074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); 150ae3bc714SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 151ae3bc714SPeter Maydell } 152ae3bc714SPeter Maydell 15333293e50SPeter Maydell typedef enum MPCInfoType { 15433293e50SPeter Maydell MPC_RAM, 15533293e50SPeter Maydell MPC_ROM, 15633293e50SPeter Maydell MPC_CRYPTOISLAND, 15733293e50SPeter Maydell } MPCInfoType; 15833293e50SPeter Maydell 15933293e50SPeter Maydell struct MPCInfo { 16033293e50SPeter Maydell const char *name; 16133293e50SPeter Maydell hwaddr addr; 16233293e50SPeter Maydell hwaddr size; 16333293e50SPeter Maydell MPCInfoType type; 16433293e50SPeter Maydell }; 16533293e50SPeter Maydell 16633293e50SPeter Maydell /* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */ 16733293e50SPeter Maydell static const MPCInfo a_mpc_info[] = { { 16833293e50SPeter Maydell .name = "qspi", 16933293e50SPeter Maydell .type = MPC_ROM, 17033293e50SPeter Maydell .addr = 0x00200000, 17133293e50SPeter Maydell .size = 0x00800000, 17233293e50SPeter Maydell }, { 17333293e50SPeter Maydell .name = "sram", 17433293e50SPeter Maydell .type = MPC_RAM, 17533293e50SPeter Maydell .addr = 0x00000000, 17633293e50SPeter Maydell .size = 0x00200000, 17733293e50SPeter Maydell } 17833293e50SPeter Maydell }; 17933293e50SPeter Maydell 18033293e50SPeter Maydell static const MPCInfo b1_mpc_info[] = { { 18133293e50SPeter Maydell .name = "qspi", 18233293e50SPeter Maydell .type = MPC_ROM, 18333293e50SPeter Maydell .addr = 0x00000000, 18433293e50SPeter Maydell .size = 0x02000000, 18533293e50SPeter Maydell }, { 18633293e50SPeter Maydell .name = "sram", 18733293e50SPeter Maydell .type = MPC_RAM, 18833293e50SPeter Maydell .addr = 0x0a400000, 18933293e50SPeter Maydell .size = 0x00080000, 19033293e50SPeter Maydell }, { 19133293e50SPeter Maydell .name = "eflash0", 19233293e50SPeter Maydell .type = MPC_ROM, 19333293e50SPeter Maydell .addr = 0x0a000000, 19433293e50SPeter Maydell .size = 0x00200000, 19533293e50SPeter Maydell }, { 19633293e50SPeter Maydell .name = "eflash1", 19733293e50SPeter Maydell .type = MPC_ROM, 19833293e50SPeter Maydell .addr = 0x0a200000, 19933293e50SPeter Maydell .size = 0x00200000, 20033293e50SPeter Maydell }, { 20133293e50SPeter Maydell .name = "cryptoisland", 20233293e50SPeter Maydell .type = MPC_CRYPTOISLAND, 20333293e50SPeter Maydell .addr = 0x0a000000, 20433293e50SPeter Maydell .size = 0x00200000, 20533293e50SPeter Maydell } 20633293e50SPeter Maydell }; 20733293e50SPeter Maydell 20833293e50SPeter Maydell static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque, 20933293e50SPeter Maydell const char *name, hwaddr size) 21033293e50SPeter Maydell { 21133293e50SPeter Maydell /* 21233293e50SPeter Maydell * Create an MPC and the RAM or flash behind it. 21333293e50SPeter Maydell * MPC 0: eFlash 0 21433293e50SPeter Maydell * MPC 1: eFlash 1 21533293e50SPeter Maydell * MPC 2: SRAM 21633293e50SPeter Maydell * MPC 3: QSPI flash 21733293e50SPeter Maydell * MPC 4: CryptoIsland 21833293e50SPeter Maydell * For now we implement the flash regions as ROM (ie not programmable) 21933293e50SPeter Maydell * (with their control interface memory regions being unimplemented 22033293e50SPeter Maydell * stubs behind the PPCs). 22133293e50SPeter Maydell * The whole CryptoIsland region behind its MPC is an unimplemented stub. 22233293e50SPeter Maydell */ 22333293e50SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 22433293e50SPeter Maydell TZMPC *mpc = opaque; 22533293e50SPeter Maydell int i = mpc - &mms->mpc[0]; 22633293e50SPeter Maydell MemoryRegion *downstream; 22733293e50SPeter Maydell MemoryRegion *upstream; 22833293e50SPeter Maydell UnimplementedDeviceState *uds; 22933293e50SPeter Maydell char *mpcname; 23033293e50SPeter Maydell const MPCInfo *mpcinfo = mmc->mpc_info; 23133293e50SPeter Maydell 23233293e50SPeter Maydell mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name); 23333293e50SPeter Maydell 23433293e50SPeter Maydell switch (mpcinfo[i].type) { 23533293e50SPeter Maydell case MPC_ROM: 23633293e50SPeter Maydell downstream = &mms->ram[i]; 23733293e50SPeter Maydell memory_region_init_rom(downstream, NULL, mpcinfo[i].name, 23833293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 23933293e50SPeter Maydell break; 24033293e50SPeter Maydell case MPC_RAM: 24133293e50SPeter Maydell downstream = &mms->ram[i]; 24233293e50SPeter Maydell memory_region_init_ram(downstream, NULL, mpcinfo[i].name, 24333293e50SPeter Maydell mpcinfo[i].size, &error_fatal); 24433293e50SPeter Maydell break; 24533293e50SPeter Maydell case MPC_CRYPTOISLAND: 24633293e50SPeter Maydell /* We don't implement the CryptoIsland yet */ 24733293e50SPeter Maydell uds = &mms->cryptoisland; 2480074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uds, 24933293e50SPeter Maydell TYPE_UNIMPLEMENTED_DEVICE); 25033293e50SPeter Maydell qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name); 25133293e50SPeter Maydell qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size); 2520074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); 25333293e50SPeter Maydell downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); 25433293e50SPeter Maydell break; 25533293e50SPeter Maydell default: 25633293e50SPeter Maydell g_assert_not_reached(); 25733293e50SPeter Maydell } 25833293e50SPeter Maydell 2590074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC); 2605325cc34SMarkus Armbruster object_property_set_link(OBJECT(mpc), "downstream", OBJECT(downstream), 2615325cc34SMarkus Armbruster &error_fatal); 2620074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal); 26333293e50SPeter Maydell /* Map the upstream end of the MPC into system memory */ 26433293e50SPeter Maydell upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); 26533293e50SPeter Maydell memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream); 26633293e50SPeter Maydell /* and connect its interrupt to the SSE-200 */ 26733293e50SPeter Maydell qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0, 26833293e50SPeter Maydell qdev_get_gpio_in_named(DEVICE(&mms->sse), 26933293e50SPeter Maydell "mpcexp_status", i)); 27033293e50SPeter Maydell 27133293e50SPeter Maydell g_free(mpcname); 27233293e50SPeter Maydell /* Return the register interface MR for our caller to map behind the PPC */ 27333293e50SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); 27433293e50SPeter Maydell } 27533293e50SPeter Maydell 2764db6a761SPeter Maydell static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque, 2774db6a761SPeter Maydell const char *name, hwaddr size) 2784db6a761SPeter Maydell { 2794db6a761SPeter Maydell PL031State *rtc = opaque; 2804db6a761SPeter Maydell 2810074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, rtc, TYPE_PL031); 2820074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(rtc), &error_fatal); 2834db6a761SPeter Maydell sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39)); 2844db6a761SPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0); 2854db6a761SPeter Maydell } 2864db6a761SPeter Maydell 2871486f1baSPeter Maydell static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque, 2881486f1baSPeter Maydell const char *name, hwaddr size) 2891486f1baSPeter Maydell { 2901486f1baSPeter Maydell PL011State *uart = opaque; 2911486f1baSPeter Maydell int i = uart - &mms->uart[0]; 2921486f1baSPeter Maydell int irqbase = 7 + i * 6; 2931486f1baSPeter Maydell SysBusDevice *s; 2941486f1baSPeter Maydell 2950074fce6SMarkus Armbruster object_initialize_child(OBJECT(mms), name, uart, TYPE_PL011); 2961486f1baSPeter Maydell qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); 2970074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal); 2981486f1baSPeter Maydell s = SYS_BUS_DEVICE(uart); 2991486f1baSPeter Maydell sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */ 3001486f1baSPeter Maydell sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */ 3011486f1baSPeter Maydell sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */ 3021486f1baSPeter Maydell sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */ 3031486f1baSPeter Maydell sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */ 3041486f1baSPeter Maydell sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */ 3051486f1baSPeter Maydell return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0); 3061486f1baSPeter Maydell } 3071486f1baSPeter Maydell 308ae3bc714SPeter Maydell static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque, 309ae3bc714SPeter Maydell const char *name, hwaddr size) 310ae3bc714SPeter Maydell { 311ae3bc714SPeter Maydell /* 312ae3bc714SPeter Maydell * Create the container MemoryRegion for all the devices that live 313ae3bc714SPeter Maydell * behind the Musca-A PPC's single port. These devices don't have a PPC 314ae3bc714SPeter Maydell * port each, but we use the PPCPortInfo struct as a convenient way 315ae3bc714SPeter Maydell * to describe them. Note that addresses here are relative to the base 316ae3bc714SPeter Maydell * address of the PPC port region: 0x40100000, and devices appear both 317ae3bc714SPeter Maydell * at the 0x4... NS region and the 0x5... S region. 318ae3bc714SPeter Maydell */ 319ae3bc714SPeter Maydell int i; 320ae3bc714SPeter Maydell MemoryRegion *container = &mms->container; 321ae3bc714SPeter Maydell 322ae3bc714SPeter Maydell const PPCPortInfo devices[] = { 3231486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 }, 3241486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 }, 325ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 }, 326ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 }, 327ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 }, 328ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 }, 329ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 }, 3304db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 }, 331ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 }, 332ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 }, 333ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 }, 334ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 }, 335ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 }, 336ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 }, 33733293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 }, 33833293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 }, 339ae3bc714SPeter Maydell }; 340ae3bc714SPeter Maydell 341ae3bc714SPeter Maydell memory_region_init(container, OBJECT(mms), "musca-device-container", size); 342ae3bc714SPeter Maydell 343ae3bc714SPeter Maydell for (i = 0; i < ARRAY_SIZE(devices); i++) { 344ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &devices[i]; 345ae3bc714SPeter Maydell MemoryRegion *mr; 346ae3bc714SPeter Maydell 347ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 348ae3bc714SPeter Maydell memory_region_add_subregion(container, pinfo->addr, mr); 349ae3bc714SPeter Maydell } 350ae3bc714SPeter Maydell 351ae3bc714SPeter Maydell return &mms->container; 352ae3bc714SPeter Maydell } 353ae3bc714SPeter Maydell 3548f69a4c1SPeter Maydell static void musca_init(MachineState *machine) 3558f69a4c1SPeter Maydell { 3568f69a4c1SPeter Maydell MuscaMachineState *mms = MUSCA_MACHINE(machine); 3578f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 3588f69a4c1SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(machine); 3598f69a4c1SPeter Maydell MemoryRegion *system_memory = get_system_memory(); 3608f69a4c1SPeter Maydell DeviceState *ssedev; 361ae3bc714SPeter Maydell DeviceState *dev_splitter; 362ae3bc714SPeter Maydell const PPCInfo *ppcs; 363ae3bc714SPeter Maydell int num_ppcs; 3648f69a4c1SPeter Maydell int i; 3658f69a4c1SPeter Maydell 3668f69a4c1SPeter Maydell assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX); 36733293e50SPeter Maydell assert(mmc->num_mpcs <= MUSCA_MPC_MAX); 3688f69a4c1SPeter Maydell 3698f69a4c1SPeter Maydell if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { 3708f69a4c1SPeter Maydell error_report("This board can only be used with CPU %s", 3718f69a4c1SPeter Maydell mc->default_cpu_type); 3728f69a4c1SPeter Maydell exit(1); 3738f69a4c1SPeter Maydell } 3748f69a4c1SPeter Maydell 375*fd630cdaSPeter Maydell mms->sysclk = clock_new(OBJECT(machine), "SYSCLK"); 376*fd630cdaSPeter Maydell clock_set_hz(mms->sysclk, SYSCLK_FRQ); 377*fd630cdaSPeter Maydell mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK"); 378*fd630cdaSPeter Maydell clock_set_hz(mms->s32kclk, S32KCLK_FRQ); 379*fd630cdaSPeter Maydell 3800074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), "sse-200", &mms->sse, 3810074fce6SMarkus Armbruster TYPE_SSE200); 3828f69a4c1SPeter Maydell ssedev = DEVICE(&mms->sse); 3835325cc34SMarkus Armbruster object_property_set_link(OBJECT(&mms->sse), "memory", 3845325cc34SMarkus Armbruster OBJECT(system_memory), &error_fatal); 3858f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs); 3868f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor); 3878f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width); 38813059a3aSPeter Maydell qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ); 389*fd630cdaSPeter Maydell qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk); 390*fd630cdaSPeter Maydell qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk); 391a90a862bSPeter Maydell /* 392a90a862bSPeter Maydell * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for 393a90a862bSPeter Maydell * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0. 394a90a862bSPeter Maydell */ 395a90a862bSPeter Maydell if (mmc->type == MUSCA_B1) { 396a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_FPU", true); 397a90a862bSPeter Maydell qdev_prop_set_bit(ssedev, "CPU0_DSP", true); 398a90a862bSPeter Maydell } 3990074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(&mms->sse), &error_fatal); 4008f69a4c1SPeter Maydell 4018f69a4c1SPeter Maydell /* 4028f69a4c1SPeter Maydell * We need to create splitters to feed the IRQ inputs 4038f69a4c1SPeter Maydell * for each CPU in the SSE-200 from each device in the board. 4048f69a4c1SPeter Maydell */ 4058f69a4c1SPeter Maydell for (i = 0; i < mmc->num_irqs; i++) { 4068f69a4c1SPeter Maydell char *name = g_strdup_printf("musca-irq-splitter%d", i); 4078f69a4c1SPeter Maydell SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; 4088f69a4c1SPeter Maydell 4099fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), name, splitter, 4109fc7fc4dSMarkus Armbruster sizeof(*splitter), TYPE_SPLIT_IRQ, 4119fc7fc4dSMarkus Armbruster &error_fatal, NULL); 4128f69a4c1SPeter Maydell g_free(name); 4138f69a4c1SPeter Maydell 4145325cc34SMarkus Armbruster object_property_set_int(OBJECT(splitter), "num-lines", 2, 4158f69a4c1SPeter Maydell &error_fatal); 416ce189ab2SMarkus Armbruster qdev_realize(DEVICE(splitter), NULL, &error_fatal); 4178f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 0, 4188f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i)); 4198f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 1, 4208f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, 4218f69a4c1SPeter Maydell "EXP_CPU1_IRQ", i)); 4228f69a4c1SPeter Maydell } 4238f69a4c1SPeter Maydell 424ae3bc714SPeter Maydell /* 425ae3bc714SPeter Maydell * The sec_resp_cfg output from the SSE-200 must be split into multiple 426ae3bc714SPeter Maydell * lines, one for each of the PPCs we create here. 427ae3bc714SPeter Maydell */ 4289fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(machine), "sec-resp-splitter", 4297840938eSPhilippe Mathieu-Daudé &mms->sec_resp_splitter, 4307840938eSPhilippe Mathieu-Daudé sizeof(mms->sec_resp_splitter), 4317840938eSPhilippe Mathieu-Daudé TYPE_SPLIT_IRQ, &error_fatal, NULL); 4327840938eSPhilippe Mathieu-Daudé 4335325cc34SMarkus Armbruster object_property_set_int(OBJECT(&mms->sec_resp_splitter), "num-lines", 4345325cc34SMarkus Armbruster ARRAY_SIZE(mms->ppc), &error_fatal); 435ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&mms->sec_resp_splitter), NULL, &error_fatal); 436ae3bc714SPeter Maydell dev_splitter = DEVICE(&mms->sec_resp_splitter); 437ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0, 438ae3bc714SPeter Maydell qdev_get_gpio_in(dev_splitter, 0)); 439ae3bc714SPeter Maydell 440ae3bc714SPeter Maydell /* 441ae3bc714SPeter Maydell * Most of the devices in the board are behind Peripheral Protection 442ae3bc714SPeter Maydell * Controllers. The required order for initializing things is: 443ae3bc714SPeter Maydell * + initialize the PPC 444ae3bc714SPeter Maydell * + initialize, configure and realize downstream devices 445ae3bc714SPeter Maydell * + connect downstream device MemoryRegions to the PPC 446ae3bc714SPeter Maydell * + realize the PPC 447ae3bc714SPeter Maydell * + map the PPC's MemoryRegions to the places in the address map 448ae3bc714SPeter Maydell * where the downstream devices should appear 449ae3bc714SPeter Maydell * + wire up the PPC's control lines to the SSE object 450ae3bc714SPeter Maydell * 451ae3bc714SPeter Maydell * The PPC mapping differs for the -A and -B1 variants; the -A version 452ae3bc714SPeter Maydell * is much simpler, using only a single port of a single PPC and putting 453ae3bc714SPeter Maydell * all the devices behind that. 454ae3bc714SPeter Maydell */ 455ae3bc714SPeter Maydell const PPCInfo a_ppcs[] = { { 456ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 457ae3bc714SPeter Maydell .ports = { 458ae3bc714SPeter Maydell { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 }, 459ae3bc714SPeter Maydell }, 460ae3bc714SPeter Maydell }, 461ae3bc714SPeter Maydell }; 462ae3bc714SPeter Maydell 463ae3bc714SPeter Maydell /* 464ae3bc714SPeter Maydell * Devices listed with an 0x4.. address appear in both the NS 0x4.. region 465ae3bc714SPeter Maydell * and the 0x5.. S region. Devices listed with an 0x5.. address appear 466ae3bc714SPeter Maydell * only in the S region. 467ae3bc714SPeter Maydell */ 468ae3bc714SPeter Maydell const PPCInfo b1_ppcs[] = { { 469ae3bc714SPeter Maydell .name = "apb_ppcexp0", 470ae3bc714SPeter Maydell .ports = { 471ae3bc714SPeter Maydell { "eflash0", make_unimp_dev, &mms->eflash[0], 472ae3bc714SPeter Maydell 0x52400000, 0x1000 }, 473ae3bc714SPeter Maydell { "eflash1", make_unimp_dev, &mms->eflash[1], 474ae3bc714SPeter Maydell 0x52500000, 0x1000 }, 475ae3bc714SPeter Maydell { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 }, 47633293e50SPeter Maydell { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 }, 47733293e50SPeter Maydell { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 }, 47833293e50SPeter Maydell { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 }, 47933293e50SPeter Maydell { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 }, 480ae3bc714SPeter Maydell { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 }, 481ae3bc714SPeter Maydell { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 }, 482ae3bc714SPeter Maydell { }, /* port 9: unused */ 483ae3bc714SPeter Maydell { }, /* port 10: unused */ 484ae3bc714SPeter Maydell { }, /* port 11: unused */ 485ae3bc714SPeter Maydell { }, /* port 12: unused */ 486ae3bc714SPeter Maydell { }, /* port 13: unused */ 48733293e50SPeter Maydell { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 }, 488ae3bc714SPeter Maydell }, 489ae3bc714SPeter Maydell }, { 490ae3bc714SPeter Maydell .name = "apb_ppcexp1", 491ae3bc714SPeter Maydell .ports = { 492ae3bc714SPeter Maydell { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 }, 493ae3bc714SPeter Maydell { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 }, 494ae3bc714SPeter Maydell { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 }, 495ae3bc714SPeter Maydell { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 }, 4961486f1baSPeter Maydell { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 }, 4971486f1baSPeter Maydell { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 }, 498ae3bc714SPeter Maydell { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 }, 499ae3bc714SPeter Maydell { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 }, 500ae3bc714SPeter Maydell { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 }, 501ae3bc714SPeter Maydell { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 }, 502ae3bc714SPeter Maydell { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 }, 5034db6a761SPeter Maydell { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 }, 504ae3bc714SPeter Maydell { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 }, 505ae3bc714SPeter Maydell { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 }, 506ae3bc714SPeter Maydell }, 507ae3bc714SPeter Maydell }, { 508ae3bc714SPeter Maydell .name = "ahb_ppcexp0", 509ae3bc714SPeter Maydell .ports = { 510ae3bc714SPeter Maydell { }, /* port 0: unused */ 511ae3bc714SPeter Maydell { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 }, 512ae3bc714SPeter Maydell }, 513ae3bc714SPeter Maydell }, 514ae3bc714SPeter Maydell }; 515ae3bc714SPeter Maydell 516ae3bc714SPeter Maydell switch (mmc->type) { 517ae3bc714SPeter Maydell case MUSCA_A: 518ae3bc714SPeter Maydell ppcs = a_ppcs; 519ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(a_ppcs); 520ae3bc714SPeter Maydell break; 521ae3bc714SPeter Maydell case MUSCA_B1: 522ae3bc714SPeter Maydell ppcs = b1_ppcs; 523ae3bc714SPeter Maydell num_ppcs = ARRAY_SIZE(b1_ppcs); 524ae3bc714SPeter Maydell break; 525ae3bc714SPeter Maydell default: 526ae3bc714SPeter Maydell g_assert_not_reached(); 527ae3bc714SPeter Maydell } 528ae3bc714SPeter Maydell assert(num_ppcs <= MUSCA_PPC_MAX); 529ae3bc714SPeter Maydell 530ae3bc714SPeter Maydell for (i = 0; i < num_ppcs; i++) { 531ae3bc714SPeter Maydell const PPCInfo *ppcinfo = &ppcs[i]; 532ae3bc714SPeter Maydell TZPPC *ppc = &mms->ppc[i]; 533ae3bc714SPeter Maydell DeviceState *ppcdev; 534ae3bc714SPeter Maydell int port; 535ae3bc714SPeter Maydell char *gpioname; 536ae3bc714SPeter Maydell 5370074fce6SMarkus Armbruster object_initialize_child(OBJECT(machine), ppcinfo->name, ppc, 5380074fce6SMarkus Armbruster TYPE_TZ_PPC); 539ae3bc714SPeter Maydell ppcdev = DEVICE(ppc); 540ae3bc714SPeter Maydell 541ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 542ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 543ae3bc714SPeter Maydell MemoryRegion *mr; 544ae3bc714SPeter Maydell char *portname; 545ae3bc714SPeter Maydell 546ae3bc714SPeter Maydell if (!pinfo->devfn) { 547ae3bc714SPeter Maydell continue; 548ae3bc714SPeter Maydell } 549ae3bc714SPeter Maydell 550ae3bc714SPeter Maydell mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); 551ae3bc714SPeter Maydell portname = g_strdup_printf("port[%d]", port); 5525325cc34SMarkus Armbruster object_property_set_link(OBJECT(ppc), portname, OBJECT(mr), 5535325cc34SMarkus Armbruster &error_fatal); 554ae3bc714SPeter Maydell g_free(portname); 555ae3bc714SPeter Maydell } 556ae3bc714SPeter Maydell 5570074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(ppc), &error_fatal); 558ae3bc714SPeter Maydell 559ae3bc714SPeter Maydell for (port = 0; port < TZ_NUM_PORTS; port++) { 560ae3bc714SPeter Maydell const PPCPortInfo *pinfo = &ppcinfo->ports[port]; 561ae3bc714SPeter Maydell 562ae3bc714SPeter Maydell if (!pinfo->devfn) { 563ae3bc714SPeter Maydell continue; 564ae3bc714SPeter Maydell } 565ae3bc714SPeter Maydell sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr); 566ae3bc714SPeter Maydell 567ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name); 568ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 569ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 570ae3bc714SPeter Maydell "cfg_nonsec", 571ae3bc714SPeter Maydell port)); 572ae3bc714SPeter Maydell g_free(gpioname); 573ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_ap", ppcinfo->name); 574ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, port, 575ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 576ae3bc714SPeter Maydell "cfg_ap", port)); 577ae3bc714SPeter Maydell g_free(gpioname); 578ae3bc714SPeter Maydell } 579ae3bc714SPeter Maydell 580ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name); 581ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 582ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 583ae3bc714SPeter Maydell "irq_enable", 0)); 584ae3bc714SPeter Maydell g_free(gpioname); 585ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name); 586ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ssedev, gpioname, 0, 587ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 588ae3bc714SPeter Maydell "irq_clear", 0)); 589ae3bc714SPeter Maydell g_free(gpioname); 590ae3bc714SPeter Maydell gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name); 591ae3bc714SPeter Maydell qdev_connect_gpio_out_named(ppcdev, "irq", 0, 592ae3bc714SPeter Maydell qdev_get_gpio_in_named(ssedev, 593ae3bc714SPeter Maydell gpioname, 0)); 594ae3bc714SPeter Maydell g_free(gpioname); 595ae3bc714SPeter Maydell 596ae3bc714SPeter Maydell qdev_connect_gpio_out(dev_splitter, i, 597ae3bc714SPeter Maydell qdev_get_gpio_in_named(ppcdev, 598ae3bc714SPeter Maydell "cfg_sec_resp", 0)); 599ae3bc714SPeter Maydell } 600ae3bc714SPeter Maydell 6018f69a4c1SPeter Maydell armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000); 6028f69a4c1SPeter Maydell } 6038f69a4c1SPeter Maydell 6048f69a4c1SPeter Maydell static void musca_class_init(ObjectClass *oc, void *data) 6058f69a4c1SPeter Maydell { 6068f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6078f69a4c1SPeter Maydell 6088f69a4c1SPeter Maydell mc->default_cpus = 2; 6098f69a4c1SPeter Maydell mc->min_cpus = mc->default_cpus; 6108f69a4c1SPeter Maydell mc->max_cpus = mc->default_cpus; 6118f69a4c1SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"); 6128f69a4c1SPeter Maydell mc->init = musca_init; 6138f69a4c1SPeter Maydell } 6148f69a4c1SPeter Maydell 6158f69a4c1SPeter Maydell static void musca_a_class_init(ObjectClass *oc, void *data) 6168f69a4c1SPeter Maydell { 6178f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6188f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6198f69a4c1SPeter Maydell 6208f69a4c1SPeter Maydell mc->desc = "ARM Musca-A board (dual Cortex-M33)"; 6218f69a4c1SPeter Maydell mmc->type = MUSCA_A; 6228f69a4c1SPeter Maydell mmc->init_svtor = 0x10200000; 6238f69a4c1SPeter Maydell mmc->sram_addr_width = 15; 6248f69a4c1SPeter Maydell mmc->num_irqs = 64; 62533293e50SPeter Maydell mmc->mpc_info = a_mpc_info; 62633293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(a_mpc_info); 6278f69a4c1SPeter Maydell } 6288f69a4c1SPeter Maydell 6298f69a4c1SPeter Maydell static void musca_b1_class_init(ObjectClass *oc, void *data) 6308f69a4c1SPeter Maydell { 6318f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 6328f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 6338f69a4c1SPeter Maydell 6348f69a4c1SPeter Maydell mc->desc = "ARM Musca-B1 board (dual Cortex-M33)"; 6358f69a4c1SPeter Maydell mmc->type = MUSCA_B1; 6368f69a4c1SPeter Maydell /* 6378f69a4c1SPeter Maydell * This matches the DAPlink firmware which boots from QSPI. There 6388f69a4c1SPeter Maydell * is also a firmware blob which boots from the eFlash, which 6398f69a4c1SPeter Maydell * uses init_svtor = 0x1A000000. QEMU doesn't currently support that, 6408f69a4c1SPeter Maydell * though we could in theory expose a machine property on the command 6418f69a4c1SPeter Maydell * line to allow the user to request eFlash boot. 6428f69a4c1SPeter Maydell */ 6438f69a4c1SPeter Maydell mmc->init_svtor = 0x10000000; 6448f69a4c1SPeter Maydell mmc->sram_addr_width = 17; 6458f69a4c1SPeter Maydell mmc->num_irqs = 96; 64633293e50SPeter Maydell mmc->mpc_info = b1_mpc_info; 64733293e50SPeter Maydell mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info); 6488f69a4c1SPeter Maydell } 6498f69a4c1SPeter Maydell 6508f69a4c1SPeter Maydell static const TypeInfo musca_info = { 6518f69a4c1SPeter Maydell .name = TYPE_MUSCA_MACHINE, 6528f69a4c1SPeter Maydell .parent = TYPE_MACHINE, 6538f69a4c1SPeter Maydell .abstract = true, 6548f69a4c1SPeter Maydell .instance_size = sizeof(MuscaMachineState), 6558f69a4c1SPeter Maydell .class_size = sizeof(MuscaMachineClass), 6568f69a4c1SPeter Maydell .class_init = musca_class_init, 6578f69a4c1SPeter Maydell }; 6588f69a4c1SPeter Maydell 6598f69a4c1SPeter Maydell static const TypeInfo musca_a_info = { 6608f69a4c1SPeter Maydell .name = TYPE_MUSCA_A_MACHINE, 6618f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6628f69a4c1SPeter Maydell .class_init = musca_a_class_init, 6638f69a4c1SPeter Maydell }; 6648f69a4c1SPeter Maydell 6658f69a4c1SPeter Maydell static const TypeInfo musca_b1_info = { 6668f69a4c1SPeter Maydell .name = TYPE_MUSCA_B1_MACHINE, 6678f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 6688f69a4c1SPeter Maydell .class_init = musca_b1_class_init, 6698f69a4c1SPeter Maydell }; 6708f69a4c1SPeter Maydell 6718f69a4c1SPeter Maydell static void musca_machine_init(void) 6728f69a4c1SPeter Maydell { 6738f69a4c1SPeter Maydell type_register_static(&musca_info); 6748f69a4c1SPeter Maydell type_register_static(&musca_a_info); 6758f69a4c1SPeter Maydell type_register_static(&musca_b1_info); 6768f69a4c1SPeter Maydell } 6778f69a4c1SPeter Maydell 6788f69a4c1SPeter Maydell type_init(musca_machine_init); 679