xref: /openbmc/qemu/hw/arm/xlnx-versal-virt.c (revision cc17f3b2ad036a315a943f1085fd29b9531f0cba)
16f16da53SEdgar E. Iglesias /*
26f16da53SEdgar E. Iglesias  * Xilinx Versal Virtual board.
36f16da53SEdgar E. Iglesias  *
46f16da53SEdgar E. Iglesias  * Copyright (c) 2018 Xilinx Inc.
56f16da53SEdgar E. Iglesias  * Written by Edgar E. Iglesias
66f16da53SEdgar E. Iglesias  *
76f16da53SEdgar E. Iglesias  * This program is free software; you can redistribute it and/or modify
86f16da53SEdgar E. Iglesias  * it under the terms of the GNU General Public License version 2 or
96f16da53SEdgar E. Iglesias  * (at your option) any later version.
106f16da53SEdgar E. Iglesias  */
116f16da53SEdgar E. Iglesias 
126f16da53SEdgar E. Iglesias #include "qemu/osdep.h"
136f16da53SEdgar E. Iglesias #include "qemu/error-report.h"
146f16da53SEdgar E. Iglesias #include "qapi/error.h"
156f16da53SEdgar E. Iglesias #include "sysemu/device_tree.h"
16a7538ca0SCédric Le Goater #include "hw/block/flash.h"
176f16da53SEdgar E. Iglesias #include "hw/boards.h"
186f16da53SEdgar E. Iglesias #include "hw/sysbus.h"
196f16da53SEdgar E. Iglesias #include "hw/arm/fdt.h"
203afec85cSEdgar E. Iglesias #include "hw/qdev-properties.h"
216f16da53SEdgar E. Iglesias #include "hw/arm/xlnx-versal.h"
22d95a3a75SPhilippe Mathieu-Daudé #include "hw/arm/boot.h"
23e2d8cf9bSPhilippe Mathieu-Daudé #include "target/arm/multiprocessing.h"
24db1015e9SEduardo Habkost #include "qom/object.h"
256f16da53SEdgar E. Iglesias 
266f16da53SEdgar E. Iglesias #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
278063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)
286f16da53SEdgar E. Iglesias 
294461f0fbSFrancisco Iglesias #define XLNX_VERSAL_NUM_OSPI_FLASH 4
304461f0fbSFrancisco Iglesias 
31db1015e9SEduardo Habkost struct VersalVirt {
326f16da53SEdgar E. Iglesias     MachineState parent_obj;
336f16da53SEdgar E. Iglesias 
346f16da53SEdgar E. Iglesias     Versal soc;
356f16da53SEdgar E. Iglesias 
366f16da53SEdgar E. Iglesias     void *fdt;
376f16da53SEdgar E. Iglesias     int fdt_size;
386f16da53SEdgar E. Iglesias     struct {
396f16da53SEdgar E. Iglesias         uint32_t gic;
406f16da53SEdgar E. Iglesias         uint32_t ethernet_phy[2];
416f16da53SEdgar E. Iglesias         uint32_t clk_125Mhz;
426f16da53SEdgar E. Iglesias         uint32_t clk_25Mhz;
43144677d4SVikram Garhwal         uint32_t usb;
44144677d4SVikram Garhwal         uint32_t dwc;
45042d6b02SVikram Garhwal         uint32_t canfd[2];
466f16da53SEdgar E. Iglesias     } phandle;
476f16da53SEdgar E. Iglesias     struct arm_boot_info binfo;
486f16da53SEdgar E. Iglesias 
49042d6b02SVikram Garhwal     CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
506f16da53SEdgar E. Iglesias     struct {
516f16da53SEdgar E. Iglesias         bool secure;
526f16da53SEdgar E. Iglesias     } cfg;
5306005459SSai Pavan Boddu     char *ospi_model;
54db1015e9SEduardo Habkost };
556f16da53SEdgar E. Iglesias 
fdt_create(VersalVirt * s)566f16da53SEdgar E. Iglesias static void fdt_create(VersalVirt *s)
576f16da53SEdgar E. Iglesias {
586f16da53SEdgar E. Iglesias     MachineClass *mc = MACHINE_GET_CLASS(s);
596f16da53SEdgar E. Iglesias     int i;
606f16da53SEdgar E. Iglesias 
616f16da53SEdgar E. Iglesias     s->fdt = create_device_tree(&s->fdt_size);
626f16da53SEdgar E. Iglesias     if (!s->fdt) {
636f16da53SEdgar E. Iglesias         error_report("create_device_tree() failed");
646f16da53SEdgar E. Iglesias         exit(1);
656f16da53SEdgar E. Iglesias     }
666f16da53SEdgar E. Iglesias 
676f16da53SEdgar E. Iglesias     /* Allocate all phandles.  */
686f16da53SEdgar E. Iglesias     s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
696f16da53SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
706f16da53SEdgar E. Iglesias         s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
716f16da53SEdgar E. Iglesias     }
726f16da53SEdgar E. Iglesias     s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
736f16da53SEdgar E. Iglesias     s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
746f16da53SEdgar E. Iglesias 
75144677d4SVikram Garhwal     s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
76144677d4SVikram Garhwal     s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
776f16da53SEdgar E. Iglesias     /* Create /chosen node for load_dtb.  */
786f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, "/chosen");
796f16da53SEdgar E. Iglesias 
806f16da53SEdgar E. Iglesias     /* Header */
816f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
826f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
836f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
846f16da53SEdgar E. Iglesias     qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
856f16da53SEdgar E. Iglesias     qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
866f16da53SEdgar E. Iglesias }
876f16da53SEdgar E. Iglesias 
fdt_add_clk_node(VersalVirt * s,const char * name,unsigned int freq_hz,uint32_t phandle)886f16da53SEdgar E. Iglesias static void fdt_add_clk_node(VersalVirt *s, const char *name,
896f16da53SEdgar E. Iglesias                              unsigned int freq_hz, uint32_t phandle)
906f16da53SEdgar E. Iglesias {
916f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, name);
926f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
936f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
946f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
956f16da53SEdgar E. Iglesias     qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
966f16da53SEdgar E. Iglesias     qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
976f16da53SEdgar E. Iglesias }
986f16da53SEdgar E. Iglesias 
fdt_add_cpu_nodes(VersalVirt * s,uint32_t psci_conduit)996f16da53SEdgar E. Iglesias static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
1006f16da53SEdgar E. Iglesias {
1016f16da53SEdgar E. Iglesias     int i;
1026f16da53SEdgar E. Iglesias 
1036f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, "/cpus");
1046f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
1056f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
1066f16da53SEdgar E. Iglesias 
1076f16da53SEdgar E. Iglesias     for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
1086f16da53SEdgar E. Iglesias         char *name = g_strdup_printf("/cpus/cpu@%d", i);
1096f16da53SEdgar E. Iglesias         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
1106f16da53SEdgar E. Iglesias 
1116f16da53SEdgar E. Iglesias         qemu_fdt_add_subnode(s->fdt, name);
112c4380f7bSRichard Henderson         qemu_fdt_setprop_cell(s->fdt, name, "reg",
113c4380f7bSRichard Henderson                               arm_cpu_mp_affinity(armcpu));
1146f16da53SEdgar E. Iglesias         if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
1156f16da53SEdgar E. Iglesias             qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
1166f16da53SEdgar E. Iglesias         }
1176f16da53SEdgar E. Iglesias         qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
1186f16da53SEdgar E. Iglesias         qemu_fdt_setprop_string(s->fdt, name, "compatible",
1196f16da53SEdgar E. Iglesias                                 armcpu->dtb_compatible);
1206f16da53SEdgar E. Iglesias         g_free(name);
1216f16da53SEdgar E. Iglesias     }
1226f16da53SEdgar E. Iglesias }
1236f16da53SEdgar E. Iglesias 
fdt_add_gic_nodes(VersalVirt * s)1246f16da53SEdgar E. Iglesias static void fdt_add_gic_nodes(VersalVirt *s)
1256f16da53SEdgar E. Iglesias {
1266f16da53SEdgar E. Iglesias     char *nodename;
1276f16da53SEdgar E. Iglesias 
1286f16da53SEdgar E. Iglesias     nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
1296f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, nodename);
1306f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
1316f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
1326f16da53SEdgar E. Iglesias                            GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
1336f16da53SEdgar E. Iglesias                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
1346f16da53SEdgar E. Iglesias     qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
1356f16da53SEdgar E. Iglesias     qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
1366f16da53SEdgar E. Iglesias                                  2, MM_GIC_APU_DIST_MAIN,
1376f16da53SEdgar E. Iglesias                                  2, MM_GIC_APU_DIST_MAIN_SIZE,
1386f16da53SEdgar E. Iglesias                                  2, MM_GIC_APU_REDIST_0,
1396f16da53SEdgar E. Iglesias                                  2, MM_GIC_APU_REDIST_0_SIZE);
1406f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
1416f16da53SEdgar E. Iglesias     qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
142aee63b07SEdgar E. Iglesias     g_free(nodename);
1436f16da53SEdgar E. Iglesias }
1446f16da53SEdgar E. Iglesias 
fdt_add_timer_nodes(VersalVirt * s)1456f16da53SEdgar E. Iglesias static void fdt_add_timer_nodes(VersalVirt *s)
1466f16da53SEdgar E. Iglesias {
1476f16da53SEdgar E. Iglesias     const char compat[] = "arm,armv8-timer";
1486f16da53SEdgar E. Iglesias     uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
1496f16da53SEdgar E. Iglesias 
1506f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, "/timer");
1516f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
1526f16da53SEdgar E. Iglesias             GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
1536f16da53SEdgar E. Iglesias             GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
1546f16da53SEdgar E. Iglesias             GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
1556f16da53SEdgar E. Iglesias             GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
1566f16da53SEdgar E. Iglesias     qemu_fdt_setprop(s->fdt, "/timer", "compatible",
1576f16da53SEdgar E. Iglesias                      compat, sizeof(compat));
1586f16da53SEdgar E. Iglesias }
1596f16da53SEdgar E. Iglesias 
fdt_add_usb_xhci_nodes(VersalVirt * s)160144677d4SVikram Garhwal static void fdt_add_usb_xhci_nodes(VersalVirt *s)
161144677d4SVikram Garhwal {
162144677d4SVikram Garhwal     const char clocknames[] = "bus_clk\0ref_clk";
163144677d4SVikram Garhwal     const char irq_name[] = "dwc_usb3";
164144677d4SVikram Garhwal     const char compatVersalDWC3[] = "xlnx,versal-dwc3";
165144677d4SVikram Garhwal     const char compatDWC3[] = "snps,dwc3";
166144677d4SVikram Garhwal     char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
167144677d4SVikram Garhwal 
168144677d4SVikram Garhwal     qemu_fdt_add_subnode(s->fdt, name);
169144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "compatible",
170144677d4SVikram Garhwal                          compatVersalDWC3, sizeof(compatVersalDWC3));
171144677d4SVikram Garhwal     qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
172144677d4SVikram Garhwal                                  2, MM_USB2_CTRL_REGS,
173144677d4SVikram Garhwal                                  2, MM_USB2_CTRL_REGS_SIZE);
174144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "clock-names",
175144677d4SVikram Garhwal                          clocknames, sizeof(clocknames));
176144677d4SVikram Garhwal     qemu_fdt_setprop_cells(s->fdt, name, "clocks",
177144677d4SVikram Garhwal                                s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
178144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
179144677d4SVikram Garhwal     qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
180144677d4SVikram Garhwal     qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
181144677d4SVikram Garhwal     qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
182144677d4SVikram Garhwal     g_free(name);
183144677d4SVikram Garhwal 
184144677d4SVikram Garhwal     name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
185144677d4SVikram Garhwal                            MM_USB2_CTRL_REGS, MM_USB_0);
186144677d4SVikram Garhwal     qemu_fdt_add_subnode(s->fdt, name);
187144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "compatible",
188144677d4SVikram Garhwal                      compatDWC3, sizeof(compatDWC3));
189144677d4SVikram Garhwal     qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
190144677d4SVikram Garhwal                                  2, MM_USB_0, 2, MM_USB_0_SIZE);
191144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "interrupt-names",
192144677d4SVikram Garhwal                      irq_name, sizeof(irq_name));
193144677d4SVikram Garhwal     qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
194144677d4SVikram Garhwal                                GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
195144677d4SVikram Garhwal                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
196144677d4SVikram Garhwal     qemu_fdt_setprop_cell(s->fdt, name,
197144677d4SVikram Garhwal                           "snps,quirk-frame-length-adjustment", 0x20);
198144677d4SVikram Garhwal     qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
199144677d4SVikram Garhwal     qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
200144677d4SVikram Garhwal     qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
201144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
202144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
203144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
204144677d4SVikram Garhwal     qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
205144677d4SVikram Garhwal     qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
206144677d4SVikram Garhwal     qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
207144677d4SVikram Garhwal     g_free(name);
208144677d4SVikram Garhwal }
209144677d4SVikram Garhwal 
fdt_add_uart_nodes(VersalVirt * s)2106f16da53SEdgar E. Iglesias static void fdt_add_uart_nodes(VersalVirt *s)
2116f16da53SEdgar E. Iglesias {
2126f16da53SEdgar E. Iglesias     uint64_t addrs[] = { MM_UART1, MM_UART0 };
2136f16da53SEdgar E. Iglesias     unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
2146f16da53SEdgar E. Iglesias     const char compat[] = "arm,pl011\0arm,sbsa-uart";
2156f16da53SEdgar E. Iglesias     const char clocknames[] = "uartclk\0apb_pclk";
2166f16da53SEdgar E. Iglesias     int i;
2176f16da53SEdgar E. Iglesias 
2186f16da53SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(addrs); i++) {
2196f16da53SEdgar E. Iglesias         char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
2206f16da53SEdgar E. Iglesias         qemu_fdt_add_subnode(s->fdt, name);
2216f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
2226f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "clocks",
2236f16da53SEdgar E. Iglesias                                s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
2246f16da53SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "clock-names",
2256f16da53SEdgar E. Iglesias                          clocknames, sizeof(clocknames));
2266f16da53SEdgar E. Iglesias 
2276f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
2286f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_TYPE_SPI, irqs[i],
2296f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
2306f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
2316f16da53SEdgar E. Iglesias                                      2, addrs[i], 2, 0x1000);
2326f16da53SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "compatible",
2336f16da53SEdgar E. Iglesias                          compat, sizeof(compat));
2346f16da53SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
2356f16da53SEdgar E. Iglesias 
2366f16da53SEdgar E. Iglesias         if (addrs[i] == MM_UART0) {
2376f16da53SEdgar E. Iglesias             /* Select UART0.  */
2386f16da53SEdgar E. Iglesias             qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
2396f16da53SEdgar E. Iglesias         }
2406f16da53SEdgar E. Iglesias         g_free(name);
2416f16da53SEdgar E. Iglesias     }
2426f16da53SEdgar E. Iglesias }
2436f16da53SEdgar E. Iglesias 
fdt_add_canfd_nodes(VersalVirt * s)244042d6b02SVikram Garhwal static void fdt_add_canfd_nodes(VersalVirt *s)
245042d6b02SVikram Garhwal {
246042d6b02SVikram Garhwal     uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
247042d6b02SVikram Garhwal     uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
248042d6b02SVikram Garhwal     unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
249042d6b02SVikram Garhwal     const char clocknames[] = "can_clk\0s_axi_aclk";
250042d6b02SVikram Garhwal     int i;
251042d6b02SVikram Garhwal 
252042d6b02SVikram Garhwal     /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
253042d6b02SVikram Garhwal     for (i = 0; i < ARRAY_SIZE(addrs); i++) {
254042d6b02SVikram Garhwal         char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
255042d6b02SVikram Garhwal         qemu_fdt_add_subnode(s->fdt, name);
256042d6b02SVikram Garhwal 
257042d6b02SVikram Garhwal         qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
258042d6b02SVikram Garhwal         qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
259042d6b02SVikram Garhwal 
260042d6b02SVikram Garhwal         qemu_fdt_setprop_cells(s->fdt, name, "clocks",
261042d6b02SVikram Garhwal                                s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
262042d6b02SVikram Garhwal         qemu_fdt_setprop(s->fdt, name, "clock-names",
263042d6b02SVikram Garhwal                          clocknames, sizeof(clocknames));
264042d6b02SVikram Garhwal         qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
265042d6b02SVikram Garhwal                                GIC_FDT_IRQ_TYPE_SPI, irqs[i],
266042d6b02SVikram Garhwal                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
267042d6b02SVikram Garhwal         qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
268042d6b02SVikram Garhwal                                      2, addrs[i], 2, size[i]);
269042d6b02SVikram Garhwal         qemu_fdt_setprop_string(s->fdt, name, "compatible",
270042d6b02SVikram Garhwal                                 "xlnx,canfd-2.0");
271042d6b02SVikram Garhwal 
272042d6b02SVikram Garhwal         g_free(name);
273042d6b02SVikram Garhwal     }
274042d6b02SVikram Garhwal }
275042d6b02SVikram Garhwal 
fdt_add_fixed_link_nodes(VersalVirt * s,char * gemname,uint32_t phandle)2766f16da53SEdgar E. Iglesias static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
2776f16da53SEdgar E. Iglesias                                      uint32_t phandle)
2786f16da53SEdgar E. Iglesias {
2796f16da53SEdgar E. Iglesias     char *name = g_strdup_printf("%s/fixed-link", gemname);
2806f16da53SEdgar E. Iglesias 
2816f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, name);
2826f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
2836f16da53SEdgar E. Iglesias     qemu_fdt_setprop(s->fdt, name, "full-duplex", NULL, 0);
2846f16da53SEdgar E. Iglesias     qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
2856f16da53SEdgar E. Iglesias     g_free(name);
2866f16da53SEdgar E. Iglesias }
2876f16da53SEdgar E. Iglesias 
fdt_add_gem_nodes(VersalVirt * s)2886f16da53SEdgar E. Iglesias static void fdt_add_gem_nodes(VersalVirt *s)
2896f16da53SEdgar E. Iglesias {
2906f16da53SEdgar E. Iglesias     uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
2916f16da53SEdgar E. Iglesias     unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
2926f16da53SEdgar E. Iglesias     const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
2936f16da53SEdgar E. Iglesias     const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
2946f16da53SEdgar E. Iglesias     int i;
2956f16da53SEdgar E. Iglesias 
2966f16da53SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(addrs); i++) {
2976f16da53SEdgar E. Iglesias         char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
2986f16da53SEdgar E. Iglesias         qemu_fdt_add_subnode(s->fdt, name);
2996f16da53SEdgar E. Iglesias 
3006f16da53SEdgar E. Iglesias         fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
3016f16da53SEdgar E. Iglesias         qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
3026f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
3036f16da53SEdgar E. Iglesias                               s->phandle.ethernet_phy[i]);
3046f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "clocks",
3056f16da53SEdgar E. Iglesias                                s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
30607fe5bb5SEdgar E. Iglesias                                s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
3076f16da53SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "clock-names",
3086f16da53SEdgar E. Iglesias                          clocknames, sizeof(clocknames));
3096f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
3106f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_TYPE_SPI, irqs[i],
3116f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_FLAGS_LEVEL_HI,
3126f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_TYPE_SPI, irqs[i],
3136f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
3146f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
3156f16da53SEdgar E. Iglesias                                      2, addrs[i], 2, 0x1000);
3166f16da53SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "compatible",
3176f16da53SEdgar E. Iglesias                          compat_gem, sizeof(compat_gem));
3186f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
3196f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
3206f16da53SEdgar E. Iglesias         g_free(name);
3216f16da53SEdgar E. Iglesias     }
3226f16da53SEdgar E. Iglesias }
3236f16da53SEdgar E. Iglesias 
fdt_add_zdma_nodes(VersalVirt * s)324ce5f4f01SEdgar E. Iglesias static void fdt_add_zdma_nodes(VersalVirt *s)
325ce5f4f01SEdgar E. Iglesias {
326ce5f4f01SEdgar E. Iglesias     const char clocknames[] = "clk_main\0clk_apb";
327ce5f4f01SEdgar E. Iglesias     const char compat[] = "xlnx,zynqmp-dma-1.0";
328ce5f4f01SEdgar E. Iglesias     int i;
329ce5f4f01SEdgar E. Iglesias 
330ce5f4f01SEdgar E. Iglesias     for (i = XLNX_VERSAL_NR_ADMAS - 1; i >= 0; i--) {
331ce5f4f01SEdgar E. Iglesias         uint64_t addr = MM_ADMA_CH0 + MM_ADMA_CH0_SIZE * i;
332ce5f4f01SEdgar E. Iglesias         char *name = g_strdup_printf("/dma@%" PRIx64, addr);
333ce5f4f01SEdgar E. Iglesias 
334ce5f4f01SEdgar E. Iglesias         qemu_fdt_add_subnode(s->fdt, name);
335ce5f4f01SEdgar E. Iglesias 
336ce5f4f01SEdgar E. Iglesias         qemu_fdt_setprop_cell(s->fdt, name, "xlnx,bus-width", 64);
337ce5f4f01SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "clocks",
338ce5f4f01SEdgar E. Iglesias                                s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
339ce5f4f01SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "clock-names",
340ce5f4f01SEdgar E. Iglesias                          clocknames, sizeof(clocknames));
341ce5f4f01SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
342ce5f4f01SEdgar E. Iglesias                                GIC_FDT_IRQ_TYPE_SPI, VERSAL_ADMA_IRQ_0 + i,
343ce5f4f01SEdgar E. Iglesias                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
344ce5f4f01SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
345ce5f4f01SEdgar E. Iglesias                                      2, addr, 2, 0x1000);
346ce5f4f01SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
347ce5f4f01SEdgar E. Iglesias         g_free(name);
348ce5f4f01SEdgar E. Iglesias     }
349ce5f4f01SEdgar E. Iglesias }
350ce5f4f01SEdgar E. Iglesias 
fdt_add_sd_nodes(VersalVirt * s)3513afec85cSEdgar E. Iglesias static void fdt_add_sd_nodes(VersalVirt *s)
3523afec85cSEdgar E. Iglesias {
3533afec85cSEdgar E. Iglesias     const char clocknames[] = "clk_xin\0clk_ahb";
3543afec85cSEdgar E. Iglesias     const char compat[] = "arasan,sdhci-8.9a";
3553afec85cSEdgar E. Iglesias     int i;
3563afec85cSEdgar E. Iglesias 
3573afec85cSEdgar E. Iglesias     for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) {
3583afec85cSEdgar E. Iglesias         uint64_t addr = MM_PMC_SD0 + MM_PMC_SD0_SIZE * i;
3593afec85cSEdgar E. Iglesias         char *name = g_strdup_printf("/sdhci@%" PRIx64, addr);
3603afec85cSEdgar E. Iglesias 
3613afec85cSEdgar E. Iglesias         qemu_fdt_add_subnode(s->fdt, name);
3623afec85cSEdgar E. Iglesias 
3633afec85cSEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "clocks",
3643afec85cSEdgar E. Iglesias                                s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
3653afec85cSEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "clock-names",
3663afec85cSEdgar E. Iglesias                          clocknames, sizeof(clocknames));
3673afec85cSEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
3683afec85cSEdgar E. Iglesias                                GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i * 2,
3693afec85cSEdgar E. Iglesias                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
3703afec85cSEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
3713afec85cSEdgar E. Iglesias                                      2, addr, 2, MM_PMC_SD0_SIZE);
3723afec85cSEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
3733afec85cSEdgar E. Iglesias         g_free(name);
3743afec85cSEdgar E. Iglesias     }
3753afec85cSEdgar E. Iglesias }
3763afec85cSEdgar E. Iglesias 
fdt_add_rtc_node(VersalVirt * s)3772aca5284SEdgar E. Iglesias static void fdt_add_rtc_node(VersalVirt *s)
3782aca5284SEdgar E. Iglesias {
3792aca5284SEdgar E. Iglesias     const char compat[] = "xlnx,zynqmp-rtc";
3802aca5284SEdgar E. Iglesias     const char interrupt_names[] = "alarm\0sec";
3812aca5284SEdgar E. Iglesias     char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
3822aca5284SEdgar E. Iglesias 
3832aca5284SEdgar E. Iglesias     qemu_fdt_add_subnode(s->fdt, name);
3842aca5284SEdgar E. Iglesias 
3852aca5284SEdgar E. Iglesias     qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
3862aca5284SEdgar E. Iglesias                            GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_ALARM_IRQ,
3872aca5284SEdgar E. Iglesias                            GIC_FDT_IRQ_FLAGS_LEVEL_HI,
3882aca5284SEdgar E. Iglesias                            GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_SECONDS_IRQ,
3892aca5284SEdgar E. Iglesias                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
3902aca5284SEdgar E. Iglesias     qemu_fdt_setprop(s->fdt, name, "interrupt-names",
3912aca5284SEdgar E. Iglesias                      interrupt_names, sizeof(interrupt_names));
3922aca5284SEdgar E. Iglesias     qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
3932aca5284SEdgar E. Iglesias                                  2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
3942aca5284SEdgar E. Iglesias     qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
3952aca5284SEdgar E. Iglesias     g_free(name);
3962aca5284SEdgar E. Iglesias }
3972aca5284SEdgar E. Iglesias 
fdt_add_bbram_node(VersalVirt * s)398393185bcSTong Ho static void fdt_add_bbram_node(VersalVirt *s)
399393185bcSTong Ho {
400393185bcSTong Ho     const char compat[] = TYPE_XLNX_BBRAM;
401393185bcSTong Ho     const char interrupt_names[] = "bbram-error";
402393185bcSTong Ho     char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL);
403393185bcSTong Ho 
404393185bcSTong Ho     qemu_fdt_add_subnode(s->fdt, name);
405393185bcSTong Ho 
406393185bcSTong Ho     qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
4079a6d4918SFrancisco Iglesias                            GIC_FDT_IRQ_TYPE_SPI, VERSAL_PMC_APB_IRQ,
408393185bcSTong Ho                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
409393185bcSTong Ho     qemu_fdt_setprop(s->fdt, name, "interrupt-names",
410393185bcSTong Ho                      interrupt_names, sizeof(interrupt_names));
411393185bcSTong Ho     qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
412393185bcSTong Ho                                  2, MM_PMC_BBRAM_CTRL,
413393185bcSTong Ho                                  2, MM_PMC_BBRAM_CTRL_SIZE);
414393185bcSTong Ho     qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
415393185bcSTong Ho     g_free(name);
416393185bcSTong Ho }
417393185bcSTong Ho 
fdt_add_efuse_ctrl_node(VersalVirt * s)4185f4910ffSTong Ho static void fdt_add_efuse_ctrl_node(VersalVirt *s)
4195f4910ffSTong Ho {
4205f4910ffSTong Ho     const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL;
4215f4910ffSTong Ho     const char interrupt_names[] = "pmc_efuse";
4225f4910ffSTong Ho     char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL);
4235f4910ffSTong Ho 
4245f4910ffSTong Ho     qemu_fdt_add_subnode(s->fdt, name);
4255f4910ffSTong Ho 
4265f4910ffSTong Ho     qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
4275f4910ffSTong Ho                            GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ,
4285f4910ffSTong Ho                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
4295f4910ffSTong Ho     qemu_fdt_setprop(s->fdt, name, "interrupt-names",
4305f4910ffSTong Ho                      interrupt_names, sizeof(interrupt_names));
4315f4910ffSTong Ho     qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
4325f4910ffSTong Ho                                  2, MM_PMC_EFUSE_CTRL,
4335f4910ffSTong Ho                                  2, MM_PMC_EFUSE_CTRL_SIZE);
4345f4910ffSTong Ho     qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
4355f4910ffSTong Ho     g_free(name);
4365f4910ffSTong Ho }
4375f4910ffSTong Ho 
fdt_add_efuse_cache_node(VersalVirt * s)4385f4910ffSTong Ho static void fdt_add_efuse_cache_node(VersalVirt *s)
4395f4910ffSTong Ho {
4405f4910ffSTong Ho     const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE;
4415f4910ffSTong Ho     char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x",
4425f4910ffSTong Ho                                  MM_PMC_EFUSE_CACHE);
4435f4910ffSTong Ho 
4445f4910ffSTong Ho     qemu_fdt_add_subnode(s->fdt, name);
4455f4910ffSTong Ho 
4465f4910ffSTong Ho     qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
4475f4910ffSTong Ho                                  2, MM_PMC_EFUSE_CACHE,
4485f4910ffSTong Ho                                  2, MM_PMC_EFUSE_CACHE_SIZE);
4495f4910ffSTong Ho     qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
4505f4910ffSTong Ho     g_free(name);
4515f4910ffSTong Ho }
4525f4910ffSTong Ho 
fdt_nop_memory_nodes(void * fdt,Error ** errp)4536f16da53SEdgar E. Iglesias static void fdt_nop_memory_nodes(void *fdt, Error **errp)
4546f16da53SEdgar E. Iglesias {
4556f16da53SEdgar E. Iglesias     Error *err = NULL;
4566f16da53SEdgar E. Iglesias     char **node_path;
4576f16da53SEdgar E. Iglesias     int n = 0;
4586f16da53SEdgar E. Iglesias 
4596f16da53SEdgar E. Iglesias     node_path = qemu_fdt_node_unit_path(fdt, "memory", &err);
4606f16da53SEdgar E. Iglesias     if (err) {
4616f16da53SEdgar E. Iglesias         error_propagate(errp, err);
4626f16da53SEdgar E. Iglesias         return;
4636f16da53SEdgar E. Iglesias     }
4646f16da53SEdgar E. Iglesias     while (node_path[n]) {
4656f16da53SEdgar E. Iglesias         if (g_str_has_prefix(node_path[n], "/memory")) {
4666f16da53SEdgar E. Iglesias             qemu_fdt_nop_node(fdt, node_path[n]);
4676f16da53SEdgar E. Iglesias         }
4686f16da53SEdgar E. Iglesias         n++;
4696f16da53SEdgar E. Iglesias     }
4706f16da53SEdgar E. Iglesias     g_strfreev(node_path);
4716f16da53SEdgar E. Iglesias }
4726f16da53SEdgar E. Iglesias 
fdt_add_memory_nodes(VersalVirt * s,void * fdt,uint64_t ram_size)4736f16da53SEdgar E. Iglesias static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
4746f16da53SEdgar E. Iglesias {
4756f16da53SEdgar E. Iglesias     /* Describes the various split DDR access regions.  */
4766f16da53SEdgar E. Iglesias     static const struct {
4776f16da53SEdgar E. Iglesias         uint64_t base;
4786f16da53SEdgar E. Iglesias         uint64_t size;
4796f16da53SEdgar E. Iglesias     } addr_ranges[] = {
4806f16da53SEdgar E. Iglesias         { MM_TOP_DDR, MM_TOP_DDR_SIZE },
4816f16da53SEdgar E. Iglesias         { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
4826f16da53SEdgar E. Iglesias         { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
4836f16da53SEdgar E. Iglesias         { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
4846f16da53SEdgar E. Iglesias     };
4856f16da53SEdgar E. Iglesias     uint64_t mem_reg_prop[8] = {0};
4866f16da53SEdgar E. Iglesias     uint64_t size = ram_size;
4876f16da53SEdgar E. Iglesias     Error *err = NULL;
4886f16da53SEdgar E. Iglesias     char *name;
4896f16da53SEdgar E. Iglesias     int i;
4906f16da53SEdgar E. Iglesias 
4916f16da53SEdgar E. Iglesias     fdt_nop_memory_nodes(fdt, &err);
4926f16da53SEdgar E. Iglesias     if (err) {
4936f16da53SEdgar E. Iglesias         error_report_err(err);
4946f16da53SEdgar E. Iglesias         return;
4956f16da53SEdgar E. Iglesias     }
4966f16da53SEdgar E. Iglesias 
4976f16da53SEdgar E. Iglesias     name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
4986f16da53SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
4996f16da53SEdgar E. Iglesias         uint64_t mapsize;
5006f16da53SEdgar E. Iglesias 
5016f16da53SEdgar E. Iglesias         mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
5026f16da53SEdgar E. Iglesias 
5036f16da53SEdgar E. Iglesias         mem_reg_prop[i * 2] = addr_ranges[i].base;
5046f16da53SEdgar E. Iglesias         mem_reg_prop[i * 2 + 1] = mapsize;
5056f16da53SEdgar E. Iglesias         size -= mapsize;
5066f16da53SEdgar E. Iglesias     }
5076f16da53SEdgar E. Iglesias     qemu_fdt_add_subnode(fdt, name);
5086f16da53SEdgar E. Iglesias     qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
5096f16da53SEdgar E. Iglesias 
5106f16da53SEdgar E. Iglesias     switch (i) {
5116f16da53SEdgar E. Iglesias     case 1:
5126f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(fdt, name, "reg",
5136f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[0],
5146f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[1]);
5156f16da53SEdgar E. Iglesias         break;
5166f16da53SEdgar E. Iglesias     case 2:
5176f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(fdt, name, "reg",
5186f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[0],
5196f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[1],
5206f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[2],
5216f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[3]);
5226f16da53SEdgar E. Iglesias         break;
5236f16da53SEdgar E. Iglesias     case 3:
5246f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(fdt, name, "reg",
5256f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[0],
5266f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[1],
5276f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[2],
5286f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[3],
5296f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[4],
5306f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[5]);
5316f16da53SEdgar E. Iglesias         break;
5326f16da53SEdgar E. Iglesias     case 4:
5336f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(fdt, name, "reg",
5346f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[0],
5356f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[1],
5366f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[2],
5376f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[3],
5386f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[4],
5396f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[5],
5406f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[6],
5416f16da53SEdgar E. Iglesias                                      2, mem_reg_prop[7]);
5426f16da53SEdgar E. Iglesias         break;
5436f16da53SEdgar E. Iglesias     default:
5446f16da53SEdgar E. Iglesias         g_assert_not_reached();
5456f16da53SEdgar E. Iglesias     }
5466f16da53SEdgar E. Iglesias     g_free(name);
5476f16da53SEdgar E. Iglesias }
5486f16da53SEdgar E. Iglesias 
versal_virt_modify_dtb(const struct arm_boot_info * binfo,void * fdt)5496f16da53SEdgar E. Iglesias static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
5506f16da53SEdgar E. Iglesias                                     void *fdt)
5516f16da53SEdgar E. Iglesias {
5526f16da53SEdgar E. Iglesias     VersalVirt *s = container_of(binfo, VersalVirt, binfo);
5536f16da53SEdgar E. Iglesias 
5546f16da53SEdgar E. Iglesias     fdt_add_memory_nodes(s, fdt, binfo->ram_size);
5556f16da53SEdgar E. Iglesias }
5566f16da53SEdgar E. Iglesias 
versal_virt_get_dtb(const struct arm_boot_info * binfo,int * fdt_size)5576f16da53SEdgar E. Iglesias static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
5586f16da53SEdgar E. Iglesias                                   int *fdt_size)
5596f16da53SEdgar E. Iglesias {
5606f16da53SEdgar E. Iglesias     const VersalVirt *board = container_of(binfo, VersalVirt, binfo);
5616f16da53SEdgar E. Iglesias 
5626f16da53SEdgar E. Iglesias     *fdt_size = board->fdt_size;
5636f16da53SEdgar E. Iglesias     return board->fdt;
5646f16da53SEdgar E. Iglesias }
5656f16da53SEdgar E. Iglesias 
5667fd8115fSEdgar E. Iglesias #define NUM_VIRTIO_TRANSPORT 8
create_virtio_regions(VersalVirt * s)5676f16da53SEdgar E. Iglesias static void create_virtio_regions(VersalVirt *s)
5686f16da53SEdgar E. Iglesias {
5696f16da53SEdgar E. Iglesias     int virtio_mmio_size = 0x200;
5706f16da53SEdgar E. Iglesias     int i;
5716f16da53SEdgar E. Iglesias 
5726f16da53SEdgar E. Iglesias     for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
5736ab64e27SPhilippe Mathieu-Daudé         char *name = g_strdup_printf("virtio%d", i);
5746f16da53SEdgar E. Iglesias         hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
575fb179055SEdgar E. Iglesias         int irq = VERSAL_RSVD_IRQ_FIRST + i;
5766f16da53SEdgar E. Iglesias         MemoryRegion *mr;
5776f16da53SEdgar E. Iglesias         DeviceState *dev;
5786f16da53SEdgar E. Iglesias         qemu_irq pic_irq;
5796f16da53SEdgar E. Iglesias 
5806f16da53SEdgar E. Iglesias         pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
5813e80f690SMarkus Armbruster         dev = qdev_new("virtio-mmio");
582d2623129SMarkus Armbruster         object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev));
5833c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5846f16da53SEdgar E. Iglesias         sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
5856f16da53SEdgar E. Iglesias         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
5866f16da53SEdgar E. Iglesias         memory_region_add_subregion(&s->soc.mr_ps, base, mr);
587aee63b07SEdgar E. Iglesias         g_free(name);
5886f16da53SEdgar E. Iglesias     }
5896f16da53SEdgar E. Iglesias 
5906f16da53SEdgar E. Iglesias     for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
5916f16da53SEdgar E. Iglesias         hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
592fb179055SEdgar E. Iglesias         int irq = VERSAL_RSVD_IRQ_FIRST + i;
5936f16da53SEdgar E. Iglesias         char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
5946f16da53SEdgar E. Iglesias 
5956f16da53SEdgar E. Iglesias         qemu_fdt_add_subnode(s->fdt, name);
5966f16da53SEdgar E. Iglesias         qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
5976f16da53SEdgar E. Iglesias         qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
5986f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_TYPE_SPI, irq,
5996f16da53SEdgar E. Iglesias                                GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
6006f16da53SEdgar E. Iglesias         qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
6016f16da53SEdgar E. Iglesias                                      2, base, 2, virtio_mmio_size);
6026f16da53SEdgar E. Iglesias         qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
6036f16da53SEdgar E. Iglesias         g_free(name);
6046f16da53SEdgar E. Iglesias     }
6056f16da53SEdgar E. Iglesias }
6066f16da53SEdgar E. Iglesias 
bbram_attach_drive(XlnxBBRam * dev)607393185bcSTong Ho static void bbram_attach_drive(XlnxBBRam *dev)
608393185bcSTong Ho {
609393185bcSTong Ho     DriveInfo *dinfo;
610393185bcSTong Ho     BlockBackend *blk;
611393185bcSTong Ho 
612393185bcSTong Ho     dinfo = drive_get_by_index(IF_PFLASH, 0);
613393185bcSTong Ho     blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
614393185bcSTong Ho     if (blk) {
615393185bcSTong Ho         qdev_prop_set_drive(DEVICE(dev), "drive", blk);
616393185bcSTong Ho     }
617393185bcSTong Ho }
618393185bcSTong Ho 
efuse_attach_drive(XlnxEFuse * dev)6195f4910ffSTong Ho static void efuse_attach_drive(XlnxEFuse *dev)
6205f4910ffSTong Ho {
6215f4910ffSTong Ho     DriveInfo *dinfo;
6225f4910ffSTong Ho     BlockBackend *blk;
6235f4910ffSTong Ho 
6245f4910ffSTong Ho     dinfo = drive_get_by_index(IF_PFLASH, 1);
6255f4910ffSTong Ho     blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
6265f4910ffSTong Ho     if (blk) {
6275f4910ffSTong Ho         qdev_prop_set_drive(DEVICE(dev), "drive", blk);
6285f4910ffSTong Ho     }
6295f4910ffSTong Ho }
6305f4910ffSTong Ho 
sd_plugin_card(SDHCIState * sd,DriveInfo * di)6313afec85cSEdgar E. Iglesias static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
6323afec85cSEdgar E. Iglesias {
6333afec85cSEdgar E. Iglesias     BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
6343afec85cSEdgar E. Iglesias     DeviceState *card;
6353afec85cSEdgar E. Iglesias 
6363e80f690SMarkus Armbruster     card = qdev_new(TYPE_SD_CARD);
637d2623129SMarkus Armbruster     object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card));
638934df912SMarkus Armbruster     qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
639*cc17f3b2SCédric Le Goater     qdev_realize_and_unref(card, BUS(&sd->sdbus),
6403e80f690SMarkus Armbruster                            &error_fatal);
6413afec85cSEdgar E. Iglesias }
6423afec85cSEdgar E. Iglesias 
versal_get_ospi_model(Object * obj,Error ** errp)64306005459SSai Pavan Boddu static char *versal_get_ospi_model(Object *obj, Error **errp)
64406005459SSai Pavan Boddu {
64506005459SSai Pavan Boddu     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
64606005459SSai Pavan Boddu 
64706005459SSai Pavan Boddu     return g_strdup(s->ospi_model);
64806005459SSai Pavan Boddu }
64906005459SSai Pavan Boddu 
versal_set_ospi_model(Object * obj,const char * value,Error ** errp)65006005459SSai Pavan Boddu static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
65106005459SSai Pavan Boddu {
65206005459SSai Pavan Boddu     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
65306005459SSai Pavan Boddu 
65406005459SSai Pavan Boddu     g_free(s->ospi_model);
65506005459SSai Pavan Boddu     s->ospi_model = g_strdup(value);
65606005459SSai Pavan Boddu }
65706005459SSai Pavan Boddu 
65806005459SSai Pavan Boddu 
versal_virt_init(MachineState * machine)6596f16da53SEdgar E. Iglesias static void versal_virt_init(MachineState *machine)
6606f16da53SEdgar E. Iglesias {
6616f16da53SEdgar E. Iglesias     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
6626f16da53SEdgar E. Iglesias     int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
6633afec85cSEdgar E. Iglesias     int i;
6646f16da53SEdgar E. Iglesias 
6656f16da53SEdgar E. Iglesias     /*
6666f16da53SEdgar E. Iglesias      * If the user provides an Operating System to be loaded, we expect them
6676f16da53SEdgar E. Iglesias      * to use the -kernel command line option.
6686f16da53SEdgar E. Iglesias      *
6696f16da53SEdgar E. Iglesias      * Users can load firmware or boot-loaders with the -device loader options.
6706f16da53SEdgar E. Iglesias      *
6716f16da53SEdgar E. Iglesias      * When loading an OS, we generate a dtb and let arm_load_kernel() select
6726f16da53SEdgar E. Iglesias      * where it gets loaded. This dtb will be passed to the kernel in x0.
6736f16da53SEdgar E. Iglesias      *
6746f16da53SEdgar E. Iglesias      * If there's no -kernel option, we generate a DTB and place it at 0x1000
6756f16da53SEdgar E. Iglesias      * for the bootloaders or firmware to pick up.
6766f16da53SEdgar E. Iglesias      *
6776f16da53SEdgar E. Iglesias      * If users want to provide their own DTB, they can use the -dtb option.
6786f16da53SEdgar E. Iglesias      * These dtb's will have their memory nodes modified to match QEMU's
6796f16da53SEdgar E. Iglesias      * selected ram_size option before they get passed to the kernel or fw.
6806f16da53SEdgar E. Iglesias      *
6816f16da53SEdgar E. Iglesias      * When loading an OS, we turn on QEMU's PSCI implementation with SMC
6826f16da53SEdgar E. Iglesias      * as the PSCI conduit. When there's no -kernel, we assume the user
6836f16da53SEdgar E. Iglesias      * provides EL3 firmware to handle PSCI.
6849437a76eSPeter Maydell      *
6859437a76eSPeter Maydell      * Even if the user provides a kernel filename, arm_load_kernel()
6869437a76eSPeter Maydell      * may suppress PSCI if it's going to boot that guest code at EL3.
6876f16da53SEdgar E. Iglesias      */
6886f16da53SEdgar E. Iglesias     if (machine->kernel_filename) {
6896f16da53SEdgar E. Iglesias         psci_conduit = QEMU_PSCI_CONDUIT_SMC;
6906f16da53SEdgar E. Iglesias     }
6916f16da53SEdgar E. Iglesias 
6920074fce6SMarkus Armbruster     object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,
6930074fce6SMarkus Armbruster                             TYPE_XLNX_VERSAL);
6945325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
6955325cc34SMarkus Armbruster                              &error_abort);
696042d6b02SVikram Garhwal     object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
697042d6b02SVikram Garhwal                              &error_abort);
698042d6b02SVikram Garhwal     object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
699042d6b02SVikram Garhwal                              &error_abort);
7000074fce6SMarkus Armbruster     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
7016f16da53SEdgar E. Iglesias 
7026f16da53SEdgar E. Iglesias     fdt_create(s);
7036f16da53SEdgar E. Iglesias     create_virtio_regions(s);
7046f16da53SEdgar E. Iglesias     fdt_add_gem_nodes(s);
7056f16da53SEdgar E. Iglesias     fdt_add_uart_nodes(s);
706042d6b02SVikram Garhwal     fdt_add_canfd_nodes(s);
7076f16da53SEdgar E. Iglesias     fdt_add_gic_nodes(s);
7086f16da53SEdgar E. Iglesias     fdt_add_timer_nodes(s);
709ce5f4f01SEdgar E. Iglesias     fdt_add_zdma_nodes(s);
710144677d4SVikram Garhwal     fdt_add_usb_xhci_nodes(s);
7113afec85cSEdgar E. Iglesias     fdt_add_sd_nodes(s);
7122aca5284SEdgar E. Iglesias     fdt_add_rtc_node(s);
713393185bcSTong Ho     fdt_add_bbram_node(s);
7145f4910ffSTong Ho     fdt_add_efuse_ctrl_node(s);
7155f4910ffSTong Ho     fdt_add_efuse_cache_node(s);
7166f16da53SEdgar E. Iglesias     fdt_add_cpu_nodes(s, psci_conduit);
7176f16da53SEdgar E. Iglesias     fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
7186f16da53SEdgar E. Iglesias     fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
7196f16da53SEdgar E. Iglesias 
7206f16da53SEdgar E. Iglesias     /* Make the APU cpu address space visible to virtio and other
721b3db996fSStefan Weil      * modules unaware of multiple address-spaces.  */
7226f16da53SEdgar E. Iglesias     memory_region_add_subregion_overlap(get_system_memory(),
7236f16da53SEdgar E. Iglesias                                         0, &s->soc.fpd.apu.mr, 0);
7246f16da53SEdgar E. Iglesias 
725393185bcSTong Ho     /* Attach bbram backend, if given */
726393185bcSTong Ho     bbram_attach_drive(&s->soc.pmc.bbram);
727393185bcSTong Ho 
7285f4910ffSTong Ho     /* Attach efuse backend, if given */
7295f4910ffSTong Ho     efuse_attach_drive(&s->soc.pmc.efuse);
7305f4910ffSTong Ho 
7313afec85cSEdgar E. Iglesias     /* Plugin SD cards.  */
7323afec85cSEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
733c29faedaSMarkus Armbruster         sd_plugin_card(&s->soc.pmc.iou.sd[i],
734c29faedaSMarkus Armbruster                        drive_get(IF_SD, 0, i));
7353afec85cSEdgar E. Iglesias     }
7363afec85cSEdgar E. Iglesias 
7376f16da53SEdgar E. Iglesias     s->binfo.ram_size = machine->ram_size;
7386f16da53SEdgar E. Iglesias     s->binfo.loader_start = 0x0;
7396f16da53SEdgar E. Iglesias     s->binfo.get_dtb = versal_virt_get_dtb;
7406f16da53SEdgar E. Iglesias     s->binfo.modify_dtb = versal_virt_modify_dtb;
7419437a76eSPeter Maydell     s->binfo.psci_conduit = psci_conduit;
74240874a38SEdgar E. Iglesias     if (!machine->kernel_filename) {
7436f16da53SEdgar E. Iglesias         /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
7446f16da53SEdgar E. Iglesias          * Offset things by 4K.  */
7456f16da53SEdgar E. Iglesias         s->binfo.loader_start = 0x1000;
7466f16da53SEdgar E. Iglesias         s->binfo.dtb_limit = 0x1000000;
7476f16da53SEdgar E. Iglesias     }
74840874a38SEdgar E. Iglesias     arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
7494461f0fbSFrancisco Iglesias 
7504461f0fbSFrancisco Iglesias     for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
7514461f0fbSFrancisco Iglesias         BusState *spi_bus;
7524461f0fbSFrancisco Iglesias         DeviceState *flash_dev;
75306005459SSai Pavan Boddu         ObjectClass *flash_klass;
7544461f0fbSFrancisco Iglesias         qemu_irq cs_line;
7554461f0fbSFrancisco Iglesias         DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
7564461f0fbSFrancisco Iglesias 
7574461f0fbSFrancisco Iglesias         spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0");
7584461f0fbSFrancisco Iglesias 
75906005459SSai Pavan Boddu         if (s->ospi_model) {
76006005459SSai Pavan Boddu             flash_klass = object_class_by_name(s->ospi_model);
76106005459SSai Pavan Boddu             if (!flash_klass ||
76206005459SSai Pavan Boddu                 object_class_is_abstract(flash_klass) ||
763a7538ca0SCédric Le Goater                 !object_class_dynamic_cast(flash_klass, TYPE_M25P80)) {
7645ae3ec63STudor Gheorghiu                 error_report("'%s' is either abstract or"
76506005459SSai Pavan Boddu                        " not a subtype of m25p80", s->ospi_model);
7665ae3ec63STudor Gheorghiu                 exit(1);
76706005459SSai Pavan Boddu             }
76806005459SSai Pavan Boddu         }
76906005459SSai Pavan Boddu 
77006005459SSai Pavan Boddu         flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
77106005459SSai Pavan Boddu 
7724461f0fbSFrancisco Iglesias         if (dinfo) {
7734461f0fbSFrancisco Iglesias             qdev_prop_set_drive_err(flash_dev, "drive",
7744461f0fbSFrancisco Iglesias                                     blk_by_legacy_dinfo(dinfo), &error_fatal);
7754461f0fbSFrancisco Iglesias         }
776a617e65fSCédric Le Goater         qdev_prop_set_uint8(flash_dev, "cs", i);
7774461f0fbSFrancisco Iglesias         qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
7784461f0fbSFrancisco Iglesias 
7794461f0fbSFrancisco Iglesias         cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
7804461f0fbSFrancisco Iglesias 
7814461f0fbSFrancisco Iglesias         sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi),
7824461f0fbSFrancisco Iglesias                            i + 1, cs_line);
7834461f0fbSFrancisco Iglesias     }
7846f16da53SEdgar E. Iglesias }
7856f16da53SEdgar E. Iglesias 
versal_virt_machine_instance_init(Object * obj)7866f16da53SEdgar E. Iglesias static void versal_virt_machine_instance_init(Object *obj)
7876f16da53SEdgar E. Iglesias {
788042d6b02SVikram Garhwal     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
789042d6b02SVikram Garhwal 
790042d6b02SVikram Garhwal     /*
791042d6b02SVikram Garhwal      * User can set canbus0 and canbus1 properties to can-bus object and connect
792042d6b02SVikram Garhwal      * to socketcan(optional) interface via command line.
793042d6b02SVikram Garhwal      */
794042d6b02SVikram Garhwal     object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
795042d6b02SVikram Garhwal                              (Object **)&s->canbus[0],
796042d6b02SVikram Garhwal                              object_property_allow_set_link,
797042d6b02SVikram Garhwal                              0);
798042d6b02SVikram Garhwal     object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
799042d6b02SVikram Garhwal                              (Object **)&s->canbus[1],
800042d6b02SVikram Garhwal                              object_property_allow_set_link,
801042d6b02SVikram Garhwal                              0);
8026f16da53SEdgar E. Iglesias }
8036f16da53SEdgar E. Iglesias 
versal_virt_machine_finalize(Object * obj)80406005459SSai Pavan Boddu static void versal_virt_machine_finalize(Object *obj)
80506005459SSai Pavan Boddu {
80606005459SSai Pavan Boddu     VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
80706005459SSai Pavan Boddu 
80806005459SSai Pavan Boddu     g_free(s->ospi_model);
80906005459SSai Pavan Boddu }
81006005459SSai Pavan Boddu 
versal_virt_machine_class_init(ObjectClass * oc,void * data)8116f16da53SEdgar E. Iglesias static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
8126f16da53SEdgar E. Iglesias {
8136f16da53SEdgar E. Iglesias     MachineClass *mc = MACHINE_CLASS(oc);
8146f16da53SEdgar E. Iglesias 
8156f16da53SEdgar E. Iglesias     mc->desc = "Xilinx Versal Virtual development board";
8166f16da53SEdgar E. Iglesias     mc->init = versal_virt_init;
81767a645a3SEdgar E. Iglesias     mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
81867a645a3SEdgar E. Iglesias     mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
81967a645a3SEdgar E. Iglesias     mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
8206f16da53SEdgar E. Iglesias     mc->no_cdrom = true;
821e9201598SIgor Mammedov     mc->default_ram_id = "ddr";
82206005459SSai Pavan Boddu     object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
82306005459SSai Pavan Boddu                                    versal_set_ospi_model);
82406005459SSai Pavan Boddu     object_class_property_set_description(oc, "ospi-flash",
82506005459SSai Pavan Boddu                                           "Change the OSPI Flash model");
8266f16da53SEdgar E. Iglesias }
8276f16da53SEdgar E. Iglesias 
8286f16da53SEdgar E. Iglesias static const TypeInfo versal_virt_machine_init_typeinfo = {
8296f16da53SEdgar E. Iglesias     .name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,
8306f16da53SEdgar E. Iglesias     .parent     = TYPE_MACHINE,
8316f16da53SEdgar E. Iglesias     .class_init = versal_virt_machine_class_init,
8326f16da53SEdgar E. Iglesias     .instance_init = versal_virt_machine_instance_init,
8336f16da53SEdgar E. Iglesias     .instance_size = sizeof(VersalVirt),
83406005459SSai Pavan Boddu     .instance_finalize = versal_virt_machine_finalize,
8356f16da53SEdgar E. Iglesias };
8366f16da53SEdgar E. Iglesias 
versal_virt_machine_init_register_types(void)8376f16da53SEdgar E. Iglesias static void versal_virt_machine_init_register_types(void)
8386f16da53SEdgar E. Iglesias {
8396f16da53SEdgar E. Iglesias     type_register_static(&versal_virt_machine_init_typeinfo);
8406f16da53SEdgar E. Iglesias }
8416f16da53SEdgar E. Iglesias 
8426f16da53SEdgar E. Iglesias type_init(versal_virt_machine_init_register_types)
8436f16da53SEdgar E. Iglesias 
844