1*8f69a4c1SPeter Maydell /* 2*8f69a4c1SPeter Maydell * Arm Musca-B1 test chip board emulation 3*8f69a4c1SPeter Maydell * 4*8f69a4c1SPeter Maydell * Copyright (c) 2019 Linaro Limited 5*8f69a4c1SPeter Maydell * Written by Peter Maydell 6*8f69a4c1SPeter Maydell * 7*8f69a4c1SPeter Maydell * This program is free software; you can redistribute it and/or modify 8*8f69a4c1SPeter Maydell * it under the terms of the GNU General Public License version 2 or 9*8f69a4c1SPeter Maydell * (at your option) any later version. 10*8f69a4c1SPeter Maydell */ 11*8f69a4c1SPeter Maydell 12*8f69a4c1SPeter Maydell /* 13*8f69a4c1SPeter Maydell * The Musca boards are a reference implementation of a system using 14*8f69a4c1SPeter Maydell * the SSE-200 subsystem for embedded: 15*8f69a4c1SPeter Maydell * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board 16*8f69a4c1SPeter Maydell * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board 17*8f69a4c1SPeter Maydell * We model the A and B1 variants of this board, as described in the TRMs: 18*8f69a4c1SPeter Maydell * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html 19*8f69a4c1SPeter Maydell * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html 20*8f69a4c1SPeter Maydell */ 21*8f69a4c1SPeter Maydell 22*8f69a4c1SPeter Maydell #include "qemu/osdep.h" 23*8f69a4c1SPeter Maydell #include "qemu/error-report.h" 24*8f69a4c1SPeter Maydell #include "qapi/error.h" 25*8f69a4c1SPeter Maydell #include "exec/address-spaces.h" 26*8f69a4c1SPeter Maydell #include "hw/arm/arm.h" 27*8f69a4c1SPeter Maydell #include "hw/arm/armsse.h" 28*8f69a4c1SPeter Maydell #include "hw/boards.h" 29*8f69a4c1SPeter Maydell #include "hw/core/split-irq.h" 30*8f69a4c1SPeter Maydell 31*8f69a4c1SPeter Maydell #define MUSCA_NUMIRQ_MAX 96 32*8f69a4c1SPeter Maydell 33*8f69a4c1SPeter Maydell typedef enum MuscaType { 34*8f69a4c1SPeter Maydell MUSCA_A, 35*8f69a4c1SPeter Maydell MUSCA_B1, 36*8f69a4c1SPeter Maydell } MuscaType; 37*8f69a4c1SPeter Maydell 38*8f69a4c1SPeter Maydell typedef struct { 39*8f69a4c1SPeter Maydell MachineClass parent; 40*8f69a4c1SPeter Maydell MuscaType type; 41*8f69a4c1SPeter Maydell uint32_t init_svtor; 42*8f69a4c1SPeter Maydell int sram_addr_width; 43*8f69a4c1SPeter Maydell int num_irqs; 44*8f69a4c1SPeter Maydell } MuscaMachineClass; 45*8f69a4c1SPeter Maydell 46*8f69a4c1SPeter Maydell typedef struct { 47*8f69a4c1SPeter Maydell MachineState parent; 48*8f69a4c1SPeter Maydell 49*8f69a4c1SPeter Maydell ARMSSE sse; 50*8f69a4c1SPeter Maydell SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX]; 51*8f69a4c1SPeter Maydell } MuscaMachineState; 52*8f69a4c1SPeter Maydell 53*8f69a4c1SPeter Maydell #define TYPE_MUSCA_MACHINE "musca" 54*8f69a4c1SPeter Maydell #define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a") 55*8f69a4c1SPeter Maydell #define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1") 56*8f69a4c1SPeter Maydell 57*8f69a4c1SPeter Maydell #define MUSCA_MACHINE(obj) \ 58*8f69a4c1SPeter Maydell OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE) 59*8f69a4c1SPeter Maydell #define MUSCA_MACHINE_GET_CLASS(obj) \ 60*8f69a4c1SPeter Maydell OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE) 61*8f69a4c1SPeter Maydell #define MUSCA_MACHINE_CLASS(klass) \ 62*8f69a4c1SPeter Maydell OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE) 63*8f69a4c1SPeter Maydell 64*8f69a4c1SPeter Maydell /* 65*8f69a4c1SPeter Maydell * Main SYSCLK frequency in Hz 66*8f69a4c1SPeter Maydell * TODO this should really be different for the two cores, but we 67*8f69a4c1SPeter Maydell * don't model that in our SSE-200 model yet. 68*8f69a4c1SPeter Maydell */ 69*8f69a4c1SPeter Maydell #define SYSCLK_FRQ 40000000 70*8f69a4c1SPeter Maydell 71*8f69a4c1SPeter Maydell static void musca_init(MachineState *machine) 72*8f69a4c1SPeter Maydell { 73*8f69a4c1SPeter Maydell MuscaMachineState *mms = MUSCA_MACHINE(machine); 74*8f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms); 75*8f69a4c1SPeter Maydell MachineClass *mc = MACHINE_GET_CLASS(machine); 76*8f69a4c1SPeter Maydell MemoryRegion *system_memory = get_system_memory(); 77*8f69a4c1SPeter Maydell DeviceState *ssedev; 78*8f69a4c1SPeter Maydell int i; 79*8f69a4c1SPeter Maydell 80*8f69a4c1SPeter Maydell assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX); 81*8f69a4c1SPeter Maydell 82*8f69a4c1SPeter Maydell if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { 83*8f69a4c1SPeter Maydell error_report("This board can only be used with CPU %s", 84*8f69a4c1SPeter Maydell mc->default_cpu_type); 85*8f69a4c1SPeter Maydell exit(1); 86*8f69a4c1SPeter Maydell } 87*8f69a4c1SPeter Maydell 88*8f69a4c1SPeter Maydell sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse, 89*8f69a4c1SPeter Maydell sizeof(mms->sse), TYPE_SSE200); 90*8f69a4c1SPeter Maydell ssedev = DEVICE(&mms->sse); 91*8f69a4c1SPeter Maydell object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory), 92*8f69a4c1SPeter Maydell "memory", &error_fatal); 93*8f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs); 94*8f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor); 95*8f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width); 96*8f69a4c1SPeter Maydell qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ); 97*8f69a4c1SPeter Maydell object_property_set_bool(OBJECT(&mms->sse), true, "realized", 98*8f69a4c1SPeter Maydell &error_fatal); 99*8f69a4c1SPeter Maydell 100*8f69a4c1SPeter Maydell /* 101*8f69a4c1SPeter Maydell * We need to create splitters to feed the IRQ inputs 102*8f69a4c1SPeter Maydell * for each CPU in the SSE-200 from each device in the board. 103*8f69a4c1SPeter Maydell */ 104*8f69a4c1SPeter Maydell for (i = 0; i < mmc->num_irqs; i++) { 105*8f69a4c1SPeter Maydell char *name = g_strdup_printf("musca-irq-splitter%d", i); 106*8f69a4c1SPeter Maydell SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; 107*8f69a4c1SPeter Maydell 108*8f69a4c1SPeter Maydell object_initialize_child(OBJECT(machine), name, 109*8f69a4c1SPeter Maydell splitter, sizeof(*splitter), 110*8f69a4c1SPeter Maydell TYPE_SPLIT_IRQ, &error_fatal, NULL); 111*8f69a4c1SPeter Maydell g_free(name); 112*8f69a4c1SPeter Maydell 113*8f69a4c1SPeter Maydell object_property_set_int(OBJECT(splitter), 2, "num-lines", 114*8f69a4c1SPeter Maydell &error_fatal); 115*8f69a4c1SPeter Maydell object_property_set_bool(OBJECT(splitter), true, "realized", 116*8f69a4c1SPeter Maydell &error_fatal); 117*8f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 0, 118*8f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i)); 119*8f69a4c1SPeter Maydell qdev_connect_gpio_out(DEVICE(splitter), 1, 120*8f69a4c1SPeter Maydell qdev_get_gpio_in_named(ssedev, 121*8f69a4c1SPeter Maydell "EXP_CPU1_IRQ", i)); 122*8f69a4c1SPeter Maydell } 123*8f69a4c1SPeter Maydell 124*8f69a4c1SPeter Maydell armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000); 125*8f69a4c1SPeter Maydell } 126*8f69a4c1SPeter Maydell 127*8f69a4c1SPeter Maydell static void musca_class_init(ObjectClass *oc, void *data) 128*8f69a4c1SPeter Maydell { 129*8f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 130*8f69a4c1SPeter Maydell 131*8f69a4c1SPeter Maydell mc->default_cpus = 2; 132*8f69a4c1SPeter Maydell mc->min_cpus = mc->default_cpus; 133*8f69a4c1SPeter Maydell mc->max_cpus = mc->default_cpus; 134*8f69a4c1SPeter Maydell mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"); 135*8f69a4c1SPeter Maydell mc->init = musca_init; 136*8f69a4c1SPeter Maydell } 137*8f69a4c1SPeter Maydell 138*8f69a4c1SPeter Maydell static void musca_a_class_init(ObjectClass *oc, void *data) 139*8f69a4c1SPeter Maydell { 140*8f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 141*8f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 142*8f69a4c1SPeter Maydell 143*8f69a4c1SPeter Maydell mc->desc = "ARM Musca-A board (dual Cortex-M33)"; 144*8f69a4c1SPeter Maydell mmc->type = MUSCA_A; 145*8f69a4c1SPeter Maydell mmc->init_svtor = 0x10200000; 146*8f69a4c1SPeter Maydell mmc->sram_addr_width = 15; 147*8f69a4c1SPeter Maydell mmc->num_irqs = 64; 148*8f69a4c1SPeter Maydell } 149*8f69a4c1SPeter Maydell 150*8f69a4c1SPeter Maydell static void musca_b1_class_init(ObjectClass *oc, void *data) 151*8f69a4c1SPeter Maydell { 152*8f69a4c1SPeter Maydell MachineClass *mc = MACHINE_CLASS(oc); 153*8f69a4c1SPeter Maydell MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc); 154*8f69a4c1SPeter Maydell 155*8f69a4c1SPeter Maydell mc->desc = "ARM Musca-B1 board (dual Cortex-M33)"; 156*8f69a4c1SPeter Maydell mmc->type = MUSCA_B1; 157*8f69a4c1SPeter Maydell /* 158*8f69a4c1SPeter Maydell * This matches the DAPlink firmware which boots from QSPI. There 159*8f69a4c1SPeter Maydell * is also a firmware blob which boots from the eFlash, which 160*8f69a4c1SPeter Maydell * uses init_svtor = 0x1A000000. QEMU doesn't currently support that, 161*8f69a4c1SPeter Maydell * though we could in theory expose a machine property on the command 162*8f69a4c1SPeter Maydell * line to allow the user to request eFlash boot. 163*8f69a4c1SPeter Maydell */ 164*8f69a4c1SPeter Maydell mmc->init_svtor = 0x10000000; 165*8f69a4c1SPeter Maydell mmc->sram_addr_width = 17; 166*8f69a4c1SPeter Maydell mmc->num_irqs = 96; 167*8f69a4c1SPeter Maydell } 168*8f69a4c1SPeter Maydell 169*8f69a4c1SPeter Maydell static const TypeInfo musca_info = { 170*8f69a4c1SPeter Maydell .name = TYPE_MUSCA_MACHINE, 171*8f69a4c1SPeter Maydell .parent = TYPE_MACHINE, 172*8f69a4c1SPeter Maydell .abstract = true, 173*8f69a4c1SPeter Maydell .instance_size = sizeof(MuscaMachineState), 174*8f69a4c1SPeter Maydell .class_size = sizeof(MuscaMachineClass), 175*8f69a4c1SPeter Maydell .class_init = musca_class_init, 176*8f69a4c1SPeter Maydell }; 177*8f69a4c1SPeter Maydell 178*8f69a4c1SPeter Maydell static const TypeInfo musca_a_info = { 179*8f69a4c1SPeter Maydell .name = TYPE_MUSCA_A_MACHINE, 180*8f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 181*8f69a4c1SPeter Maydell .class_init = musca_a_class_init, 182*8f69a4c1SPeter Maydell }; 183*8f69a4c1SPeter Maydell 184*8f69a4c1SPeter Maydell static const TypeInfo musca_b1_info = { 185*8f69a4c1SPeter Maydell .name = TYPE_MUSCA_B1_MACHINE, 186*8f69a4c1SPeter Maydell .parent = TYPE_MUSCA_MACHINE, 187*8f69a4c1SPeter Maydell .class_init = musca_b1_class_init, 188*8f69a4c1SPeter Maydell }; 189*8f69a4c1SPeter Maydell 190*8f69a4c1SPeter Maydell static void musca_machine_init(void) 191*8f69a4c1SPeter Maydell { 192*8f69a4c1SPeter Maydell type_register_static(&musca_info); 193*8f69a4c1SPeter Maydell type_register_static(&musca_a_info); 194*8f69a4c1SPeter Maydell type_register_static(&musca_b1_info); 195*8f69a4c1SPeter Maydell } 196*8f69a4c1SPeter Maydell 197*8f69a4c1SPeter Maydell type_init(musca_machine_init); 198