2
0

xlnx-versal.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * Xilinx Versal SoC model.
  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 "qapi/error.h"
  13. #include "qemu/log.h"
  14. #include "qemu/module.h"
  15. #include "hw/sysbus.h"
  16. #include "net/net.h"
  17. #include "sysemu/sysemu.h"
  18. #include "sysemu/kvm.h"
  19. #include "hw/arm/boot.h"
  20. #include "kvm_arm.h"
  21. #include "hw/misc/unimp.h"
  22. #include "hw/arm/xlnx-versal.h"
  23. #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
  24. #define GEM_REVISION 0x40070106
  25. static void versal_create_apu_cpus(Versal *s)
  26. {
  27. int i;
  28. for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
  29. Object *obj;
  30. object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
  31. XLNX_VERSAL_ACPU_TYPE);
  32. obj = OBJECT(&s->fpd.apu.cpu[i]);
  33. object_property_set_int(obj, "psci-conduit", s->cfg.psci_conduit,
  34. &error_abort);
  35. if (i) {
  36. /* Secondary CPUs start in PSCI powered-down state */
  37. object_property_set_bool(obj, "start-powered-off", true,
  38. &error_abort);
  39. }
  40. object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu),
  41. &error_abort);
  42. object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr),
  43. &error_abort);
  44. qdev_realize(DEVICE(obj), NULL, &error_fatal);
  45. }
  46. }
  47. static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
  48. {
  49. static const uint64_t addrs[] = {
  50. MM_GIC_APU_DIST_MAIN,
  51. MM_GIC_APU_REDIST_0
  52. };
  53. SysBusDevice *gicbusdev;
  54. DeviceState *gicdev;
  55. int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
  56. int i;
  57. object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic,
  58. gicv3_class_name());
  59. gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
  60. gicdev = DEVICE(&s->fpd.apu.gic);
  61. qdev_prop_set_uint32(gicdev, "revision", 3);
  62. qdev_prop_set_uint32(gicdev, "num-cpu", 2);
  63. qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
  64. qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
  65. qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2);
  66. qdev_prop_set_bit(gicdev, "has-security-extensions", true);
  67. sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal);
  68. for (i = 0; i < ARRAY_SIZE(addrs); i++) {
  69. MemoryRegion *mr;
  70. mr = sysbus_mmio_get_region(gicbusdev, i);
  71. memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
  72. }
  73. for (i = 0; i < nr_apu_cpus; i++) {
  74. DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]);
  75. int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
  76. qemu_irq maint_irq;
  77. int ti;
  78. /* Mapping from the output timer irq lines from the CPU to the
  79. * GIC PPI inputs.
  80. */
  81. const int timer_irq[] = {
  82. [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
  83. [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
  84. [GTIMER_HYP] = VERSAL_TIMER_NS_EL2_IRQ,
  85. [GTIMER_SEC] = VERSAL_TIMER_S_EL1_IRQ,
  86. };
  87. for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
  88. qdev_connect_gpio_out(cpudev, ti,
  89. qdev_get_gpio_in(gicdev,
  90. ppibase + timer_irq[ti]));
  91. }
  92. maint_irq = qdev_get_gpio_in(gicdev,
  93. ppibase + VERSAL_GIC_MAINT_IRQ);
  94. qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
  95. 0, maint_irq);
  96. sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
  97. sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
  98. qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
  99. sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
  100. qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
  101. sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
  102. qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
  103. }
  104. for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
  105. pic[i] = qdev_get_gpio_in(gicdev, i);
  106. }
  107. }
  108. static void versal_create_uarts(Versal *s, qemu_irq *pic)
  109. {
  110. int i;
  111. for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
  112. static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
  113. static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
  114. char *name = g_strdup_printf("uart%d", i);
  115. DeviceState *dev;
  116. MemoryRegion *mr;
  117. object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i],
  118. TYPE_PL011);
  119. dev = DEVICE(&s->lpd.iou.uart[i]);
  120. qdev_prop_set_chr(dev, "chardev", serial_hd(i));
  121. sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
  122. mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
  123. memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
  124. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
  125. g_free(name);
  126. }
  127. }
  128. static void versal_create_gems(Versal *s, qemu_irq *pic)
  129. {
  130. int i;
  131. for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
  132. static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
  133. static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
  134. char *name = g_strdup_printf("gem%d", i);
  135. NICInfo *nd = &nd_table[i];
  136. DeviceState *dev;
  137. MemoryRegion *mr;
  138. object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i],
  139. TYPE_CADENCE_GEM);
  140. dev = DEVICE(&s->lpd.iou.gem[i]);
  141. /* FIXME use qdev NIC properties instead of nd_table[] */
  142. if (nd->used) {
  143. qemu_check_nic_model(nd, "cadence_gem");
  144. qdev_set_nic_properties(dev, nd);
  145. }
  146. object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
  147. &error_abort);
  148. object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
  149. &error_abort);
  150. sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
  151. mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
  152. memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
  153. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
  154. g_free(name);
  155. }
  156. }
  157. static void versal_create_admas(Versal *s, qemu_irq *pic)
  158. {
  159. int i;
  160. for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
  161. char *name = g_strdup_printf("adma%d", i);
  162. DeviceState *dev;
  163. MemoryRegion *mr;
  164. object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i],
  165. TYPE_XLNX_ZDMA);
  166. dev = DEVICE(&s->lpd.iou.adma[i]);
  167. object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort);
  168. sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
  169. mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
  170. memory_region_add_subregion(&s->mr_ps,
  171. MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
  172. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]);
  173. g_free(name);
  174. }
  175. }
  176. #define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */
  177. static void versal_create_sds(Versal *s, qemu_irq *pic)
  178. {
  179. int i;
  180. for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) {
  181. DeviceState *dev;
  182. MemoryRegion *mr;
  183. object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i],
  184. TYPE_SYSBUS_SDHCI);
  185. dev = DEVICE(&s->pmc.iou.sd[i]);
  186. object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
  187. &error_fatal);
  188. object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
  189. &error_fatal);
  190. object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
  191. sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
  192. mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
  193. memory_region_add_subregion(&s->mr_ps,
  194. MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr);
  195. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
  196. pic[VERSAL_SD0_IRQ_0 + i * 2]);
  197. }
  198. }
  199. static void versal_create_rtc(Versal *s, qemu_irq *pic)
  200. {
  201. SysBusDevice *sbd;
  202. MemoryRegion *mr;
  203. object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
  204. TYPE_XLNX_ZYNQMP_RTC);
  205. sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
  206. sysbus_realize(SYS_BUS_DEVICE(sbd), &error_fatal);
  207. mr = sysbus_mmio_get_region(sbd, 0);
  208. memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
  209. /*
  210. * TODO: Connect the ALARM and SECONDS interrupts once our RTC model
  211. * supports them.
  212. */
  213. sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]);
  214. }
  215. /* This takes the board allocated linear DDR memory and creates aliases
  216. * for each split DDR range/aperture on the Versal address map.
  217. */
  218. static void versal_map_ddr(Versal *s)
  219. {
  220. uint64_t size = memory_region_size(s->cfg.mr_ddr);
  221. /* Describes the various split DDR access regions. */
  222. static const struct {
  223. uint64_t base;
  224. uint64_t size;
  225. } addr_ranges[] = {
  226. { MM_TOP_DDR, MM_TOP_DDR_SIZE },
  227. { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
  228. { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
  229. { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
  230. };
  231. uint64_t offset = 0;
  232. int i;
  233. assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
  234. for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
  235. char *name;
  236. uint64_t mapsize;
  237. mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
  238. name = g_strdup_printf("noc-ddr-range%d", i);
  239. /* Create the MR alias. */
  240. memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
  241. name, s->cfg.mr_ddr,
  242. offset, mapsize);
  243. /* Map it onto the NoC MR. */
  244. memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
  245. &s->noc.mr_ddr_ranges[i]);
  246. offset += mapsize;
  247. size -= mapsize;
  248. g_free(name);
  249. }
  250. }
  251. static void versal_unimp_area(Versal *s, const char *name,
  252. MemoryRegion *mr,
  253. hwaddr base, hwaddr size)
  254. {
  255. DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
  256. MemoryRegion *mr_dev;
  257. qdev_prop_set_string(dev, "name", name);
  258. qdev_prop_set_uint64(dev, "size", size);
  259. object_property_add_child(OBJECT(s), name, OBJECT(dev));
  260. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  261. mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
  262. memory_region_add_subregion(mr, base, mr_dev);
  263. }
  264. static void versal_unimp(Versal *s)
  265. {
  266. versal_unimp_area(s, "psm", &s->mr_ps,
  267. MM_PSM_START, MM_PSM_END - MM_PSM_START);
  268. versal_unimp_area(s, "crl", &s->mr_ps,
  269. MM_CRL, MM_CRL_SIZE);
  270. versal_unimp_area(s, "crf", &s->mr_ps,
  271. MM_FPD_CRF, MM_FPD_CRF_SIZE);
  272. versal_unimp_area(s, "crp", &s->mr_ps,
  273. MM_PMC_CRP, MM_PMC_CRP_SIZE);
  274. versal_unimp_area(s, "iou-scntr", &s->mr_ps,
  275. MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
  276. versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
  277. MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
  278. }
  279. static void versal_realize(DeviceState *dev, Error **errp)
  280. {
  281. Versal *s = XLNX_VERSAL(dev);
  282. qemu_irq pic[XLNX_VERSAL_NR_IRQS];
  283. versal_create_apu_cpus(s);
  284. versal_create_apu_gic(s, pic);
  285. versal_create_uarts(s, pic);
  286. versal_create_gems(s, pic);
  287. versal_create_admas(s, pic);
  288. versal_create_sds(s, pic);
  289. versal_create_rtc(s, pic);
  290. versal_map_ddr(s);
  291. versal_unimp(s);
  292. /* Create the On Chip Memory (OCM). */
  293. memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
  294. MM_OCM_SIZE, &error_fatal);
  295. memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
  296. memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
  297. }
  298. static void versal_init(Object *obj)
  299. {
  300. Versal *s = XLNX_VERSAL(obj);
  301. memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
  302. memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
  303. }
  304. static Property versal_properties[] = {
  305. DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
  306. MemoryRegion *),
  307. DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
  308. DEFINE_PROP_END_OF_LIST()
  309. };
  310. static void versal_class_init(ObjectClass *klass, void *data)
  311. {
  312. DeviceClass *dc = DEVICE_CLASS(klass);
  313. dc->realize = versal_realize;
  314. device_class_set_props(dc, versal_properties);
  315. /* No VMSD since we haven't got any top-level SoC state to save. */
  316. }
  317. static const TypeInfo versal_info = {
  318. .name = TYPE_XLNX_VERSAL,
  319. .parent = TYPE_SYS_BUS_DEVICE,
  320. .instance_size = sizeof(Versal),
  321. .instance_init = versal_init,
  322. .class_init = versal_class_init,
  323. };
  324. static void versal_register_types(void)
  325. {
  326. type_register_static(&versal_info);
  327. }
  328. type_init(versal_register_types);