xref: /openbmc/qemu/hw/arm/musca.c (revision 8f69a4c1)
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