xref: /openbmc/qemu/hw/arm/xlnx-versal-virt.c (revision 8bd8b04a)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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