2 * QEMU RISC-V Board Compatible with Microchip PolarFire SoC Icicle Kit
4 * Copyright (c) 2020 Wind River Systems, Inc.
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
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"
34 #include "qemu/units.h"
35 #include "qemu/cutils.h"
36 #include "qapi/error.h"
37 #include "hw/boards.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
{
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
;
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
);
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
,
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
);
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
,
180 /* create PLIC hart topology configuration string */
181 plic_hart_config_len
= (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG
) + 1) *
183 plic_hart_config
= g_malloc0(plic_hart_config_len
);
184 for (i
= 0; i
< ms
->smp
.cpus
; i
++) {
186 strncat(plic_hart_config
, "," MICROCHIP_PFSOC_PLIC_HART_CONFIG
,
187 plic_hart_config_len
);
189 strncat(plic_hart_config
, "M", plic_hart_config_len
);
191 plic_hart_config_len
-= (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG
) + 1);
195 s
->plic
= sifive_plic_create(memmap
[MICROCHIP_PFSOC_PLIC
].base
,
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
);
209 create_unimplemented_device("microchip.pfsoc.sysreg",
210 memmap
[MICROCHIP_PFSOC_SYSREG
].base
,
211 memmap
[MICROCHIP_PFSOC_SYSREG
].size
);
214 create_unimplemented_device("microchip.pfsoc.mpucfg",
215 memmap
[MICROCHIP_PFSOC_MPUCFG
].base
,
216 memmap
[MICROCHIP_PFSOC_MPUCFG
].size
);
219 memory_region_init_rom(envm_data
, OBJECT(dev
), "microchip.pfsoc.envm.data",
220 memmap
[MICROCHIP_PFSOC_ENVM_DATA
].size
,
222 memory_region_add_subregion(system_memory
,
223 memmap
[MICROCHIP_PFSOC_ENVM_DATA
].base
,
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(µchip_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
);
273 object_initialize_child(OBJECT(machine
), "soc", &s
->soc
,
274 TYPE_MICROCHIP_PFSOC
);
275 qdev_realize(DEVICE(&s
->soc
), NULL
, &error_abort
);
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(µchip_icicle_kit_machine_typeinfo
);
312 type_init(microchip_icicle_kit_machine_init_register_types
)