xlnx-versal-virt.c 31 KB

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