xref: /openbmc/qemu/hw/arm/musca.c (revision 761c532a)
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:
18932a8d1fSPeter Maydell  * https://developer.arm.com/documentation/101107/latest/
19932a8d1fSPeter Maydell  * https://developer.arm.com/documentation/101312/latest/
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"
36fd630cdaSPeter 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;
86fd630cdaSPeter Maydell     Clock *sysclk;
87fd630cdaSPeter 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 
OBJECT_DECLARE_TYPE(MuscaMachineState,MuscaMachineClass,MUSCA_MACHINE)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
102fd630cdaSPeter Maydell /* Slow 32Khz S32KCLK frequency in Hz */
103fd630cdaSPeter 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 
make_unimp_dev(MuscaMachineState * mms,void * opaque,const char * name,hwaddr size)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 
make_mpc(MuscaMachineState * mms,void * opaque,const char * name,hwaddr size)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 
make_rtc(MuscaMachineState * mms,void * opaque,const char * name,hwaddr size)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 
make_uart(MuscaMachineState * mms,void * opaque,const char * name,hwaddr size)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 
make_musca_a_devs(MuscaMachineState * mms,void * opaque,const char * name,hwaddr size)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 
musca_init(MachineState * machine)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 
375fd630cdaSPeter Maydell     mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
376fd630cdaSPeter Maydell     clock_set_hz(mms->sysclk, SYSCLK_FRQ);
377fd630cdaSPeter Maydell     mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
378fd630cdaSPeter Maydell     clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
379fd630cdaSPeter 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);
388fd630cdaSPeter Maydell     qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
389fd630cdaSPeter Maydell     qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
390a90a862bSPeter Maydell     /*
391a90a862bSPeter Maydell      * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
392a90a862bSPeter Maydell      * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
393a90a862bSPeter Maydell      */
394a90a862bSPeter Maydell     if (mmc->type == MUSCA_B1) {
395a90a862bSPeter Maydell         qdev_prop_set_bit(ssedev, "CPU0_FPU", true);
396a90a862bSPeter Maydell         qdev_prop_set_bit(ssedev, "CPU0_DSP", true);
397a90a862bSPeter Maydell     }
3980074fce6SMarkus Armbruster     sysbus_realize(SYS_BUS_DEVICE(&mms->sse), &error_fatal);
3998f69a4c1SPeter Maydell 
4008f69a4c1SPeter Maydell     /*
4018f69a4c1SPeter Maydell      * We need to create splitters to feed the IRQ inputs
4028f69a4c1SPeter Maydell      * for each CPU in the SSE-200 from each device in the board.
4038f69a4c1SPeter Maydell      */
4048f69a4c1SPeter Maydell     for (i = 0; i < mmc->num_irqs; i++) {
4058f69a4c1SPeter Maydell         char *name = g_strdup_printf("musca-irq-splitter%d", i);
4068f69a4c1SPeter Maydell         SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
4078f69a4c1SPeter Maydell 
4089fc7fc4dSMarkus Armbruster         object_initialize_child_with_props(OBJECT(machine), name, splitter,
4099fc7fc4dSMarkus Armbruster                                            sizeof(*splitter), TYPE_SPLIT_IRQ,
4109fc7fc4dSMarkus Armbruster                                            &error_fatal, NULL);
4118f69a4c1SPeter Maydell         g_free(name);
4128f69a4c1SPeter Maydell 
4135325cc34SMarkus Armbruster         object_property_set_int(OBJECT(splitter), "num-lines", 2,
4148f69a4c1SPeter Maydell                                 &error_fatal);
415ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(splitter), NULL, &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      */
4279fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(machine), "sec-resp-splitter",
4287840938eSPhilippe Mathieu-Daudé                                        &mms->sec_resp_splitter,
4297840938eSPhilippe Mathieu-Daudé                                        sizeof(mms->sec_resp_splitter),
4307840938eSPhilippe Mathieu-Daudé                                        TYPE_SPLIT_IRQ, &error_fatal, NULL);
4317840938eSPhilippe Mathieu-Daudé 
4325325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&mms->sec_resp_splitter), "num-lines",
4335325cc34SMarkus Armbruster                             ARRAY_SIZE(mms->ppc), &error_fatal);
434ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&mms->sec_resp_splitter), NULL, &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 
5360074fce6SMarkus Armbruster         object_initialize_child(OBJECT(machine), ppcinfo->name, ppc,
5370074fce6SMarkus Armbruster                                 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);
5515325cc34SMarkus Armbruster             object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
5525325cc34SMarkus Armbruster                                      &error_fatal);
553ae3bc714SPeter Maydell             g_free(portname);
554ae3bc714SPeter Maydell         }
555ae3bc714SPeter Maydell 
5560074fce6SMarkus Armbruster         sysbus_realize(SYS_BUS_DEVICE(ppc), &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 
600*761c532aSPeter Maydell     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
601*761c532aSPeter Maydell                        0, 0x2000000);
6028f69a4c1SPeter Maydell }
6038f69a4c1SPeter Maydell 
musca_class_init(ObjectClass * oc,void * data)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 
musca_a_class_init(ObjectClass * oc,void * data)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 
musca_b1_class_init(ObjectClass * oc,void * data)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 
musca_machine_init(void)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