1 /*
2 * Xilinx Versal Virtual board.
3 *
4 * Copyright (c) 2018 Xilinx Inc.
5 * Written by Edgar E. Iglesias
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 or
9 * (at your option) any later version.
10 */
11
12 #include "qemu/osdep.h"
13 #include "qemu/error-report.h"
14 #include "qapi/error.h"
15 #include "sysemu/device_tree.h"
16 #include "hw/block/flash.h"
17 #include "hw/boards.h"
18 #include "hw/sysbus.h"
19 #include "hw/arm/fdt.h"
20 #include "hw/qdev-properties.h"
21 #include "hw/arm/xlnx-versal.h"
22 #include "hw/arm/boot.h"
23 #include "target/arm/multiprocessing.h"
24 #include "qom/object.h"
25
26 #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
27 OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
28
29 #define XLNX_VERSAL_NUM_OSPI_FLASH 4
30
31 struct VersalVirt {
32 MachineState parent_obj;
33
34 Versal soc;
35
36 void *fdt;
37 int fdt_size;
38 struct {
39 uint32_t gic;
40 uint32_t ethernet_phy[2];
41 uint32_t clk_125Mhz;
42 uint32_t clk_25Mhz;
43 uint32_t usb;
44 uint32_t dwc;
45 uint32_t canfd[2];
46 } phandle;
47 struct arm_boot_info binfo;
48
49 CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
50 struct {
51 bool secure;
52 } cfg;
53 char *ospi_model;
54 };
55
fdt_create(VersalVirt * s)56 static void fdt_create(VersalVirt *s)
57 {
58 MachineClass *mc = MACHINE_GET_CLASS(s);
59 int i;
60
61 s->fdt = create_device_tree(&s->fdt_size);
62 if (!s->fdt) {
63 error_report("create_device_tree() failed");
64 exit(1);
65 }
66
67 /* Allocate all phandles. */
68 s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
69 for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
70 s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
71 }
72 s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
73 s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
74
75 s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
76 s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
77 /* Create /chosen node for load_dtb. */
78 qemu_fdt_add_subnode(s->fdt, "/chosen");
79
80 /* Header */
81 qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
82 qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
83 qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
84 qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
85 qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
86 }
87
fdt_add_clk_node(VersalVirt * s,const char * name,unsigned int freq_hz,uint32_t phandle)88 static void fdt_add_clk_node(VersalVirt *s, const char *name,
89 unsigned int freq_hz, uint32_t phandle)
90 {
91 qemu_fdt_add_subnode(s->fdt, name);
92 qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
93 qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
94 qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
95 qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
96 qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
97 }
98
fdt_add_cpu_nodes(VersalVirt * s,uint32_t psci_conduit)99 static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
100 {
101 int i;
102
103 qemu_fdt_add_subnode(s->fdt, "/cpus");
104 qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
105 qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
106
107 for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
108 char *name = g_strdup_printf("/cpus/cpu@%d", i);
109 ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
110
111 qemu_fdt_add_subnode(s->fdt, name);
112 qemu_fdt_setprop_cell(s->fdt, name, "reg",
113 arm_cpu_mp_affinity(armcpu));
114 if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
115 qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
116 }
117 qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
118 qemu_fdt_setprop_string(s->fdt, name, "compatible",
119 armcpu->dtb_compatible);
120 g_free(name);
121 }
122 }
123
fdt_add_gic_nodes(VersalVirt * s)124 static void fdt_add_gic_nodes(VersalVirt *s)
125 {
126 char *nodename;
127
128 nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
129 qemu_fdt_add_subnode(s->fdt, nodename);
130 qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
131 qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
132 GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
133 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
134 qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
135 qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
136 2, MM_GIC_APU_DIST_MAIN,
137 2, MM_GIC_APU_DIST_MAIN_SIZE,
138 2, MM_GIC_APU_REDIST_0,
139 2, MM_GIC_APU_REDIST_0_SIZE);
140 qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
141 qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
142 g_free(nodename);
143 }
144
fdt_add_timer_nodes(VersalVirt * s)145 static void fdt_add_timer_nodes(VersalVirt *s)
146 {
147 const char compat[] = "arm,armv8-timer";
148 uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
149
150 qemu_fdt_add_subnode(s->fdt, "/timer");
151 qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
152 GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
153 GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
154 GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
155 GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
156 qemu_fdt_setprop(s->fdt, "/timer", "compatible",
157 compat, sizeof(compat));
158 }
159
fdt_add_usb_xhci_nodes(VersalVirt * s)160 static void fdt_add_usb_xhci_nodes(VersalVirt *s)
161 {
162 const char clocknames[] = "bus_clk\0ref_clk";
163 const char irq_name[] = "dwc_usb3";
164 const char compatVersalDWC3[] = "xlnx,versal-dwc3";
165 const char compatDWC3[] = "snps,dwc3";
166 char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
167
168 qemu_fdt_add_subnode(s->fdt, name);
169 qemu_fdt_setprop(s->fdt, name, "compatible",
170 compatVersalDWC3, sizeof(compatVersalDWC3));
171 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
172 2, MM_USB2_CTRL_REGS,
173 2, MM_USB2_CTRL_REGS_SIZE);
174 qemu_fdt_setprop(s->fdt, name, "clock-names",
175 clocknames, sizeof(clocknames));
176 qemu_fdt_setprop_cells(s->fdt, name, "clocks",
177 s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
178 qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
179 qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
180 qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
181 qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
182 g_free(name);
183
184 name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
185 MM_USB2_CTRL_REGS, MM_USB_0);
186 qemu_fdt_add_subnode(s->fdt, name);
187 qemu_fdt_setprop(s->fdt, name, "compatible",
188 compatDWC3, sizeof(compatDWC3));
189 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
190 2, MM_USB_0, 2, MM_USB_0_SIZE);
191 qemu_fdt_setprop(s->fdt, name, "interrupt-names",
192 irq_name, sizeof(irq_name));
193 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
194 GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
195 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
196 qemu_fdt_setprop_cell(s->fdt, name,
197 "snps,quirk-frame-length-adjustment", 0x20);
198 qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
199 qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
200 qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
201 qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
202 qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
203 qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
204 qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
205 qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
206 qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
207 g_free(name);
208 }
209
fdt_add_uart_nodes(VersalVirt * s)210 static void fdt_add_uart_nodes(VersalVirt *s)
211 {
212 uint64_t addrs[] = { MM_UART1, MM_UART0 };
213 unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
214 const char compat[] = "arm,pl011\0arm,sbsa-uart";
215 const char clocknames[] = "uartclk\0apb_pclk";
216 int i;
217
218 for (i = 0; i < ARRAY_SIZE(addrs); i++) {
219 char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
220 qemu_fdt_add_subnode(s->fdt, name);
221 qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
222 qemu_fdt_setprop_cells(s->fdt, name, "clocks",
223 s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
224 qemu_fdt_setprop(s->fdt, name, "clock-names",
225 clocknames, sizeof(clocknames));
226
227 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
228 GIC_FDT_IRQ_TYPE_SPI, irqs[i],
229 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
230 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
231 2, addrs[i], 2, 0x1000);
232 qemu_fdt_setprop(s->fdt, name, "compatible",
233 compat, sizeof(compat));
234 qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
235
236 if (addrs[i] == MM_UART0) {
237 /* Select UART0. */
238 qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
239 }
240 g_free(name);
241 }
242 }
243
fdt_add_canfd_nodes(VersalVirt * s)244 static void fdt_add_canfd_nodes(VersalVirt *s)
245 {
246 uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
247 uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
248 unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
249 const char clocknames[] = "can_clk\0s_axi_aclk";
250 int i;
251
252 /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
253 for (i = 0; i < ARRAY_SIZE(addrs); i++) {
254 char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
255 qemu_fdt_add_subnode(s->fdt, name);
256
257 qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
258 qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
259
260 qemu_fdt_setprop_cells(s->fdt, name, "clocks",
261 s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
262 qemu_fdt_setprop(s->fdt, name, "clock-names",
263 clocknames, sizeof(clocknames));
264 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
265 GIC_FDT_IRQ_TYPE_SPI, irqs[i],
266 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
267 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
268 2, addrs[i], 2, size[i]);
269 qemu_fdt_setprop_string(s->fdt, name, "compatible",
270 "xlnx,canfd-2.0");
271
272 g_free(name);
273 }
274 }
275
fdt_add_fixed_link_nodes(VersalVirt * s,char * gemname,uint32_t phandle)276 static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
277 uint32_t phandle)
278 {
279 char *name = g_strdup_printf("%s/fixed-link", gemname);
280
281 qemu_fdt_add_subnode(s->fdt, name);
282 qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
283 qemu_fdt_setprop(s->fdt, name, "full-duplex", NULL, 0);
284 qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
285 g_free(name);
286 }
287
fdt_add_gem_nodes(VersalVirt * s)288 static void fdt_add_gem_nodes(VersalVirt *s)
289 {
290 uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
291 unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
292 const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
293 const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
294 int i;
295
296 for (i = 0; i < ARRAY_SIZE(addrs); i++) {
297 char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
298 qemu_fdt_add_subnode(s->fdt, name);
299
300 fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
301 qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
302 qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
303 s->phandle.ethernet_phy[i]);
304 qemu_fdt_setprop_cells(s->fdt, name, "clocks",
305 s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
306 s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
307 qemu_fdt_setprop(s->fdt, name, "clock-names",
308 clocknames, sizeof(clocknames));
309 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
310 GIC_FDT_IRQ_TYPE_SPI, irqs[i],
311 GIC_FDT_IRQ_FLAGS_LEVEL_HI,
312 GIC_FDT_IRQ_TYPE_SPI, irqs[i],
313 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
314 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
315 2, addrs[i], 2, 0x1000);
316 qemu_fdt_setprop(s->fdt, name, "compatible",
317 compat_gem, sizeof(compat_gem));
318 qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
319 qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
320 g_free(name);
321 }
322 }
323
fdt_add_zdma_nodes(VersalVirt * s)324 static void fdt_add_zdma_nodes(VersalVirt *s)
325 {
326 const char clocknames[] = "clk_main\0clk_apb";
327 const char compat[] = "xlnx,zynqmp-dma-1.0";
328 int i;
329
330 for (i = XLNX_VERSAL_NR_ADMAS - 1; i >= 0; i--) {
331 uint64_t addr = MM_ADMA_CH0 + MM_ADMA_CH0_SIZE * i;
332 char *name = g_strdup_printf("/dma@%" PRIx64, addr);
333
334 qemu_fdt_add_subnode(s->fdt, name);
335
336 qemu_fdt_setprop_cell(s->fdt, name, "xlnx,bus-width", 64);
337 qemu_fdt_setprop_cells(s->fdt, name, "clocks",
338 s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
339 qemu_fdt_setprop(s->fdt, name, "clock-names",
340 clocknames, sizeof(clocknames));
341 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
342 GIC_FDT_IRQ_TYPE_SPI, VERSAL_ADMA_IRQ_0 + i,
343 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
344 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
345 2, addr, 2, 0x1000);
346 qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
347 g_free(name);
348 }
349 }
350
fdt_add_sd_nodes(VersalVirt * s)351 static void fdt_add_sd_nodes(VersalVirt *s)
352 {
353 const char clocknames[] = "clk_xin\0clk_ahb";
354 const char compat[] = "arasan,sdhci-8.9a";
355 int i;
356
357 for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) {
358 uint64_t addr = MM_PMC_SD0 + MM_PMC_SD0_SIZE * i;
359 char *name = g_strdup_printf("/sdhci@%" PRIx64, addr);
360
361 qemu_fdt_add_subnode(s->fdt, name);
362
363 qemu_fdt_setprop_cells(s->fdt, name, "clocks",
364 s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
365 qemu_fdt_setprop(s->fdt, name, "clock-names",
366 clocknames, sizeof(clocknames));
367 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
368 GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i * 2,
369 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
370 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
371 2, addr, 2, MM_PMC_SD0_SIZE);
372 qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
373 g_free(name);
374 }
375 }
376
fdt_add_rtc_node(VersalVirt * s)377 static void fdt_add_rtc_node(VersalVirt *s)
378 {
379 const char compat[] = "xlnx,zynqmp-rtc";
380 const char interrupt_names[] = "alarm\0sec";
381 char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
382
383 qemu_fdt_add_subnode(s->fdt, name);
384
385 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
386 GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_ALARM_IRQ,
387 GIC_FDT_IRQ_FLAGS_LEVEL_HI,
388 GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_SECONDS_IRQ,
389 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
390 qemu_fdt_setprop(s->fdt, name, "interrupt-names",
391 interrupt_names, sizeof(interrupt_names));
392 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
393 2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
394 qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
395 g_free(name);
396 }
397
fdt_add_bbram_node(VersalVirt * s)398 static void fdt_add_bbram_node(VersalVirt *s)
399 {
400 const char compat[] = TYPE_XLNX_BBRAM;
401 const char interrupt_names[] = "bbram-error";
402 char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL);
403
404 qemu_fdt_add_subnode(s->fdt, name);
405
406 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
407 GIC_FDT_IRQ_TYPE_SPI, VERSAL_PMC_APB_IRQ,
408 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
409 qemu_fdt_setprop(s->fdt, name, "interrupt-names",
410 interrupt_names, sizeof(interrupt_names));
411 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
412 2, MM_PMC_BBRAM_CTRL,
413 2, MM_PMC_BBRAM_CTRL_SIZE);
414 qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
415 g_free(name);
416 }
417
fdt_add_efuse_ctrl_node(VersalVirt * s)418 static void fdt_add_efuse_ctrl_node(VersalVirt *s)
419 {
420 const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL;
421 const char interrupt_names[] = "pmc_efuse";
422 char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL);
423
424 qemu_fdt_add_subnode(s->fdt, name);
425
426 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
427 GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ,
428 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
429 qemu_fdt_setprop(s->fdt, name, "interrupt-names",
430 interrupt_names, sizeof(interrupt_names));
431 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
432 2, MM_PMC_EFUSE_CTRL,
433 2, MM_PMC_EFUSE_CTRL_SIZE);
434 qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
435 g_free(name);
436 }
437
fdt_add_efuse_cache_node(VersalVirt * s)438 static void fdt_add_efuse_cache_node(VersalVirt *s)
439 {
440 const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE;
441 char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x",
442 MM_PMC_EFUSE_CACHE);
443
444 qemu_fdt_add_subnode(s->fdt, name);
445
446 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
447 2, MM_PMC_EFUSE_CACHE,
448 2, MM_PMC_EFUSE_CACHE_SIZE);
449 qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
450 g_free(name);
451 }
452
fdt_nop_memory_nodes(void * fdt,Error ** errp)453 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
454 {
455 Error *err = NULL;
456 char **node_path;
457 int n = 0;
458
459 node_path = qemu_fdt_node_unit_path(fdt, "memory", &err);
460 if (err) {
461 error_propagate(errp, err);
462 return;
463 }
464 while (node_path[n]) {
465 if (g_str_has_prefix(node_path[n], "/memory")) {
466 qemu_fdt_nop_node(fdt, node_path[n]);
467 }
468 n++;
469 }
470 g_strfreev(node_path);
471 }
472
fdt_add_memory_nodes(VersalVirt * s,void * fdt,uint64_t ram_size)473 static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
474 {
475 /* Describes the various split DDR access regions. */
476 static const struct {
477 uint64_t base;
478 uint64_t size;
479 } addr_ranges[] = {
480 { MM_TOP_DDR, MM_TOP_DDR_SIZE },
481 { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
482 { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
483 { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
484 };
485 uint64_t mem_reg_prop[8] = {0};
486 uint64_t size = ram_size;
487 Error *err = NULL;
488 char *name;
489 int i;
490
491 fdt_nop_memory_nodes(fdt, &err);
492 if (err) {
493 error_report_err(err);
494 return;
495 }
496
497 name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
498 for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
499 uint64_t mapsize;
500
501 mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
502
503 mem_reg_prop[i * 2] = addr_ranges[i].base;
504 mem_reg_prop[i * 2 + 1] = mapsize;
505 size -= mapsize;
506 }
507 qemu_fdt_add_subnode(fdt, name);
508 qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
509
510 switch (i) {
511 case 1:
512 qemu_fdt_setprop_sized_cells(fdt, name, "reg",
513 2, mem_reg_prop[0],
514 2, mem_reg_prop[1]);
515 break;
516 case 2:
517 qemu_fdt_setprop_sized_cells(fdt, name, "reg",
518 2, mem_reg_prop[0],
519 2, mem_reg_prop[1],
520 2, mem_reg_prop[2],
521 2, mem_reg_prop[3]);
522 break;
523 case 3:
524 qemu_fdt_setprop_sized_cells(fdt, name, "reg",
525 2, mem_reg_prop[0],
526 2, mem_reg_prop[1],
527 2, mem_reg_prop[2],
528 2, mem_reg_prop[3],
529 2, mem_reg_prop[4],
530 2, mem_reg_prop[5]);
531 break;
532 case 4:
533 qemu_fdt_setprop_sized_cells(fdt, name, "reg",
534 2, mem_reg_prop[0],
535 2, mem_reg_prop[1],
536 2, mem_reg_prop[2],
537 2, mem_reg_prop[3],
538 2, mem_reg_prop[4],
539 2, mem_reg_prop[5],
540 2, mem_reg_prop[6],
541 2, mem_reg_prop[7]);
542 break;
543 default:
544 g_assert_not_reached();
545 }
546 g_free(name);
547 }
548
versal_virt_modify_dtb(const struct arm_boot_info * binfo,void * fdt)549 static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
550 void *fdt)
551 {
552 VersalVirt *s = container_of(binfo, VersalVirt, binfo);
553
554 fdt_add_memory_nodes(s, fdt, binfo->ram_size);
555 }
556
versal_virt_get_dtb(const struct arm_boot_info * binfo,int * fdt_size)557 static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
558 int *fdt_size)
559 {
560 const VersalVirt *board = container_of(binfo, VersalVirt, binfo);
561
562 *fdt_size = board->fdt_size;
563 return board->fdt;
564 }
565
566 #define NUM_VIRTIO_TRANSPORT 8
create_virtio_regions(VersalVirt * s)567 static void create_virtio_regions(VersalVirt *s)
568 {
569 int virtio_mmio_size = 0x200;
570 int i;
571
572 for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
573 char *name = g_strdup_printf("virtio%d", i);
574 hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
575 int irq = VERSAL_RSVD_IRQ_FIRST + i;
576 MemoryRegion *mr;
577 DeviceState *dev;
578 qemu_irq pic_irq;
579
580 pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
581 dev = qdev_new("virtio-mmio");
582 object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev));
583 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
584 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
585 mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
586 memory_region_add_subregion(&s->soc.mr_ps, base, mr);
587 g_free(name);
588 }
589
590 for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
591 hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
592 int irq = VERSAL_RSVD_IRQ_FIRST + i;
593 char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
594
595 qemu_fdt_add_subnode(s->fdt, name);
596 qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
597 qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
598 GIC_FDT_IRQ_TYPE_SPI, irq,
599 GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
600 qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
601 2, base, 2, virtio_mmio_size);
602 qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
603 g_free(name);
604 }
605 }
606
bbram_attach_drive(XlnxBBRam * dev)607 static void bbram_attach_drive(XlnxBBRam *dev)
608 {
609 DriveInfo *dinfo;
610 BlockBackend *blk;
611
612 dinfo = drive_get_by_index(IF_PFLASH, 0);
613 blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
614 if (blk) {
615 qdev_prop_set_drive(DEVICE(dev), "drive", blk);
616 }
617 }
618
efuse_attach_drive(XlnxEFuse * dev)619 static void efuse_attach_drive(XlnxEFuse *dev)
620 {
621 DriveInfo *dinfo;
622 BlockBackend *blk;
623
624 dinfo = drive_get_by_index(IF_PFLASH, 1);
625 blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
626 if (blk) {
627 qdev_prop_set_drive(DEVICE(dev), "drive", blk);
628 }
629 }
630
sd_plugin_card(SDHCIState * sd,DriveInfo * di)631 static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
632 {
633 BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
634 DeviceState *card;
635
636 card = qdev_new(TYPE_SD_CARD);
637 object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card));
638 qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
639 qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"),
640 &error_fatal);
641 }
642
versal_get_ospi_model(Object * obj,Error ** errp)643 static char *versal_get_ospi_model(Object *obj, Error **errp)
644 {
645 VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
646
647 return g_strdup(s->ospi_model);
648 }
649
versal_set_ospi_model(Object * obj,const char * value,Error ** errp)650 static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
651 {
652 VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
653
654 g_free(s->ospi_model);
655 s->ospi_model = g_strdup(value);
656 }
657
658
versal_virt_init(MachineState * machine)659 static void versal_virt_init(MachineState *machine)
660 {
661 VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
662 int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
663 int i;
664
665 /*
666 * If the user provides an Operating System to be loaded, we expect them
667 * to use the -kernel command line option.
668 *
669 * Users can load firmware or boot-loaders with the -device loader options.
670 *
671 * When loading an OS, we generate a dtb and let arm_load_kernel() select
672 * where it gets loaded. This dtb will be passed to the kernel in x0.
673 *
674 * If there's no -kernel option, we generate a DTB and place it at 0x1000
675 * for the bootloaders or firmware to pick up.
676 *
677 * If users want to provide their own DTB, they can use the -dtb option.
678 * These dtb's will have their memory nodes modified to match QEMU's
679 * selected ram_size option before they get passed to the kernel or fw.
680 *
681 * When loading an OS, we turn on QEMU's PSCI implementation with SMC
682 * as the PSCI conduit. When there's no -kernel, we assume the user
683 * provides EL3 firmware to handle PSCI.
684 *
685 * Even if the user provides a kernel filename, arm_load_kernel()
686 * may suppress PSCI if it's going to boot that guest code at EL3.
687 */
688 if (machine->kernel_filename) {
689 psci_conduit = QEMU_PSCI_CONDUIT_SMC;
690 }
691
692 object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,
693 TYPE_XLNX_VERSAL);
694 object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
695 &error_abort);
696 object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
697 &error_abort);
698 object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
699 &error_abort);
700 sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
701
702 fdt_create(s);
703 create_virtio_regions(s);
704 fdt_add_gem_nodes(s);
705 fdt_add_uart_nodes(s);
706 fdt_add_canfd_nodes(s);
707 fdt_add_gic_nodes(s);
708 fdt_add_timer_nodes(s);
709 fdt_add_zdma_nodes(s);
710 fdt_add_usb_xhci_nodes(s);
711 fdt_add_sd_nodes(s);
712 fdt_add_rtc_node(s);
713 fdt_add_bbram_node(s);
714 fdt_add_efuse_ctrl_node(s);
715 fdt_add_efuse_cache_node(s);
716 fdt_add_cpu_nodes(s, psci_conduit);
717 fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
718 fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
719
720 /* Make the APU cpu address space visible to virtio and other
721 * modules unaware of multiple address-spaces. */
722 memory_region_add_subregion_overlap(get_system_memory(),
723 0, &s->soc.fpd.apu.mr, 0);
724
725 /* Attach bbram backend, if given */
726 bbram_attach_drive(&s->soc.pmc.bbram);
727
728 /* Attach efuse backend, if given */
729 efuse_attach_drive(&s->soc.pmc.efuse);
730
731 /* Plugin SD cards. */
732 for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
733 sd_plugin_card(&s->soc.pmc.iou.sd[i],
734 drive_get(IF_SD, 0, i));
735 }
736
737 s->binfo.ram_size = machine->ram_size;
738 s->binfo.loader_start = 0x0;
739 s->binfo.get_dtb = versal_virt_get_dtb;
740 s->binfo.modify_dtb = versal_virt_modify_dtb;
741 s->binfo.psci_conduit = psci_conduit;
742 if (!machine->kernel_filename) {
743 /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
744 * Offset things by 4K. */
745 s->binfo.loader_start = 0x1000;
746 s->binfo.dtb_limit = 0x1000000;
747 }
748 arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
749
750 for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
751 BusState *spi_bus;
752 DeviceState *flash_dev;
753 ObjectClass *flash_klass;
754 qemu_irq cs_line;
755 DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
756
757 spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0");
758
759 if (s->ospi_model) {
760 flash_klass = object_class_by_name(s->ospi_model);
761 if (!flash_klass ||
762 object_class_is_abstract(flash_klass) ||
763 !object_class_dynamic_cast(flash_klass, TYPE_M25P80)) {
764 error_setg(&error_fatal, "'%s' is either abstract or"
765 " not a subtype of m25p80", s->ospi_model);
766 return;
767 }
768 }
769
770 flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
771
772 if (dinfo) {
773 qdev_prop_set_drive_err(flash_dev, "drive",
774 blk_by_legacy_dinfo(dinfo), &error_fatal);
775 }
776 qdev_prop_set_uint8(flash_dev, "cs", i);
777 qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
778
779 cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
780
781 sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi),
782 i + 1, cs_line);
783 }
784 }
785
versal_virt_machine_instance_init(Object * obj)786 static void versal_virt_machine_instance_init(Object *obj)
787 {
788 VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
789
790 /*
791 * User can set canbus0 and canbus1 properties to can-bus object and connect
792 * to socketcan(optional) interface via command line.
793 */
794 object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
795 (Object **)&s->canbus[0],
796 object_property_allow_set_link,
797 0);
798 object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
799 (Object **)&s->canbus[1],
800 object_property_allow_set_link,
801 0);
802 }
803
versal_virt_machine_finalize(Object * obj)804 static void versal_virt_machine_finalize(Object *obj)
805 {
806 VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
807
808 g_free(s->ospi_model);
809 }
810
versal_virt_machine_class_init(ObjectClass * oc,void * data)811 static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
812 {
813 MachineClass *mc = MACHINE_CLASS(oc);
814
815 mc->desc = "Xilinx Versal Virtual development board";
816 mc->init = versal_virt_init;
817 mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
818 mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
819 mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
820 mc->no_cdrom = true;
821 mc->default_ram_id = "ddr";
822 object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
823 versal_set_ospi_model);
824 object_class_property_set_description(oc, "ospi-flash",
825 "Change the OSPI Flash model");
826 }
827
828 static const TypeInfo versal_virt_machine_init_typeinfo = {
829 .name = TYPE_XLNX_VERSAL_VIRT_MACHINE,
830 .parent = TYPE_MACHINE,
831 .class_init = versal_virt_machine_class_init,
832 .instance_init = versal_virt_machine_instance_init,
833 .instance_size = sizeof(VersalVirt),
834 .instance_finalize = versal_virt_machine_finalize,
835 };
836
versal_virt_machine_init_register_types(void)837 static void versal_virt_machine_init_register_types(void)
838 {
839 type_register_static(&versal_virt_machine_init_typeinfo);
840 }
841
842 type_init(versal_virt_machine_init_register_types)
843
844