xref: /qemu/hw/arm/mps3r.c (revision 273a70ae823768081084d51a780e18f9ad80d68e)
1*273a70aeSPeter Maydell /*
2*273a70aeSPeter Maydell  * Arm MPS3 board emulation for Cortex-R-based FPGA images.
3*273a70aeSPeter Maydell  * (For M-profile images see mps2.c and mps2tz.c.)
4*273a70aeSPeter Maydell  *
5*273a70aeSPeter Maydell  * Copyright (c) 2017 Linaro Limited
6*273a70aeSPeter Maydell  * Written by Peter Maydell
7*273a70aeSPeter Maydell  *
8*273a70aeSPeter Maydell  *  This program is free software; you can redistribute it and/or modify
9*273a70aeSPeter Maydell  *  it under the terms of the GNU General Public License version 2 or
10*273a70aeSPeter Maydell  *  (at your option) any later version.
11*273a70aeSPeter Maydell  */
12*273a70aeSPeter Maydell 
13*273a70aeSPeter Maydell /*
14*273a70aeSPeter Maydell  * The MPS3 is an FPGA based dev board. This file handles FPGA images
15*273a70aeSPeter Maydell  * which use the Cortex-R CPUs. We model these separately from the
16*273a70aeSPeter Maydell  * M-profile images, because on M-profile the FPGA image is based on
17*273a70aeSPeter Maydell  * a "Subsystem for Embedded" which is similar to an SoC, whereas
18*273a70aeSPeter Maydell  * the R-profile FPGA images don't have that abstraction layer.
19*273a70aeSPeter Maydell  *
20*273a70aeSPeter Maydell  * We model the following FPGA images here:
21*273a70aeSPeter Maydell  *  "mps3-an536" -- dual Cortex-R52 as documented in Arm Application Note AN536
22*273a70aeSPeter Maydell  *
23*273a70aeSPeter Maydell  * Application Note AN536:
24*273a70aeSPeter Maydell  * https://developer.arm.com/documentation/dai0536/latest/
25*273a70aeSPeter Maydell  */
26*273a70aeSPeter Maydell 
27*273a70aeSPeter Maydell #include "qemu/osdep.h"
28*273a70aeSPeter Maydell #include "qemu/units.h"
29*273a70aeSPeter Maydell #include "qapi/error.h"
30*273a70aeSPeter Maydell #include "exec/address-spaces.h"
31*273a70aeSPeter Maydell #include "cpu.h"
32*273a70aeSPeter Maydell #include "hw/boards.h"
33*273a70aeSPeter Maydell #include "hw/arm/boot.h"
34*273a70aeSPeter Maydell 
35*273a70aeSPeter Maydell /* Define the layout of RAM and ROM in a board */
36*273a70aeSPeter Maydell typedef struct RAMInfo {
37*273a70aeSPeter Maydell     const char *name;
38*273a70aeSPeter Maydell     hwaddr base;
39*273a70aeSPeter Maydell     hwaddr size;
40*273a70aeSPeter Maydell     int mrindex; /* index into rams[]; -1 for the system RAM block */
41*273a70aeSPeter Maydell     int flags;
42*273a70aeSPeter Maydell } RAMInfo;
43*273a70aeSPeter Maydell 
44*273a70aeSPeter Maydell /*
45*273a70aeSPeter Maydell  * The MPS3 DDR is 3GiB, but on a 32-bit host QEMU doesn't permit
46*273a70aeSPeter Maydell  * emulation of that much guest RAM, so artificially make it smaller.
47*273a70aeSPeter Maydell  */
48*273a70aeSPeter Maydell #if HOST_LONG_BITS == 32
49*273a70aeSPeter Maydell #define MPS3_DDR_SIZE (1 * GiB)
50*273a70aeSPeter Maydell #else
51*273a70aeSPeter Maydell #define MPS3_DDR_SIZE (3 * GiB)
52*273a70aeSPeter Maydell #endif
53*273a70aeSPeter Maydell 
54*273a70aeSPeter Maydell /*
55*273a70aeSPeter Maydell  * Flag values:
56*273a70aeSPeter Maydell  * IS_MAIN: this is the main machine RAM
57*273a70aeSPeter Maydell  * IS_ROM: this area is read-only
58*273a70aeSPeter Maydell  */
59*273a70aeSPeter Maydell #define IS_MAIN 1
60*273a70aeSPeter Maydell #define IS_ROM 2
61*273a70aeSPeter Maydell 
62*273a70aeSPeter Maydell #define MPS3R_RAM_MAX 9
63*273a70aeSPeter Maydell 
64*273a70aeSPeter Maydell typedef enum MPS3RFPGAType {
65*273a70aeSPeter Maydell     FPGA_AN536,
66*273a70aeSPeter Maydell } MPS3RFPGAType;
67*273a70aeSPeter Maydell 
68*273a70aeSPeter Maydell struct MPS3RMachineClass {
69*273a70aeSPeter Maydell     MachineClass parent;
70*273a70aeSPeter Maydell     MPS3RFPGAType fpga_type;
71*273a70aeSPeter Maydell     const RAMInfo *raminfo;
72*273a70aeSPeter Maydell };
73*273a70aeSPeter Maydell 
74*273a70aeSPeter Maydell struct MPS3RMachineState {
75*273a70aeSPeter Maydell     MachineState parent;
76*273a70aeSPeter Maydell     MemoryRegion ram[MPS3R_RAM_MAX];
77*273a70aeSPeter Maydell };
78*273a70aeSPeter Maydell 
79*273a70aeSPeter Maydell #define TYPE_MPS3R_MACHINE "mps3r"
80*273a70aeSPeter Maydell #define TYPE_MPS3R_AN536_MACHINE MACHINE_TYPE_NAME("mps3-an536")
81*273a70aeSPeter Maydell 
82*273a70aeSPeter Maydell OBJECT_DECLARE_TYPE(MPS3RMachineState, MPS3RMachineClass, MPS3R_MACHINE)
83*273a70aeSPeter Maydell 
84*273a70aeSPeter Maydell static const RAMInfo an536_raminfo[] = {
85*273a70aeSPeter Maydell     {
86*273a70aeSPeter Maydell         .name = "ATCM",
87*273a70aeSPeter Maydell         .base = 0x00000000,
88*273a70aeSPeter Maydell         .size = 0x00008000,
89*273a70aeSPeter Maydell         .mrindex = 0,
90*273a70aeSPeter Maydell     }, {
91*273a70aeSPeter Maydell         /* We model the QSPI flash as simple ROM for now */
92*273a70aeSPeter Maydell         .name = "QSPI",
93*273a70aeSPeter Maydell         .base = 0x08000000,
94*273a70aeSPeter Maydell         .size = 0x00800000,
95*273a70aeSPeter Maydell         .flags = IS_ROM,
96*273a70aeSPeter Maydell         .mrindex = 1,
97*273a70aeSPeter Maydell     }, {
98*273a70aeSPeter Maydell         .name = "BRAM",
99*273a70aeSPeter Maydell         .base = 0x10000000,
100*273a70aeSPeter Maydell         .size = 0x00080000,
101*273a70aeSPeter Maydell         .mrindex = 2,
102*273a70aeSPeter Maydell     }, {
103*273a70aeSPeter Maydell         .name = "DDR",
104*273a70aeSPeter Maydell         .base = 0x20000000,
105*273a70aeSPeter Maydell         .size = MPS3_DDR_SIZE,
106*273a70aeSPeter Maydell         .mrindex = -1,
107*273a70aeSPeter Maydell     }, {
108*273a70aeSPeter Maydell         .name = "ATCM0",
109*273a70aeSPeter Maydell         .base = 0xee000000,
110*273a70aeSPeter Maydell         .size = 0x00008000,
111*273a70aeSPeter Maydell         .mrindex = 3,
112*273a70aeSPeter Maydell     }, {
113*273a70aeSPeter Maydell         .name = "BTCM0",
114*273a70aeSPeter Maydell         .base = 0xee100000,
115*273a70aeSPeter Maydell         .size = 0x00008000,
116*273a70aeSPeter Maydell         .mrindex = 4,
117*273a70aeSPeter Maydell     }, {
118*273a70aeSPeter Maydell         .name = "CTCM0",
119*273a70aeSPeter Maydell         .base = 0xee200000,
120*273a70aeSPeter Maydell         .size = 0x00008000,
121*273a70aeSPeter Maydell         .mrindex = 5,
122*273a70aeSPeter Maydell     }, {
123*273a70aeSPeter Maydell         .name = "ATCM1",
124*273a70aeSPeter Maydell         .base = 0xee400000,
125*273a70aeSPeter Maydell         .size = 0x00008000,
126*273a70aeSPeter Maydell         .mrindex = 6,
127*273a70aeSPeter Maydell     }, {
128*273a70aeSPeter Maydell         .name = "BTCM1",
129*273a70aeSPeter Maydell         .base = 0xee500000,
130*273a70aeSPeter Maydell         .size = 0x00008000,
131*273a70aeSPeter Maydell         .mrindex = 7,
132*273a70aeSPeter Maydell     }, {
133*273a70aeSPeter Maydell         .name = "CTCM1",
134*273a70aeSPeter Maydell         .base = 0xee600000,
135*273a70aeSPeter Maydell         .size = 0x00008000,
136*273a70aeSPeter Maydell         .mrindex = 8,
137*273a70aeSPeter Maydell     }, {
138*273a70aeSPeter Maydell         .name = NULL,
139*273a70aeSPeter Maydell     }
140*273a70aeSPeter Maydell };
141*273a70aeSPeter Maydell 
142*273a70aeSPeter Maydell static MemoryRegion *mr_for_raminfo(MPS3RMachineState *mms,
143*273a70aeSPeter Maydell                                     const RAMInfo *raminfo)
144*273a70aeSPeter Maydell {
145*273a70aeSPeter Maydell     /* Return an initialized MemoryRegion for the RAMInfo. */
146*273a70aeSPeter Maydell     MemoryRegion *ram;
147*273a70aeSPeter Maydell 
148*273a70aeSPeter Maydell     if (raminfo->mrindex < 0) {
149*273a70aeSPeter Maydell         /* Means this RAMInfo is for QEMU's "system memory" */
150*273a70aeSPeter Maydell         MachineState *machine = MACHINE(mms);
151*273a70aeSPeter Maydell         assert(!(raminfo->flags & IS_ROM));
152*273a70aeSPeter Maydell         return machine->ram;
153*273a70aeSPeter Maydell     }
154*273a70aeSPeter Maydell 
155*273a70aeSPeter Maydell     assert(raminfo->mrindex < MPS3R_RAM_MAX);
156*273a70aeSPeter Maydell     ram = &mms->ram[raminfo->mrindex];
157*273a70aeSPeter Maydell 
158*273a70aeSPeter Maydell     memory_region_init_ram(ram, NULL, raminfo->name,
159*273a70aeSPeter Maydell                            raminfo->size, &error_fatal);
160*273a70aeSPeter Maydell     if (raminfo->flags & IS_ROM) {
161*273a70aeSPeter Maydell         memory_region_set_readonly(ram, true);
162*273a70aeSPeter Maydell     }
163*273a70aeSPeter Maydell     return ram;
164*273a70aeSPeter Maydell }
165*273a70aeSPeter Maydell 
166*273a70aeSPeter Maydell static void mps3r_common_init(MachineState *machine)
167*273a70aeSPeter Maydell {
168*273a70aeSPeter Maydell     MPS3RMachineState *mms = MPS3R_MACHINE(machine);
169*273a70aeSPeter Maydell     MPS3RMachineClass *mmc = MPS3R_MACHINE_GET_CLASS(mms);
170*273a70aeSPeter Maydell     MemoryRegion *sysmem = get_system_memory();
171*273a70aeSPeter Maydell 
172*273a70aeSPeter Maydell     for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) {
173*273a70aeSPeter Maydell         MemoryRegion *mr = mr_for_raminfo(mms, ri);
174*273a70aeSPeter Maydell         memory_region_add_subregion(sysmem, ri->base, mr);
175*273a70aeSPeter Maydell     }
176*273a70aeSPeter Maydell }
177*273a70aeSPeter Maydell 
178*273a70aeSPeter Maydell static void mps3r_set_default_ram_info(MPS3RMachineClass *mmc)
179*273a70aeSPeter Maydell {
180*273a70aeSPeter Maydell     /*
181*273a70aeSPeter Maydell      * Set mc->default_ram_size and default_ram_id from the
182*273a70aeSPeter Maydell      * information in mmc->raminfo.
183*273a70aeSPeter Maydell      */
184*273a70aeSPeter Maydell     MachineClass *mc = MACHINE_CLASS(mmc);
185*273a70aeSPeter Maydell     const RAMInfo *p;
186*273a70aeSPeter Maydell 
187*273a70aeSPeter Maydell     for (p = mmc->raminfo; p->name; p++) {
188*273a70aeSPeter Maydell         if (p->mrindex < 0) {
189*273a70aeSPeter Maydell             /* Found the entry for "system memory" */
190*273a70aeSPeter Maydell             mc->default_ram_size = p->size;
191*273a70aeSPeter Maydell             mc->default_ram_id = p->name;
192*273a70aeSPeter Maydell             return;
193*273a70aeSPeter Maydell         }
194*273a70aeSPeter Maydell     }
195*273a70aeSPeter Maydell     g_assert_not_reached();
196*273a70aeSPeter Maydell }
197*273a70aeSPeter Maydell 
198*273a70aeSPeter Maydell static void mps3r_class_init(ObjectClass *oc, void *data)
199*273a70aeSPeter Maydell {
200*273a70aeSPeter Maydell     MachineClass *mc = MACHINE_CLASS(oc);
201*273a70aeSPeter Maydell 
202*273a70aeSPeter Maydell     mc->init = mps3r_common_init;
203*273a70aeSPeter Maydell }
204*273a70aeSPeter Maydell 
205*273a70aeSPeter Maydell static void mps3r_an536_class_init(ObjectClass *oc, void *data)
206*273a70aeSPeter Maydell {
207*273a70aeSPeter Maydell     MachineClass *mc = MACHINE_CLASS(oc);
208*273a70aeSPeter Maydell     MPS3RMachineClass *mmc = MPS3R_MACHINE_CLASS(oc);
209*273a70aeSPeter Maydell     static const char * const valid_cpu_types[] = {
210*273a70aeSPeter Maydell         ARM_CPU_TYPE_NAME("cortex-r52"),
211*273a70aeSPeter Maydell         NULL
212*273a70aeSPeter Maydell     };
213*273a70aeSPeter Maydell 
214*273a70aeSPeter Maydell     mc->desc = "ARM MPS3 with AN536 FPGA image for Cortex-R52";
215*273a70aeSPeter Maydell     mc->default_cpus = 2;
216*273a70aeSPeter Maydell     mc->min_cpus = mc->default_cpus;
217*273a70aeSPeter Maydell     mc->max_cpus = mc->default_cpus;
218*273a70aeSPeter Maydell     mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-r52");
219*273a70aeSPeter Maydell     mc->valid_cpu_types = valid_cpu_types;
220*273a70aeSPeter Maydell     mmc->raminfo = an536_raminfo;
221*273a70aeSPeter Maydell     mps3r_set_default_ram_info(mmc);
222*273a70aeSPeter Maydell }
223*273a70aeSPeter Maydell 
224*273a70aeSPeter Maydell static const TypeInfo mps3r_machine_types[] = {
225*273a70aeSPeter Maydell     {
226*273a70aeSPeter Maydell         .name = TYPE_MPS3R_MACHINE,
227*273a70aeSPeter Maydell         .parent = TYPE_MACHINE,
228*273a70aeSPeter Maydell         .abstract = true,
229*273a70aeSPeter Maydell         .instance_size = sizeof(MPS3RMachineState),
230*273a70aeSPeter Maydell         .class_size = sizeof(MPS3RMachineClass),
231*273a70aeSPeter Maydell         .class_init = mps3r_class_init,
232*273a70aeSPeter Maydell     }, {
233*273a70aeSPeter Maydell         .name = TYPE_MPS3R_AN536_MACHINE,
234*273a70aeSPeter Maydell         .parent = TYPE_MPS3R_MACHINE,
235*273a70aeSPeter Maydell         .class_init = mps3r_an536_class_init,
236*273a70aeSPeter Maydell     },
237*273a70aeSPeter Maydell };
238*273a70aeSPeter Maydell 
239*273a70aeSPeter Maydell DEFINE_TYPES(mps3r_machine_types);
240