]>
Commit | Line | Data |
---|---|---|
56f6e31e BM |
1 | /* |
2 | * QEMU RISC-V Board Compatible with Microchip PolarFire SoC Icicle Kit | |
3 | * | |
4 | * Copyright (c) 2020 Wind River Systems, Inc. | |
5 | * | |
6 | * Author: | |
7 | * Bin Meng <bin.meng@windriver.com> | |
8 | * | |
9 | * Provides a board compatible with the Microchip PolarFire SoC Icicle Kit | |
10 | * | |
11 | * 0) CLINT (Core Level Interruptor) | |
12 | * 1) PLIC (Platform Level Interrupt Controller) | |
13 | * 2) eNVM (Embedded Non-Volatile Memory) | |
8f2ac39d | 14 | * 3) MMUARTs (Multi-Mode UART) |
898dc008 | 15 | * 4) Cadence eMMC/SDHC controller and an SD card connected to it |
7124e27b | 16 | * 5) SiFive Platform DMA (Direct Memory Access Controller) |
47374b07 | 17 | * 6) GEM (Gigabit Ethernet MAC Controller) |
933f73f1 | 18 | * 7) DMC (DDR Memory Controller) |
e35d6179 | 19 | * 8) IOSCB modules |
56f6e31e BM |
20 | * |
21 | * This board currently generates devicetree dynamically that indicates at least | |
22 | * two harts and up to five harts. | |
23 | * | |
24 | * This program is free software; you can redistribute it and/or modify it | |
25 | * under the terms and conditions of the GNU General Public License, | |
26 | * version 2 or later, as published by the Free Software Foundation. | |
27 | * | |
28 | * This program is distributed in the hope it will be useful, but WITHOUT | |
29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
30 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
31 | * more details. | |
32 | * | |
33 | * You should have received a copy of the GNU General Public License along with | |
34 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
35 | */ | |
36 | ||
37 | #include "qemu/osdep.h" | |
38 | #include "qemu/error-report.h" | |
56f6e31e BM |
39 | #include "qemu/units.h" |
40 | #include "qemu/cutils.h" | |
41 | #include "qapi/error.h" | |
42 | #include "hw/boards.h" | |
56f6e31e BM |
43 | #include "hw/loader.h" |
44 | #include "hw/sysbus.h" | |
8f2ac39d | 45 | #include "chardev/char.h" |
56f6e31e BM |
46 | #include "hw/cpu/cluster.h" |
47 | #include "target/riscv/cpu.h" | |
48 | #include "hw/misc/unimp.h" | |
49 | #include "hw/riscv/boot.h" | |
50 | #include "hw/riscv/riscv_hart.h" | |
56f6e31e | 51 | #include "hw/riscv/microchip_pfsoc.h" |
cc63a182 | 52 | #include "hw/intc/riscv_aclint.h" |
84fcf3c1 | 53 | #include "hw/intc/sifive_plic.h" |
143897b5 | 54 | #include "sysemu/device_tree.h" |
8f2ac39d | 55 | #include "sysemu/sysemu.h" |
56f6e31e BM |
56 | |
57 | /* | |
58 | * The BIOS image used by this machine is called Hart Software Services (HSS). | |
59 | * See https://github.com/polarfire-soc/hart-software-services | |
60 | */ | |
61 | #define BIOS_FILENAME "hss.bin" | |
62 | #define RESET_VECTOR 0x20220000 | |
63 | ||
a47ef6e9 BM |
64 | /* CLINT timebase frequency */ |
65 | #define CLINT_TIMEBASE_FREQ 1000000 | |
66 | ||
47374b07 BM |
67 | /* GEM version */ |
68 | #define GEM_REVISION 0x0107010c | |
69 | ||
08b86e3b BM |
70 | /* |
71 | * The complete description of the whole PolarFire SoC memory map is scattered | |
72 | * in different documents. There are several places to look at for memory maps: | |
73 | * | |
74 | * 1 Chapter 11 "MSS Memory Map", in the doc "UG0880: PolarFire SoC FPGA | |
75 | * Microprocessor Subsystem (MSS) User Guide", which can be downloaded from | |
76 | * https://www.microsemi.com/document-portal/doc_download/ | |
77 | * 1244570-ug0880-polarfire-soc-fpga-microprocessor-subsystem-mss-user-guide, | |
78 | * describes the whole picture of the PolarFire SoC memory map. | |
79 | * | |
80 | * 2 A zip file for PolarFire soC memory map, which can be downloaded from | |
81 | * https://www.microsemi.com/document-portal/doc_download/ | |
82 | * 1244581-polarfire-soc-register-map, contains the following 2 major parts: | |
83 | * - Register Map/PF_SoC_RegMap_V1_1/pfsoc_regmap.htm | |
84 | * describes the complete integrated peripherals memory map | |
85 | * - Register Map/PF_SoC_RegMap_V1_1/MPFS250T/mpfs250t_ioscb_memmap_dri.htm | |
86 | * describes the complete IOSCB modules memory maps | |
87 | */ | |
73261285 | 88 | static const MemMapEntry microchip_pfsoc_memmap[] = { |
27c22b2d BM |
89 | [MICROCHIP_PFSOC_RSVD0] = { 0x0, 0x100 }, |
90 | [MICROCHIP_PFSOC_DEBUG] = { 0x100, 0xf00 }, | |
56f6e31e BM |
91 | [MICROCHIP_PFSOC_E51_DTIM] = { 0x1000000, 0x2000 }, |
92 | [MICROCHIP_PFSOC_BUSERR_UNIT0] = { 0x1700000, 0x1000 }, | |
93 | [MICROCHIP_PFSOC_BUSERR_UNIT1] = { 0x1701000, 0x1000 }, | |
94 | [MICROCHIP_PFSOC_BUSERR_UNIT2] = { 0x1702000, 0x1000 }, | |
95 | [MICROCHIP_PFSOC_BUSERR_UNIT3] = { 0x1703000, 0x1000 }, | |
96 | [MICROCHIP_PFSOC_BUSERR_UNIT4] = { 0x1704000, 0x1000 }, | |
97 | [MICROCHIP_PFSOC_CLINT] = { 0x2000000, 0x10000 }, | |
98 | [MICROCHIP_PFSOC_L2CC] = { 0x2010000, 0x1000 }, | |
7124e27b | 99 | [MICROCHIP_PFSOC_DMA] = { 0x3000000, 0x100000 }, |
56f6e31e BM |
100 | [MICROCHIP_PFSOC_L2LIM] = { 0x8000000, 0x2000000 }, |
101 | [MICROCHIP_PFSOC_PLIC] = { 0xc000000, 0x4000000 }, | |
8f2ac39d | 102 | [MICROCHIP_PFSOC_MMUART0] = { 0x20000000, 0x1000 }, |
56f6e31e BM |
103 | [MICROCHIP_PFSOC_SYSREG] = { 0x20002000, 0x2000 }, |
104 | [MICROCHIP_PFSOC_MPUCFG] = { 0x20005000, 0x1000 }, | |
933f73f1 | 105 | [MICROCHIP_PFSOC_DDR_SGMII_PHY] = { 0x20007000, 0x1000 }, |
898dc008 | 106 | [MICROCHIP_PFSOC_EMMC_SD] = { 0x20008000, 0x1000 }, |
933f73f1 | 107 | [MICROCHIP_PFSOC_DDR_CFG] = { 0x20080000, 0x40000 }, |
8f2ac39d BM |
108 | [MICROCHIP_PFSOC_MMUART1] = { 0x20100000, 0x1000 }, |
109 | [MICROCHIP_PFSOC_MMUART2] = { 0x20102000, 0x1000 }, | |
110 | [MICROCHIP_PFSOC_MMUART3] = { 0x20104000, 0x1000 }, | |
111 | [MICROCHIP_PFSOC_MMUART4] = { 0x20106000, 0x1000 }, | |
dfc973ec VW |
112 | [MICROCHIP_PFSOC_SPI0] = { 0x20108000, 0x1000 }, |
113 | [MICROCHIP_PFSOC_SPI1] = { 0x20109000, 0x1000 }, | |
90742c54 | 114 | [MICROCHIP_PFSOC_I2C1] = { 0x2010b000, 0x1000 }, |
47374b07 BM |
115 | [MICROCHIP_PFSOC_GEM0] = { 0x20110000, 0x2000 }, |
116 | [MICROCHIP_PFSOC_GEM1] = { 0x20112000, 0x2000 }, | |
ce908a2f BM |
117 | [MICROCHIP_PFSOC_GPIO0] = { 0x20120000, 0x1000 }, |
118 | [MICROCHIP_PFSOC_GPIO1] = { 0x20121000, 0x1000 }, | |
119 | [MICROCHIP_PFSOC_GPIO2] = { 0x20122000, 0x1000 }, | |
56f6e31e BM |
120 | [MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 }, |
121 | [MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 }, | |
dfc973ec | 122 | [MICROCHIP_PFSOC_QSPI_XIP] = { 0x21000000, 0x1000000 }, |
e35d6179 | 123 | [MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 }, |
d6150ace | 124 | [MICROCHIP_PFSOC_EMMC_SD_MUX] = { 0x4f000000, 0x4 }, |
f03100d7 BM |
125 | [MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 }, |
126 | [MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 }, | |
127 | [MICROCHIP_PFSOC_DRAM_HI] = { 0x1000000000, 0x0 }, | |
128 | [MICROCHIP_PFSOC_DRAM_HI_ALIAS] = { 0x1400000000, 0x0 }, | |
56f6e31e BM |
129 | }; |
130 | ||
131 | static void microchip_pfsoc_soc_instance_init(Object *obj) | |
132 | { | |
133 | MachineState *ms = MACHINE(qdev_get_machine()); | |
134 | MicrochipPFSoCState *s = MICROCHIP_PFSOC(obj); | |
135 | ||
136 | object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER); | |
137 | qdev_prop_set_uint32(DEVICE(&s->e_cluster), "cluster-id", 0); | |
138 | ||
139 | object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", &s->e_cpus, | |
140 | TYPE_RISCV_HART_ARRAY); | |
141 | qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1); | |
142 | qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0); | |
143 | qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type", | |
144 | TYPE_RISCV_CPU_SIFIVE_E51); | |
145 | qdev_prop_set_uint64(DEVICE(&s->e_cpus), "resetvec", RESET_VECTOR); | |
146 | ||
147 | object_initialize_child(obj, "u-cluster", &s->u_cluster, TYPE_CPU_CLUSTER); | |
148 | qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1); | |
149 | ||
150 | object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus, | |
151 | TYPE_RISCV_HART_ARRAY); | |
152 | qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); | |
153 | qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); | |
154 | qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", | |
155 | TYPE_RISCV_CPU_SIFIVE_U54); | |
156 | qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", RESET_VECTOR); | |
898dc008 | 157 | |
7124e27b BM |
158 | object_initialize_child(obj, "dma-controller", &s->dma, |
159 | TYPE_SIFIVE_PDMA); | |
160 | ||
cdd58c70 BM |
161 | object_initialize_child(obj, "sysreg", &s->sysreg, |
162 | TYPE_MCHP_PFSOC_SYSREG); | |
163 | ||
933f73f1 BM |
164 | object_initialize_child(obj, "ddr-sgmii-phy", &s->ddr_sgmii_phy, |
165 | TYPE_MCHP_PFSOC_DDR_SGMII_PHY); | |
166 | object_initialize_child(obj, "ddr-cfg", &s->ddr_cfg, | |
167 | TYPE_MCHP_PFSOC_DDR_CFG); | |
168 | ||
47374b07 BM |
169 | object_initialize_child(obj, "gem0", &s->gem0, TYPE_CADENCE_GEM); |
170 | object_initialize_child(obj, "gem1", &s->gem1, TYPE_CADENCE_GEM); | |
171 | ||
898dc008 BM |
172 | object_initialize_child(obj, "sd-controller", &s->sdhci, |
173 | TYPE_CADENCE_SDHCI); | |
e35d6179 BM |
174 | |
175 | object_initialize_child(obj, "ioscb", &s->ioscb, TYPE_MCHP_PFSOC_IOSCB); | |
56f6e31e BM |
176 | } |
177 | ||
178 | static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) | |
179 | { | |
180 | MachineState *ms = MACHINE(qdev_get_machine()); | |
181 | MicrochipPFSoCState *s = MICROCHIP_PFSOC(dev); | |
73261285 | 182 | const MemMapEntry *memmap = microchip_pfsoc_memmap; |
56f6e31e | 183 | MemoryRegion *system_memory = get_system_memory(); |
27c22b2d | 184 | MemoryRegion *rsvd0_mem = g_new(MemoryRegion, 1); |
56f6e31e BM |
185 | MemoryRegion *e51_dtim_mem = g_new(MemoryRegion, 1); |
186 | MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1); | |
187 | MemoryRegion *envm_data = g_new(MemoryRegion, 1); | |
dfc973ec | 188 | MemoryRegion *qspi_xip_mem = g_new(MemoryRegion, 1); |
56f6e31e BM |
189 | char *plic_hart_config; |
190 | size_t plic_hart_config_len; | |
47374b07 | 191 | NICInfo *nd; |
56f6e31e BM |
192 | int i; |
193 | ||
194 | sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort); | |
195 | sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort); | |
196 | /* | |
197 | * The cluster must be realized after the RISC-V hart array container, | |
198 | * as the container's CPU object is only created on realize, and the | |
199 | * CPU must exist and have been parented into the cluster before the | |
200 | * cluster is realized. | |
201 | */ | |
202 | qdev_realize(DEVICE(&s->e_cluster), NULL, &error_abort); | |
203 | qdev_realize(DEVICE(&s->u_cluster), NULL, &error_abort); | |
204 | ||
27c22b2d BM |
205 | /* Reserved Memory at address 0 */ |
206 | memory_region_init_ram(rsvd0_mem, NULL, "microchip.pfsoc.rsvd0_mem", | |
207 | memmap[MICROCHIP_PFSOC_RSVD0].size, &error_fatal); | |
208 | memory_region_add_subregion(system_memory, | |
209 | memmap[MICROCHIP_PFSOC_RSVD0].base, | |
210 | rsvd0_mem); | |
211 | ||
56f6e31e BM |
212 | /* E51 DTIM */ |
213 | memory_region_init_ram(e51_dtim_mem, NULL, "microchip.pfsoc.e51_dtim_mem", | |
214 | memmap[MICROCHIP_PFSOC_E51_DTIM].size, &error_fatal); | |
215 | memory_region_add_subregion(system_memory, | |
216 | memmap[MICROCHIP_PFSOC_E51_DTIM].base, | |
217 | e51_dtim_mem); | |
218 | ||
219 | /* Bus Error Units */ | |
220 | create_unimplemented_device("microchip.pfsoc.buserr_unit0_mem", | |
221 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].base, | |
222 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].size); | |
223 | create_unimplemented_device("microchip.pfsoc.buserr_unit1_mem", | |
224 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].base, | |
225 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].size); | |
226 | create_unimplemented_device("microchip.pfsoc.buserr_unit2_mem", | |
227 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].base, | |
228 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].size); | |
229 | create_unimplemented_device("microchip.pfsoc.buserr_unit3_mem", | |
230 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].base, | |
231 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].size); | |
232 | create_unimplemented_device("microchip.pfsoc.buserr_unit4_mem", | |
233 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].base, | |
234 | memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size); | |
235 | ||
236 | /* CLINT */ | |
b8fb878a AP |
237 | riscv_aclint_swi_create(memmap[MICROCHIP_PFSOC_CLINT].base, |
238 | 0, ms->smp.cpus, false); | |
239 | riscv_aclint_mtimer_create( | |
240 | memmap[MICROCHIP_PFSOC_CLINT].base + RISCV_ACLINT_SWI_SIZE, | |
241 | RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, | |
242 | RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, | |
a47ef6e9 | 243 | CLINT_TIMEBASE_FREQ, false); |
56f6e31e BM |
244 | |
245 | /* L2 cache controller */ | |
246 | create_unimplemented_device("microchip.pfsoc.l2cc", | |
247 | memmap[MICROCHIP_PFSOC_L2CC].base, memmap[MICROCHIP_PFSOC_L2CC].size); | |
248 | ||
249 | /* | |
250 | * Add L2-LIM at reset size. | |
251 | * This should be reduced in size as the L2 Cache Controller WayEnable | |
252 | * register is incremented. Unfortunately I don't see a nice (or any) way | |
253 | * to handle reducing or blocking out the L2 LIM while still allowing it | |
254 | * be re returned to all enabled after a reset. For the time being, just | |
255 | * leave it enabled all the time. This won't break anything, but will be | |
256 | * too generous to misbehaving guests. | |
257 | */ | |
258 | memory_region_init_ram(l2lim_mem, NULL, "microchip.pfsoc.l2lim", | |
259 | memmap[MICROCHIP_PFSOC_L2LIM].size, &error_fatal); | |
260 | memory_region_add_subregion(system_memory, | |
261 | memmap[MICROCHIP_PFSOC_L2LIM].base, | |
262 | l2lim_mem); | |
263 | ||
264 | /* create PLIC hart topology configuration string */ | |
265 | plic_hart_config_len = (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1) * | |
266 | ms->smp.cpus; | |
267 | plic_hart_config = g_malloc0(plic_hart_config_len); | |
268 | for (i = 0; i < ms->smp.cpus; i++) { | |
269 | if (i != 0) { | |
270 | strncat(plic_hart_config, "," MICROCHIP_PFSOC_PLIC_HART_CONFIG, | |
271 | plic_hart_config_len); | |
272 | } else { | |
273 | strncat(plic_hart_config, "M", plic_hart_config_len); | |
274 | } | |
275 | plic_hart_config_len -= (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1); | |
276 | } | |
277 | ||
278 | /* PLIC */ | |
279 | s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base, | |
f436ecc3 | 280 | plic_hart_config, ms->smp.cpus, 0, |
56f6e31e BM |
281 | MICROCHIP_PFSOC_PLIC_NUM_SOURCES, |
282 | MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES, | |
283 | MICROCHIP_PFSOC_PLIC_PRIORITY_BASE, | |
284 | MICROCHIP_PFSOC_PLIC_PENDING_BASE, | |
285 | MICROCHIP_PFSOC_PLIC_ENABLE_BASE, | |
286 | MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE, | |
287 | MICROCHIP_PFSOC_PLIC_CONTEXT_BASE, | |
288 | MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE, | |
289 | memmap[MICROCHIP_PFSOC_PLIC].size); | |
290 | g_free(plic_hart_config); | |
291 | ||
7124e27b BM |
292 | /* DMA */ |
293 | sysbus_realize(SYS_BUS_DEVICE(&s->dma), errp); | |
294 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->dma), 0, | |
295 | memmap[MICROCHIP_PFSOC_DMA].base); | |
296 | for (i = 0; i < SIFIVE_PDMA_IRQS; i++) { | |
297 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), i, | |
298 | qdev_get_gpio_in(DEVICE(s->plic), | |
299 | MICROCHIP_PFSOC_DMA_IRQ0 + i)); | |
300 | } | |
301 | ||
56f6e31e | 302 | /* SYSREG */ |
cdd58c70 BM |
303 | sysbus_realize(SYS_BUS_DEVICE(&s->sysreg), errp); |
304 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysreg), 0, | |
305 | memmap[MICROCHIP_PFSOC_SYSREG].base); | |
56f6e31e BM |
306 | |
307 | /* MPUCFG */ | |
308 | create_unimplemented_device("microchip.pfsoc.mpucfg", | |
309 | memmap[MICROCHIP_PFSOC_MPUCFG].base, | |
310 | memmap[MICROCHIP_PFSOC_MPUCFG].size); | |
311 | ||
933f73f1 BM |
312 | /* DDR SGMII PHY */ |
313 | sysbus_realize(SYS_BUS_DEVICE(&s->ddr_sgmii_phy), errp); | |
314 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_sgmii_phy), 0, | |
315 | memmap[MICROCHIP_PFSOC_DDR_SGMII_PHY].base); | |
316 | ||
317 | /* DDR CFG */ | |
318 | sysbus_realize(SYS_BUS_DEVICE(&s->ddr_cfg), errp); | |
319 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_cfg), 0, | |
320 | memmap[MICROCHIP_PFSOC_DDR_CFG].base); | |
321 | ||
898dc008 BM |
322 | /* SDHCI */ |
323 | sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp); | |
324 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0, | |
325 | memmap[MICROCHIP_PFSOC_EMMC_SD].base); | |
326 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, | |
327 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_EMMC_SD_IRQ)); | |
328 | ||
8f2ac39d BM |
329 | /* MMUARTs */ |
330 | s->serial0 = mchp_pfsoc_mmuart_create(system_memory, | |
331 | memmap[MICROCHIP_PFSOC_MMUART0].base, | |
332 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART0_IRQ), | |
333 | serial_hd(0)); | |
334 | s->serial1 = mchp_pfsoc_mmuart_create(system_memory, | |
335 | memmap[MICROCHIP_PFSOC_MMUART1].base, | |
336 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART1_IRQ), | |
337 | serial_hd(1)); | |
338 | s->serial2 = mchp_pfsoc_mmuart_create(system_memory, | |
339 | memmap[MICROCHIP_PFSOC_MMUART2].base, | |
340 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART2_IRQ), | |
341 | serial_hd(2)); | |
342 | s->serial3 = mchp_pfsoc_mmuart_create(system_memory, | |
343 | memmap[MICROCHIP_PFSOC_MMUART3].base, | |
344 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART3_IRQ), | |
345 | serial_hd(3)); | |
346 | s->serial4 = mchp_pfsoc_mmuart_create(system_memory, | |
347 | memmap[MICROCHIP_PFSOC_MMUART4].base, | |
348 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART4_IRQ), | |
349 | serial_hd(4)); | |
350 | ||
dfc973ec VW |
351 | /* SPI */ |
352 | create_unimplemented_device("microchip.pfsoc.spi0", | |
353 | memmap[MICROCHIP_PFSOC_SPI0].base, | |
354 | memmap[MICROCHIP_PFSOC_SPI0].size); | |
355 | create_unimplemented_device("microchip.pfsoc.spi1", | |
356 | memmap[MICROCHIP_PFSOC_SPI1].base, | |
357 | memmap[MICROCHIP_PFSOC_SPI1].size); | |
358 | ||
90742c54 BM |
359 | /* I2C1 */ |
360 | create_unimplemented_device("microchip.pfsoc.i2c1", | |
361 | memmap[MICROCHIP_PFSOC_I2C1].base, | |
362 | memmap[MICROCHIP_PFSOC_I2C1].size); | |
363 | ||
47374b07 BM |
364 | /* GEMs */ |
365 | ||
366 | nd = &nd_table[0]; | |
367 | if (nd->used) { | |
368 | qemu_check_nic_model(nd, TYPE_CADENCE_GEM); | |
369 | qdev_set_nic_properties(DEVICE(&s->gem0), nd); | |
370 | } | |
371 | nd = &nd_table[1]; | |
372 | if (nd->used) { | |
373 | qemu_check_nic_model(nd, TYPE_CADENCE_GEM); | |
374 | qdev_set_nic_properties(DEVICE(&s->gem1), nd); | |
375 | } | |
376 | ||
377 | object_property_set_int(OBJECT(&s->gem0), "revision", GEM_REVISION, errp); | |
378 | object_property_set_int(OBJECT(&s->gem0), "phy-addr", 8, errp); | |
379 | sysbus_realize(SYS_BUS_DEVICE(&s->gem0), errp); | |
380 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem0), 0, | |
381 | memmap[MICROCHIP_PFSOC_GEM0].base); | |
382 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem0), 0, | |
383 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_GEM0_IRQ)); | |
384 | ||
385 | object_property_set_int(OBJECT(&s->gem1), "revision", GEM_REVISION, errp); | |
386 | object_property_set_int(OBJECT(&s->gem1), "phy-addr", 9, errp); | |
387 | sysbus_realize(SYS_BUS_DEVICE(&s->gem1), errp); | |
388 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem1), 0, | |
389 | memmap[MICROCHIP_PFSOC_GEM1].base); | |
390 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem1), 0, | |
391 | qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_GEM1_IRQ)); | |
392 | ||
ce908a2f BM |
393 | /* GPIOs */ |
394 | create_unimplemented_device("microchip.pfsoc.gpio0", | |
395 | memmap[MICROCHIP_PFSOC_GPIO0].base, | |
396 | memmap[MICROCHIP_PFSOC_GPIO0].size); | |
397 | create_unimplemented_device("microchip.pfsoc.gpio1", | |
398 | memmap[MICROCHIP_PFSOC_GPIO1].base, | |
399 | memmap[MICROCHIP_PFSOC_GPIO1].size); | |
400 | create_unimplemented_device("microchip.pfsoc.gpio2", | |
401 | memmap[MICROCHIP_PFSOC_GPIO2].base, | |
402 | memmap[MICROCHIP_PFSOC_GPIO2].size); | |
403 | ||
56f6e31e BM |
404 | /* eNVM */ |
405 | memory_region_init_rom(envm_data, OBJECT(dev), "microchip.pfsoc.envm.data", | |
406 | memmap[MICROCHIP_PFSOC_ENVM_DATA].size, | |
407 | &error_fatal); | |
408 | memory_region_add_subregion(system_memory, | |
409 | memmap[MICROCHIP_PFSOC_ENVM_DATA].base, | |
410 | envm_data); | |
411 | ||
e35d6179 BM |
412 | /* IOSCB */ |
413 | sysbus_realize(SYS_BUS_DEVICE(&s->ioscb), errp); | |
414 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0, | |
415 | memmap[MICROCHIP_PFSOC_IOSCB].base); | |
dfc973ec | 416 | |
d6150ace BM |
417 | /* eMMC/SD mux */ |
418 | create_unimplemented_device("microchip.pfsoc.emmc_sd_mux", | |
419 | memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].base, | |
420 | memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].size); | |
421 | ||
dfc973ec VW |
422 | /* QSPI Flash */ |
423 | memory_region_init_rom(qspi_xip_mem, OBJECT(dev), | |
424 | "microchip.pfsoc.qspi_xip", | |
425 | memmap[MICROCHIP_PFSOC_QSPI_XIP].size, | |
426 | &error_fatal); | |
427 | memory_region_add_subregion(system_memory, | |
428 | memmap[MICROCHIP_PFSOC_QSPI_XIP].base, | |
429 | qspi_xip_mem); | |
56f6e31e BM |
430 | } |
431 | ||
432 | static void microchip_pfsoc_soc_class_init(ObjectClass *oc, void *data) | |
433 | { | |
434 | DeviceClass *dc = DEVICE_CLASS(oc); | |
435 | ||
436 | dc->realize = microchip_pfsoc_soc_realize; | |
437 | /* Reason: Uses serial_hds in realize function, thus can't be used twice */ | |
438 | dc->user_creatable = false; | |
439 | } | |
440 | ||
441 | static const TypeInfo microchip_pfsoc_soc_type_info = { | |
442 | .name = TYPE_MICROCHIP_PFSOC, | |
443 | .parent = TYPE_DEVICE, | |
444 | .instance_size = sizeof(MicrochipPFSoCState), | |
445 | .instance_init = microchip_pfsoc_soc_instance_init, | |
446 | .class_init = microchip_pfsoc_soc_class_init, | |
447 | }; | |
448 | ||
449 | static void microchip_pfsoc_soc_register_types(void) | |
450 | { | |
451 | type_register_static(µchip_pfsoc_soc_type_info); | |
452 | } | |
453 | ||
454 | type_init(microchip_pfsoc_soc_register_types) | |
455 | ||
456 | static void microchip_icicle_kit_machine_init(MachineState *machine) | |
457 | { | |
458 | MachineClass *mc = MACHINE_GET_CLASS(machine); | |
73261285 | 459 | const MemMapEntry *memmap = microchip_pfsoc_memmap; |
56f6e31e BM |
460 | MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(machine); |
461 | MemoryRegion *system_memory = get_system_memory(); | |
f03100d7 BM |
462 | MemoryRegion *mem_low = g_new(MemoryRegion, 1); |
463 | MemoryRegion *mem_low_alias = g_new(MemoryRegion, 1); | |
464 | MemoryRegion *mem_high = g_new(MemoryRegion, 1); | |
465 | MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1); | |
466 | uint64_t mem_high_size; | |
143897b5 BM |
467 | hwaddr firmware_load_addr; |
468 | const char *firmware_name; | |
469 | bool kernel_as_payload = false; | |
470 | target_ulong firmware_end_addr, kernel_start_addr; | |
471 | uint64_t kernel_entry; | |
472 | uint32_t fdt_load_addr; | |
898dc008 | 473 | DriveInfo *dinfo = drive_get_next(IF_SD); |
56f6e31e BM |
474 | |
475 | /* Sanity check on RAM size */ | |
476 | if (machine->ram_size < mc->default_ram_size) { | |
477 | char *sz = size_to_str(mc->default_ram_size); | |
478 | error_report("Invalid RAM size, should be bigger than %s", sz); | |
479 | g_free(sz); | |
480 | exit(EXIT_FAILURE); | |
481 | } | |
482 | ||
483 | /* Initialize SoC */ | |
484 | object_initialize_child(OBJECT(machine), "soc", &s->soc, | |
485 | TYPE_MICROCHIP_PFSOC); | |
486 | qdev_realize(DEVICE(&s->soc), NULL, &error_abort); | |
487 | ||
488 | /* Register RAM */ | |
f03100d7 BM |
489 | memory_region_init_ram(mem_low, NULL, "microchip.icicle.kit.ram_low", |
490 | memmap[MICROCHIP_PFSOC_DRAM_LO].size, | |
491 | &error_fatal); | |
492 | memory_region_init_alias(mem_low_alias, NULL, | |
493 | "microchip.icicle.kit.ram_low.alias", | |
494 | mem_low, 0, | |
495 | memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].size); | |
496 | memory_region_add_subregion(system_memory, | |
497 | memmap[MICROCHIP_PFSOC_DRAM_LO].base, | |
498 | mem_low); | |
56f6e31e | 499 | memory_region_add_subregion(system_memory, |
f03100d7 BM |
500 | memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].base, |
501 | mem_low_alias); | |
502 | ||
503 | mem_high_size = machine->ram_size - 1 * GiB; | |
504 | ||
505 | memory_region_init_ram(mem_high, NULL, "microchip.icicle.kit.ram_high", | |
506 | mem_high_size, &error_fatal); | |
507 | memory_region_init_alias(mem_high_alias, NULL, | |
508 | "microchip.icicle.kit.ram_high.alias", | |
509 | mem_high, 0, mem_high_size); | |
510 | memory_region_add_subregion(system_memory, | |
511 | memmap[MICROCHIP_PFSOC_DRAM_HI].base, | |
512 | mem_high); | |
513 | memory_region_add_subregion(system_memory, | |
514 | memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base, | |
515 | mem_high_alias); | |
56f6e31e | 516 | |
898dc008 BM |
517 | /* Attach an SD card */ |
518 | if (dinfo) { | |
519 | CadenceSDHCIState *sdhci = &(s->soc.sdhci); | |
520 | DeviceState *card = qdev_new(TYPE_SD_CARD); | |
521 | ||
522 | qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), | |
523 | &error_fatal); | |
524 | qdev_realize_and_unref(card, sdhci->bus, &error_fatal); | |
525 | } | |
143897b5 BM |
526 | |
527 | /* | |
528 | * We follow the following table to select which payload we execute. | |
529 | * | |
530 | * -bios | -kernel | payload | |
531 | * -------+------------+-------- | |
532 | * N | N | HSS | |
533 | * Y | don't care | HSS | |
534 | * N | Y | kernel | |
535 | * | |
536 | * This ensures backwards compatibility with how we used to expose -bios | |
537 | * to users but allows them to run through direct kernel booting as well. | |
538 | * | |
539 | * When -kernel is used for direct boot, -dtb must be present to provide | |
540 | * a valid device tree for the board, as we don't generate device tree. | |
541 | */ | |
542 | ||
543 | if (machine->kernel_filename && machine->dtb) { | |
544 | int fdt_size; | |
545 | machine->fdt = load_device_tree(machine->dtb, &fdt_size); | |
546 | if (!machine->fdt) { | |
547 | error_report("load_device_tree() failed"); | |
548 | exit(1); | |
549 | } | |
550 | ||
551 | firmware_name = RISCV64_BIOS_BIN; | |
552 | firmware_load_addr = memmap[MICROCHIP_PFSOC_DRAM_LO].base; | |
553 | kernel_as_payload = true; | |
554 | } | |
555 | ||
556 | if (!kernel_as_payload) { | |
557 | firmware_name = BIOS_FILENAME; | |
558 | firmware_load_addr = RESET_VECTOR; | |
559 | } | |
560 | ||
561 | /* Load the firmware */ | |
562 | firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name, | |
563 | firmware_load_addr, NULL); | |
564 | ||
565 | if (kernel_as_payload) { | |
566 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, | |
567 | firmware_end_addr); | |
568 | ||
569 | kernel_entry = riscv_load_kernel(machine->kernel_filename, | |
570 | kernel_start_addr, NULL); | |
571 | ||
572 | if (machine->initrd_filename) { | |
573 | hwaddr start; | |
574 | hwaddr end = riscv_load_initrd(machine->initrd_filename, | |
575 | machine->ram_size, kernel_entry, | |
576 | &start); | |
577 | qemu_fdt_setprop_cell(machine->fdt, "/chosen", | |
578 | "linux,initrd-start", start); | |
579 | qemu_fdt_setprop_cell(machine->fdt, "/chosen", | |
580 | "linux,initrd-end", end); | |
581 | } | |
582 | ||
583 | if (machine->kernel_cmdline) { | |
584 | qemu_fdt_setprop_string(machine->fdt, "/chosen", | |
585 | "bootargs", machine->kernel_cmdline); | |
586 | } | |
587 | ||
588 | /* Compute the fdt load address in dram */ | |
589 | fdt_load_addr = riscv_load_fdt(memmap[MICROCHIP_PFSOC_DRAM_LO].base, | |
590 | machine->ram_size, machine->fdt); | |
591 | /* Load the reset vector */ | |
592 | riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, firmware_load_addr, | |
593 | memmap[MICROCHIP_PFSOC_ENVM_DATA].base, | |
594 | memmap[MICROCHIP_PFSOC_ENVM_DATA].size, | |
595 | kernel_entry, fdt_load_addr, machine->fdt); | |
596 | } | |
56f6e31e BM |
597 | } |
598 | ||
599 | static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data) | |
600 | { | |
601 | MachineClass *mc = MACHINE_CLASS(oc); | |
602 | ||
603 | mc->desc = "Microchip PolarFire SoC Icicle Kit"; | |
604 | mc->init = microchip_icicle_kit_machine_init; | |
605 | mc->max_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + | |
606 | MICROCHIP_PFSOC_COMPUTE_CPU_COUNT; | |
607 | mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1; | |
608 | mc->default_cpus = mc->min_cpus; | |
f03100d7 BM |
609 | |
610 | /* | |
611 | * Map 513 MiB high memory, the mimimum required high memory size, because | |
612 | * HSS will do memory test against the high memory address range regardless | |
613 | * of physical memory installed. | |
614 | * | |
615 | * See memory_tests() in mss_ddr.c in the HSS source code. | |
616 | */ | |
617 | mc->default_ram_size = 1537 * MiB; | |
56f6e31e BM |
618 | } |
619 | ||
620 | static const TypeInfo microchip_icicle_kit_machine_typeinfo = { | |
621 | .name = MACHINE_TYPE_NAME("microchip-icicle-kit"), | |
622 | .parent = TYPE_MACHINE, | |
623 | .class_init = microchip_icicle_kit_machine_class_init, | |
624 | .instance_size = sizeof(MicrochipIcicleKitState), | |
625 | }; | |
626 | ||
627 | static void microchip_icicle_kit_machine_init_register_types(void) | |
628 | { | |
629 | type_register_static(µchip_icicle_kit_machine_typeinfo); | |
630 | } | |
631 | ||
632 | type_init(microchip_icicle_kit_machine_init_register_types) |