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