hw/riscv: Initial support for Microchip PolarFire SoC Icicle Kit board
[qemu/ar7.git] / hw / riscv / microchip_pfsoc.c
blobd946b2aae552266a78d5d867001d22f2eb812af7
1 /*
2 * QEMU RISC-V Board Compatible with Microchip PolarFire SoC Icicle Kit
4 * Copyright (c) 2020 Wind River Systems, Inc.
6 * Author:
7 * Bin Meng <bin.meng@windriver.com>
9 * Provides a board compatible with the Microchip PolarFire SoC Icicle Kit
11 * 0) CLINT (Core Level Interruptor)
12 * 1) PLIC (Platform Level Interrupt Controller)
13 * 2) eNVM (Embedded Non-Volatile Memory)
15 * This board currently generates devicetree dynamically that indicates at least
16 * two harts and up to five harts.
18 * This program is free software; you can redistribute it and/or modify it
19 * under the terms and conditions of the GNU General Public License,
20 * version 2 or later, as published by the Free Software Foundation.
22 * This program is distributed in the hope it will be useful, but WITHOUT
23 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
25 * more details.
27 * You should have received a copy of the GNU General Public License along with
28 * this program. If not, see <http://www.gnu.org/licenses/>.
31 #include "qemu/osdep.h"
32 #include "qemu/error-report.h"
33 #include "qemu/log.h"
34 #include "qemu/units.h"
35 #include "qemu/cutils.h"
36 #include "qapi/error.h"
37 #include "hw/boards.h"
38 #include "hw/irq.h"
39 #include "hw/loader.h"
40 #include "hw/sysbus.h"
41 #include "hw/cpu/cluster.h"
42 #include "target/riscv/cpu.h"
43 #include "hw/misc/unimp.h"
44 #include "hw/riscv/boot.h"
45 #include "hw/riscv/riscv_hart.h"
46 #include "hw/riscv/sifive_clint.h"
47 #include "hw/riscv/sifive_plic.h"
48 #include "hw/riscv/microchip_pfsoc.h"
51 * The BIOS image used by this machine is called Hart Software Services (HSS).
52 * See https://github.com/polarfire-soc/hart-software-services
54 #define BIOS_FILENAME "hss.bin"
55 #define RESET_VECTOR 0x20220000
57 static const struct MemmapEntry {
58 hwaddr base;
59 hwaddr size;
60 } microchip_pfsoc_memmap[] = {
61 [MICROCHIP_PFSOC_DEBUG] = { 0x0, 0x1000 },
62 [MICROCHIP_PFSOC_E51_DTIM] = { 0x1000000, 0x2000 },
63 [MICROCHIP_PFSOC_BUSERR_UNIT0] = { 0x1700000, 0x1000 },
64 [MICROCHIP_PFSOC_BUSERR_UNIT1] = { 0x1701000, 0x1000 },
65 [MICROCHIP_PFSOC_BUSERR_UNIT2] = { 0x1702000, 0x1000 },
66 [MICROCHIP_PFSOC_BUSERR_UNIT3] = { 0x1703000, 0x1000 },
67 [MICROCHIP_PFSOC_BUSERR_UNIT4] = { 0x1704000, 0x1000 },
68 [MICROCHIP_PFSOC_CLINT] = { 0x2000000, 0x10000 },
69 [MICROCHIP_PFSOC_L2CC] = { 0x2010000, 0x1000 },
70 [MICROCHIP_PFSOC_L2LIM] = { 0x8000000, 0x2000000 },
71 [MICROCHIP_PFSOC_PLIC] = { 0xc000000, 0x4000000 },
72 [MICROCHIP_PFSOC_SYSREG] = { 0x20002000, 0x2000 },
73 [MICROCHIP_PFSOC_MPUCFG] = { 0x20005000, 0x1000 },
74 [MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 },
75 [MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 },
76 [MICROCHIP_PFSOC_IOSCB_CFG] = { 0x37080000, 0x1000 },
77 [MICROCHIP_PFSOC_DRAM] = { 0x80000000, 0x0 },
80 static void microchip_pfsoc_soc_instance_init(Object *obj)
82 MachineState *ms = MACHINE(qdev_get_machine());
83 MicrochipPFSoCState *s = MICROCHIP_PFSOC(obj);
85 object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER);
86 qdev_prop_set_uint32(DEVICE(&s->e_cluster), "cluster-id", 0);
88 object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", &s->e_cpus,
89 TYPE_RISCV_HART_ARRAY);
90 qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1);
91 qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0);
92 qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type",
93 TYPE_RISCV_CPU_SIFIVE_E51);
94 qdev_prop_set_uint64(DEVICE(&s->e_cpus), "resetvec", RESET_VECTOR);
96 object_initialize_child(obj, "u-cluster", &s->u_cluster, TYPE_CPU_CLUSTER);
97 qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1);
99 object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus,
100 TYPE_RISCV_HART_ARRAY);
101 qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
102 qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
103 qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type",
104 TYPE_RISCV_CPU_SIFIVE_U54);
105 qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", RESET_VECTOR);
108 static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
110 MachineState *ms = MACHINE(qdev_get_machine());
111 MicrochipPFSoCState *s = MICROCHIP_PFSOC(dev);
112 const struct MemmapEntry *memmap = microchip_pfsoc_memmap;
113 MemoryRegion *system_memory = get_system_memory();
114 MemoryRegion *e51_dtim_mem = g_new(MemoryRegion, 1);
115 MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
116 MemoryRegion *envm_data = g_new(MemoryRegion, 1);
117 char *plic_hart_config;
118 size_t plic_hart_config_len;
119 int i;
121 sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort);
122 sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort);
124 * The cluster must be realized after the RISC-V hart array container,
125 * as the container's CPU object is only created on realize, and the
126 * CPU must exist and have been parented into the cluster before the
127 * cluster is realized.
129 qdev_realize(DEVICE(&s->e_cluster), NULL, &error_abort);
130 qdev_realize(DEVICE(&s->u_cluster), NULL, &error_abort);
132 /* E51 DTIM */
133 memory_region_init_ram(e51_dtim_mem, NULL, "microchip.pfsoc.e51_dtim_mem",
134 memmap[MICROCHIP_PFSOC_E51_DTIM].size, &error_fatal);
135 memory_region_add_subregion(system_memory,
136 memmap[MICROCHIP_PFSOC_E51_DTIM].base,
137 e51_dtim_mem);
139 /* Bus Error Units */
140 create_unimplemented_device("microchip.pfsoc.buserr_unit0_mem",
141 memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].base,
142 memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].size);
143 create_unimplemented_device("microchip.pfsoc.buserr_unit1_mem",
144 memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].base,
145 memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].size);
146 create_unimplemented_device("microchip.pfsoc.buserr_unit2_mem",
147 memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].base,
148 memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].size);
149 create_unimplemented_device("microchip.pfsoc.buserr_unit3_mem",
150 memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].base,
151 memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].size);
152 create_unimplemented_device("microchip.pfsoc.buserr_unit4_mem",
153 memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].base,
154 memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size);
156 /* CLINT */
157 sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
158 memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
159 SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
161 /* L2 cache controller */
162 create_unimplemented_device("microchip.pfsoc.l2cc",
163 memmap[MICROCHIP_PFSOC_L2CC].base, memmap[MICROCHIP_PFSOC_L2CC].size);
166 * Add L2-LIM at reset size.
167 * This should be reduced in size as the L2 Cache Controller WayEnable
168 * register is incremented. Unfortunately I don't see a nice (or any) way
169 * to handle reducing or blocking out the L2 LIM while still allowing it
170 * be re returned to all enabled after a reset. For the time being, just
171 * leave it enabled all the time. This won't break anything, but will be
172 * too generous to misbehaving guests.
174 memory_region_init_ram(l2lim_mem, NULL, "microchip.pfsoc.l2lim",
175 memmap[MICROCHIP_PFSOC_L2LIM].size, &error_fatal);
176 memory_region_add_subregion(system_memory,
177 memmap[MICROCHIP_PFSOC_L2LIM].base,
178 l2lim_mem);
180 /* create PLIC hart topology configuration string */
181 plic_hart_config_len = (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1) *
182 ms->smp.cpus;
183 plic_hart_config = g_malloc0(plic_hart_config_len);
184 for (i = 0; i < ms->smp.cpus; i++) {
185 if (i != 0) {
186 strncat(plic_hart_config, "," MICROCHIP_PFSOC_PLIC_HART_CONFIG,
187 plic_hart_config_len);
188 } else {
189 strncat(plic_hart_config, "M", plic_hart_config_len);
191 plic_hart_config_len -= (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1);
194 /* PLIC */
195 s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
196 plic_hart_config, 0,
197 MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
198 MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
199 MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
200 MICROCHIP_PFSOC_PLIC_PENDING_BASE,
201 MICROCHIP_PFSOC_PLIC_ENABLE_BASE,
202 MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE,
203 MICROCHIP_PFSOC_PLIC_CONTEXT_BASE,
204 MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE,
205 memmap[MICROCHIP_PFSOC_PLIC].size);
206 g_free(plic_hart_config);
208 /* SYSREG */
209 create_unimplemented_device("microchip.pfsoc.sysreg",
210 memmap[MICROCHIP_PFSOC_SYSREG].base,
211 memmap[MICROCHIP_PFSOC_SYSREG].size);
213 /* MPUCFG */
214 create_unimplemented_device("microchip.pfsoc.mpucfg",
215 memmap[MICROCHIP_PFSOC_MPUCFG].base,
216 memmap[MICROCHIP_PFSOC_MPUCFG].size);
218 /* eNVM */
219 memory_region_init_rom(envm_data, OBJECT(dev), "microchip.pfsoc.envm.data",
220 memmap[MICROCHIP_PFSOC_ENVM_DATA].size,
221 &error_fatal);
222 memory_region_add_subregion(system_memory,
223 memmap[MICROCHIP_PFSOC_ENVM_DATA].base,
224 envm_data);
226 /* IOSCBCFG */
227 create_unimplemented_device("microchip.pfsoc.ioscb.cfg",
228 memmap[MICROCHIP_PFSOC_IOSCB_CFG].base,
229 memmap[MICROCHIP_PFSOC_IOSCB_CFG].size);
232 static void microchip_pfsoc_soc_class_init(ObjectClass *oc, void *data)
234 DeviceClass *dc = DEVICE_CLASS(oc);
236 dc->realize = microchip_pfsoc_soc_realize;
237 /* Reason: Uses serial_hds in realize function, thus can't be used twice */
238 dc->user_creatable = false;
241 static const TypeInfo microchip_pfsoc_soc_type_info = {
242 .name = TYPE_MICROCHIP_PFSOC,
243 .parent = TYPE_DEVICE,
244 .instance_size = sizeof(MicrochipPFSoCState),
245 .instance_init = microchip_pfsoc_soc_instance_init,
246 .class_init = microchip_pfsoc_soc_class_init,
249 static void microchip_pfsoc_soc_register_types(void)
251 type_register_static(&microchip_pfsoc_soc_type_info);
254 type_init(microchip_pfsoc_soc_register_types)
256 static void microchip_icicle_kit_machine_init(MachineState *machine)
258 MachineClass *mc = MACHINE_GET_CLASS(machine);
259 const struct MemmapEntry *memmap = microchip_pfsoc_memmap;
260 MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(machine);
261 MemoryRegion *system_memory = get_system_memory();
262 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
264 /* Sanity check on RAM size */
265 if (machine->ram_size < mc->default_ram_size) {
266 char *sz = size_to_str(mc->default_ram_size);
267 error_report("Invalid RAM size, should be bigger than %s", sz);
268 g_free(sz);
269 exit(EXIT_FAILURE);
272 /* Initialize SoC */
273 object_initialize_child(OBJECT(machine), "soc", &s->soc,
274 TYPE_MICROCHIP_PFSOC);
275 qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
277 /* Register RAM */
278 memory_region_init_ram(main_mem, NULL, "microchip.icicle.kit.ram",
279 machine->ram_size, &error_fatal);
280 memory_region_add_subregion(system_memory,
281 memmap[MICROCHIP_PFSOC_DRAM].base, main_mem);
283 /* Load the firmware */
284 riscv_find_and_load_firmware(machine, BIOS_FILENAME, RESET_VECTOR, NULL);
287 static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data)
289 MachineClass *mc = MACHINE_CLASS(oc);
291 mc->desc = "Microchip PolarFire SoC Icicle Kit";
292 mc->init = microchip_icicle_kit_machine_init;
293 mc->max_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT +
294 MICROCHIP_PFSOC_COMPUTE_CPU_COUNT;
295 mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1;
296 mc->default_cpus = mc->min_cpus;
297 mc->default_ram_size = 1 * GiB;
300 static const TypeInfo microchip_icicle_kit_machine_typeinfo = {
301 .name = MACHINE_TYPE_NAME("microchip-icicle-kit"),
302 .parent = TYPE_MACHINE,
303 .class_init = microchip_icicle_kit_machine_class_init,
304 .instance_size = sizeof(MicrochipIcicleKitState),
307 static void microchip_icicle_kit_machine_init_register_types(void)
309 type_register_static(&microchip_icicle_kit_machine_typeinfo);
312 type_init(microchip_icicle_kit_machine_init_register_types)