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