xref: /qemu/hw/arm/xlnx-versal.c (revision 2c4815590f9ea399bc87f727dd1c883b0d701bb8)
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  
12  #include "qemu/osdep.h"
13  #include "qemu/units.h"
14  #include "qapi/error.h"
15  #include "qapi/qmp/qlist.h"
16  #include "qemu/module.h"
17  #include "hw/sysbus.h"
18  #include "net/net.h"
19  #include "system/system.h"
20  #include "system/kvm.h"
21  #include "hw/arm/boot.h"
22  #include "kvm_arm.h"
23  #include "hw/misc/unimp.h"
24  #include "hw/arm/xlnx-versal.h"
25  #include "qemu/log.h"
26  #include "target/arm/cpu-qom.h"
27  #include "target/arm/gtimer.h"
28  
29  #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
30  #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
31  #define GEM_REVISION        0x40070106
32  
33  #define VERSAL_NUM_PMC_APB_IRQS 18
34  #define NUM_OSPI_IRQ_LINES 3
35  
36  static void versal_create_apu_cpus(Versal *s)
37  {
38      int i;
39  
40      object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
41                              TYPE_CPU_CLUSTER);
42      qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
43  
44      for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
45          Object *obj;
46  
47          object_initialize_child(OBJECT(&s->fpd.apu.cluster),
48                                  "apu-cpu[*]", &s->fpd.apu.cpu[i],
49                                  XLNX_VERSAL_ACPU_TYPE);
50          obj = OBJECT(&s->fpd.apu.cpu[i]);
51          if (i) {
52              /* Secondary CPUs start in powered-down state */
53              object_property_set_bool(obj, "start-powered-off", true,
54                                       &error_abort);
55          }
56  
57          object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu),
58                                  &error_abort);
59          object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr),
60                                   &error_abort);
61          qdev_realize(DEVICE(obj), NULL, &error_fatal);
62      }
63  
64      qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
65  }
66  
67  static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
68  {
69      static const uint64_t addrs[] = {
70          MM_GIC_APU_DIST_MAIN,
71          MM_GIC_APU_REDIST_0
72      };
73      SysBusDevice *gicbusdev;
74      DeviceState *gicdev;
75      QList *redist_region_count;
76      int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
77      int i;
78  
79      object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic,
80                              gicv3_class_name());
81      gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
82      gicdev = DEVICE(&s->fpd.apu.gic);
83      qdev_prop_set_uint32(gicdev, "revision", 3);
84      qdev_prop_set_uint32(gicdev, "num-cpu", nr_apu_cpus);
85      qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
86  
87      redist_region_count = qlist_new();
88      qlist_append_int(redist_region_count, nr_apu_cpus);
89      qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
90  
91      qdev_prop_set_bit(gicdev, "has-security-extensions", true);
92  
93      sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal);
94  
95      for (i = 0; i < ARRAY_SIZE(addrs); i++) {
96          MemoryRegion *mr;
97  
98          mr = sysbus_mmio_get_region(gicbusdev, i);
99          memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
100      }
101  
102      for (i = 0; i < nr_apu_cpus; i++) {
103          DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]);
104          int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
105          qemu_irq maint_irq;
106          int ti;
107          /* Mapping from the output timer irq lines from the CPU to the
108           * GIC PPI inputs.
109           */
110          const int timer_irq[] = {
111              [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
112              [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
113              [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
114              [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
115          };
116  
117          for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
118              qdev_connect_gpio_out(cpudev, ti,
119                                    qdev_get_gpio_in(gicdev,
120                                                     ppibase + timer_irq[ti]));
121          }
122          maint_irq = qdev_get_gpio_in(gicdev,
123                                          ppibase + VERSAL_GIC_MAINT_IRQ);
124          qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
125                                      0, maint_irq);
126          sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
127          sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
128                             qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
129          sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
130                             qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
131          sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
132                             qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
133      }
134  
135      for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
136          pic[i] = qdev_get_gpio_in(gicdev, i);
137      }
138  }
139  
140  static void versal_create_rpu_cpus(Versal *s)
141  {
142      int i;
143  
144      object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
145                              TYPE_CPU_CLUSTER);
146      qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
147  
148      for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
149          Object *obj;
150  
151          object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
152                                  "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
153                                  XLNX_VERSAL_RCPU_TYPE);
154          obj = OBJECT(&s->lpd.rpu.cpu[i]);
155          object_property_set_bool(obj, "start-powered-off", true,
156                                   &error_abort);
157  
158          object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
159          object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
160                                  &error_abort);
161          object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
162                                   &error_abort);
163          qdev_realize(DEVICE(obj), NULL, &error_fatal);
164      }
165  
166      qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
167  }
168  
169  static void versal_create_uarts(Versal *s, qemu_irq *pic)
170  {
171      int i;
172  
173      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
174          static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
175          static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
176          char *name = g_strdup_printf("uart%d", i);
177          DeviceState *dev;
178          MemoryRegion *mr;
179  
180          object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i],
181                                  TYPE_PL011);
182          dev = DEVICE(&s->lpd.iou.uart[i]);
183          qdev_prop_set_chr(dev, "chardev", serial_hd(i));
184          sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
185  
186          mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
187          memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
188  
189          sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
190          g_free(name);
191      }
192  }
193  
194  static void versal_create_canfds(Versal *s, qemu_irq *pic)
195  {
196      int i;
197      uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
198      uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
199  
200      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
201          char *name = g_strdup_printf("canfd%d", i);
202          SysBusDevice *sbd;
203          MemoryRegion *mr;
204  
205          object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i],
206                                  TYPE_XILINX_CANFD);
207          sbd = SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]);
208  
209          object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_freq",
210                                  XLNX_VERSAL_CANFD_REF_CLK , &error_abort);
211  
212          object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus",
213                                   OBJECT(s->lpd.iou.canbus[i]),
214                                   &error_abort);
215  
216          sysbus_realize(sbd, &error_fatal);
217  
218          mr = sysbus_mmio_get_region(sbd, 0);
219          memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
220  
221          sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
222          g_free(name);
223      }
224  }
225  
226  static void versal_create_usbs(Versal *s, qemu_irq *pic)
227  {
228      DeviceState *dev;
229      MemoryRegion *mr;
230  
231      object_initialize_child(OBJECT(s), "usb2", &s->lpd.iou.usb,
232                              TYPE_XILINX_VERSAL_USB2);
233      dev = DEVICE(&s->lpd.iou.usb);
234  
235      object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
236                               &error_abort);
237      qdev_prop_set_uint32(dev, "intrs", 1);
238      qdev_prop_set_uint32(dev, "slots", 2);
239  
240      sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
241  
242      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
243      memory_region_add_subregion(&s->mr_ps, MM_USB_0, mr);
244  
245      sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_USB0_IRQ_0]);
246  
247      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
248      memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
249  }
250  
251  static void versal_create_gems(Versal *s, qemu_irq *pic)
252  {
253      int i;
254  
255      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
256          static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
257          static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
258          char *name = g_strdup_printf("gem%d", i);
259          DeviceState *dev;
260          MemoryRegion *mr;
261          OrIRQState *or_irq;
262  
263          object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i],
264                                  TYPE_CADENCE_GEM);
265          or_irq = &s->lpd.iou.gem_irq_orgate[i];
266          object_initialize_child(OBJECT(s), "gem-irq-orgate[*]",
267                                  or_irq, TYPE_OR_IRQ);
268          dev = DEVICE(&s->lpd.iou.gem[i]);
269          qemu_configure_nic_device(dev, true, NULL);
270          object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
271          object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
272                                  &error_abort);
273          object_property_set_int(OBJECT(or_irq),
274                                  "num-lines", 2, &error_fatal);
275          qdev_realize(DEVICE(or_irq), NULL, &error_fatal);
276          qdev_connect_gpio_out(DEVICE(or_irq), 0, pic[irqs[i]]);
277  
278          object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
279                                   &error_abort);
280          sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
281  
282          mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
283          memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
284  
285          sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(or_irq), 0));
286          sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(or_irq), 1));
287          g_free(name);
288      }
289  }
290  
291  static void versal_create_admas(Versal *s, qemu_irq *pic)
292  {
293      int i;
294  
295      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
296          char *name = g_strdup_printf("adma%d", i);
297          DeviceState *dev;
298          MemoryRegion *mr;
299  
300          object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i],
301                                  TYPE_XLNX_ZDMA);
302          dev = DEVICE(&s->lpd.iou.adma[i]);
303          object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort);
304          object_property_set_link(OBJECT(dev), "dma",
305                                   OBJECT(get_system_memory()), &error_fatal);
306          sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
307  
308          mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
309          memory_region_add_subregion(&s->mr_ps,
310                                      MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
311  
312          sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]);
313          g_free(name);
314      }
315  }
316  
317  #define SDHCI_CAPABILITIES  0x280737ec6481 /* Same as on ZynqMP.  */
318  static void versal_create_sds(Versal *s, qemu_irq *pic)
319  {
320      int i;
321  
322      for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) {
323          DeviceState *dev;
324          MemoryRegion *mr;
325  
326          object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i],
327                                  TYPE_SYSBUS_SDHCI);
328          dev = DEVICE(&s->pmc.iou.sd[i]);
329  
330          object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
331                                   &error_fatal);
332          object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
333                                   &error_fatal);
334          object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
335          sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
336  
337          mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
338          memory_region_add_subregion(&s->mr_ps,
339                                      MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr);
340  
341          sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
342                             pic[VERSAL_SD0_IRQ_0 + i * 2]);
343      }
344  }
345  
346  static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
347  {
348      DeviceState *orgate;
349  
350      /*
351       * The VERSAL_PMC_APB_IRQ is an 'or' of the interrupts from the following
352       * models:
353       *  - RTC
354       *  - BBRAM
355       *  - PMC SLCR
356       *  - CFRAME regs (input 3 - 17 to the orgate)
357       */
358      object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
359                              &s->pmc.apb_irq_orgate, TYPE_OR_IRQ);
360      orgate = DEVICE(&s->pmc.apb_irq_orgate);
361      object_property_set_int(OBJECT(orgate),
362                              "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal);
363      qdev_realize(orgate, NULL, &error_fatal);
364      qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]);
365  }
366  
367  static void versal_create_rtc(Versal *s, qemu_irq *pic)
368  {
369      SysBusDevice *sbd;
370      MemoryRegion *mr;
371  
372      object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
373                              TYPE_XLNX_ZYNQMP_RTC);
374      sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
375      sysbus_realize(sbd, &error_fatal);
376  
377      mr = sysbus_mmio_get_region(sbd, 0);
378      memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
379  
380      /*
381       * TODO: Connect the ALARM and SECONDS interrupts once our RTC model
382       * supports them.
383       */
384      sysbus_connect_irq(sbd, 1,
385                         qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0));
386  }
387  
388  static void versal_create_trng(Versal *s, qemu_irq *pic)
389  {
390      SysBusDevice *sbd;
391      MemoryRegion *mr;
392  
393      object_initialize_child(OBJECT(s), "trng", &s->pmc.trng,
394                              TYPE_XLNX_VERSAL_TRNG);
395      sbd = SYS_BUS_DEVICE(&s->pmc.trng);
396      sysbus_realize(sbd, &error_fatal);
397  
398      mr = sysbus_mmio_get_region(sbd, 0);
399      memory_region_add_subregion(&s->mr_ps, MM_PMC_TRNG, mr);
400      sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]);
401  }
402  
403  static void versal_create_xrams(Versal *s, qemu_irq *pic)
404  {
405      int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
406      DeviceState *orgate;
407      int i;
408  
409      /* XRAM IRQs get ORed into a single line.  */
410      object_initialize_child(OBJECT(s), "xram-irq-orgate",
411                              &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
412      orgate = DEVICE(&s->lpd.xram.irq_orgate);
413      object_property_set_int(OBJECT(orgate),
414                              "num-lines", nr_xrams, &error_fatal);
415      qdev_realize(orgate, NULL, &error_fatal);
416      qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
417  
418      for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
419          SysBusDevice *sbd;
420          MemoryRegion *mr;
421  
422          object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i],
423                                  TYPE_XLNX_XRAM_CTRL);
424          sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]);
425          sysbus_realize(sbd, &error_fatal);
426  
427          mr = sysbus_mmio_get_region(sbd, 0);
428          memory_region_add_subregion(&s->mr_ps,
429                                      MM_XRAMC + i * MM_XRAMC_SIZE, mr);
430          mr = sysbus_mmio_get_region(sbd, 1);
431          memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr);
432  
433          sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i));
434      }
435  }
436  
437  static void versal_create_bbram(Versal *s, qemu_irq *pic)
438  {
439      SysBusDevice *sbd;
440  
441      object_initialize_child_with_props(OBJECT(s), "bbram", &s->pmc.bbram,
442                                         sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM,
443                                         &error_fatal,
444                                         "crc-zpads", "0",
445                                         NULL);
446      sbd = SYS_BUS_DEVICE(&s->pmc.bbram);
447  
448      sysbus_realize(sbd, &error_fatal);
449      memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL,
450                                  sysbus_mmio_get_region(sbd, 0));
451      sysbus_connect_irq(sbd, 0,
452                         qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1));
453  }
454  
455  static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base)
456  {
457      SysBusDevice *part = SYS_BUS_DEVICE(dev);
458  
459      object_property_set_link(OBJECT(part), "efuse",
460                               OBJECT(&s->pmc.efuse), &error_abort);
461  
462      sysbus_realize(part, &error_abort);
463      memory_region_add_subregion(&s->mr_ps, base,
464                                  sysbus_mmio_get_region(part, 0));
465  }
466  
467  static void versal_create_efuse(Versal *s, qemu_irq *pic)
468  {
469      Object *bits = OBJECT(&s->pmc.efuse);
470      Object *ctrl = OBJECT(&s->pmc.efuse_ctrl);
471      Object *cache = OBJECT(&s->pmc.efuse_cache);
472  
473      object_initialize_child(OBJECT(s), "efuse-ctrl", &s->pmc.efuse_ctrl,
474                              TYPE_XLNX_VERSAL_EFUSE_CTRL);
475  
476      object_initialize_child(OBJECT(s), "efuse-cache", &s->pmc.efuse_cache,
477                              TYPE_XLNX_VERSAL_EFUSE_CACHE);
478  
479      object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits,
480                                         sizeof(s->pmc.efuse),
481                                         TYPE_XLNX_EFUSE, &error_abort,
482                                         "efuse-nr", "3",
483                                         "efuse-size", "8192",
484                                         NULL);
485  
486      qdev_realize(DEVICE(bits), NULL, &error_abort);
487      versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL);
488      versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE);
489  
490      sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]);
491  }
492  
493  static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
494  {
495      SysBusDevice *sbd;
496  
497      object_initialize_child(OBJECT(s), "versal-pmc-iou-slcr", &s->pmc.iou.slcr,
498                              TYPE_XILINX_VERSAL_PMC_IOU_SLCR);
499  
500      sbd = SYS_BUS_DEVICE(&s->pmc.iou.slcr);
501      sysbus_realize(sbd, &error_fatal);
502  
503      memory_region_add_subregion(&s->mr_ps, MM_PMC_PMC_IOU_SLCR,
504                                  sysbus_mmio_get_region(sbd, 0));
505  
506      sysbus_connect_irq(sbd, 0,
507                         qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
508  }
509  
510  static void versal_create_ospi(Versal *s, qemu_irq *pic)
511  {
512      SysBusDevice *sbd;
513      MemoryRegion *mr_dac;
514      qemu_irq ospi_mux_sel;
515      DeviceState *orgate;
516  
517      memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s),
518                         "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE);
519  
520      object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi,
521                              TYPE_XILINX_VERSAL_OSPI);
522  
523      mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1);
524      memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac);
525  
526      /* Create the OSPI destination DMA */
527      object_initialize_child(OBJECT(s), "versal-ospi-dma-dst",
528                              &s->pmc.iou.ospi.dma_dst,
529                              TYPE_XLNX_CSU_DMA);
530  
531      object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst),
532                              "dma", OBJECT(get_system_memory()),
533                               &error_abort);
534  
535      sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst);
536      sysbus_realize(sbd, &error_fatal);
537  
538      memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST,
539                                  sysbus_mmio_get_region(sbd, 0));
540  
541      /* Create the OSPI source DMA */
542      object_initialize_child(OBJECT(s), "versal-ospi-dma-src",
543                              &s->pmc.iou.ospi.dma_src,
544                              TYPE_XLNX_CSU_DMA);
545  
546      object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst",
547                               false, &error_abort);
548  
549      object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
550                              "dma", OBJECT(mr_dac), &error_abort);
551  
552      object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
553                              "stream-connected-dma",
554                               OBJECT(&s->pmc.iou.ospi.dma_dst),
555                               &error_abort);
556  
557      sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src);
558      sysbus_realize(sbd, &error_fatal);
559  
560      memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC,
561                                  sysbus_mmio_get_region(sbd, 0));
562  
563      /* Realize the OSPI */
564      object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src",
565                               OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort);
566  
567      sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi);
568      sysbus_realize(sbd, &error_fatal);
569  
570      memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI,
571                                  sysbus_mmio_get_region(sbd, 0));
572  
573      memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC,
574                                  &s->pmc.iou.ospi.linear_mr);
575  
576      /* ospi_mux_sel */
577      ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi),
578                                            "ospi-mux-sel", 0);
579      qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0,
580                                  ospi_mux_sel);
581  
582      /* OSPI irq */
583      object_initialize_child(OBJECT(s), "ospi-irq-orgate",
584                              &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ);
585      object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate),
586                              "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal);
587  
588      orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate);
589      qdev_realize(orgate, NULL, &error_fatal);
590  
591      sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0,
592                         qdev_get_gpio_in(orgate, 0));
593      sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0,
594                         qdev_get_gpio_in(orgate, 1));
595      sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0,
596                         qdev_get_gpio_in(orgate, 2));
597  
598      qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
599  }
600  
601  static void versal_create_cfu(Versal *s, qemu_irq *pic)
602  {
603      SysBusDevice *sbd;
604      DeviceState *dev;
605      int i;
606      const struct {
607          uint64_t reg_base;
608          uint64_t fdri_base;
609      } cframe_addr[] = {
610          { MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
611          { MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
612          { MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
613          { MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
614          { MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
615          { MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
616          { MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
617          { MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
618          { MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
619          { MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
620          { MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
621          { MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
622          { MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
623          { MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
624          { MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
625      };
626      const struct {
627          uint32_t blktype0_frames;
628          uint32_t blktype1_frames;
629          uint32_t blktype2_frames;
630          uint32_t blktype3_frames;
631          uint32_t blktype4_frames;
632          uint32_t blktype5_frames;
633          uint32_t blktype6_frames;
634      } cframe_cfg[] = {
635          [0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
636          [1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
637          [2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
638          [3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
639      };
640  
641      /* CFU FDRO */
642      object_initialize_child(OBJECT(s), "cfu-fdro", &s->pmc.cfu_fdro,
643                              TYPE_XLNX_VERSAL_CFU_FDRO);
644      sbd = SYS_BUS_DEVICE(&s->pmc.cfu_fdro);
645  
646      sysbus_realize(sbd, &error_fatal);
647      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_FDRO,
648                                  sysbus_mmio_get_region(sbd, 0));
649  
650      /* CFRAME REG */
651      for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
652          g_autofree char *name = g_strdup_printf("cframe%d", i);
653  
654          object_initialize_child(OBJECT(s), name, &s->pmc.cframe[i],
655                                  TYPE_XLNX_VERSAL_CFRAME_REG);
656  
657          sbd = SYS_BUS_DEVICE(&s->pmc.cframe[i]);
658          dev = DEVICE(&s->pmc.cframe[i]);
659  
660          if (i < ARRAY_SIZE(cframe_cfg)) {
661              object_property_set_int(OBJECT(dev), "blktype0-frames",
662                                      cframe_cfg[i].blktype0_frames,
663                                      &error_abort);
664              object_property_set_int(OBJECT(dev), "blktype1-frames",
665                                      cframe_cfg[i].blktype1_frames,
666                                      &error_abort);
667              object_property_set_int(OBJECT(dev), "blktype2-frames",
668                                      cframe_cfg[i].blktype2_frames,
669                                      &error_abort);
670              object_property_set_int(OBJECT(dev), "blktype3-frames",
671                                      cframe_cfg[i].blktype3_frames,
672                                      &error_abort);
673              object_property_set_int(OBJECT(dev), "blktype4-frames",
674                                      cframe_cfg[i].blktype4_frames,
675                                      &error_abort);
676              object_property_set_int(OBJECT(dev), "blktype5-frames",
677                                      cframe_cfg[i].blktype5_frames,
678                                      &error_abort);
679              object_property_set_int(OBJECT(dev), "blktype6-frames",
680                                      cframe_cfg[i].blktype6_frames,
681                                      &error_abort);
682          }
683          object_property_set_link(OBJECT(dev), "cfu-fdro",
684                                   OBJECT(&s->pmc.cfu_fdro), &error_fatal);
685  
686          sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
687  
688          memory_region_add_subregion(&s->mr_ps, cframe_addr[i].reg_base,
689                                      sysbus_mmio_get_region(sbd, 0));
690          memory_region_add_subregion(&s->mr_ps, cframe_addr[i].fdri_base,
691                                      sysbus_mmio_get_region(sbd, 1));
692          sysbus_connect_irq(sbd, 0,
693                             qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate),
694                                              3 + i));
695      }
696  
697      /* CFRAME BCAST */
698      object_initialize_child(OBJECT(s), "cframe_bcast", &s->pmc.cframe_bcast,
699                              TYPE_XLNX_VERSAL_CFRAME_BCAST_REG);
700  
701      sbd = SYS_BUS_DEVICE(&s->pmc.cframe_bcast);
702      dev = DEVICE(&s->pmc.cframe_bcast);
703  
704      for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
705          g_autofree char *propname = g_strdup_printf("cframe%d", i);
706          object_property_set_link(OBJECT(dev), propname,
707                                   OBJECT(&s->pmc.cframe[i]), &error_fatal);
708      }
709  
710      sysbus_realize(sbd, &error_fatal);
711  
712      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_REG,
713                                  sysbus_mmio_get_region(sbd, 0));
714      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_FDRI,
715                                  sysbus_mmio_get_region(sbd, 1));
716  
717      /* CFU APB */
718      object_initialize_child(OBJECT(s), "cfu-apb", &s->pmc.cfu_apb,
719                              TYPE_XLNX_VERSAL_CFU_APB);
720      sbd = SYS_BUS_DEVICE(&s->pmc.cfu_apb);
721      dev = DEVICE(&s->pmc.cfu_apb);
722  
723      for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
724          g_autofree char *propname = g_strdup_printf("cframe%d", i);
725          object_property_set_link(OBJECT(dev), propname,
726                                   OBJECT(&s->pmc.cframe[i]), &error_fatal);
727      }
728  
729      sysbus_realize(sbd, &error_fatal);
730      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_APB,
731                                  sysbus_mmio_get_region(sbd, 0));
732      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM,
733                                  sysbus_mmio_get_region(sbd, 1));
734      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM_2,
735                                  sysbus_mmio_get_region(sbd, 2));
736      sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
737  
738      /* CFU SFR */
739      object_initialize_child(OBJECT(s), "cfu-sfr", &s->pmc.cfu_sfr,
740                              TYPE_XLNX_VERSAL_CFU_SFR);
741  
742      sbd = SYS_BUS_DEVICE(&s->pmc.cfu_sfr);
743  
744      object_property_set_link(OBJECT(&s->pmc.cfu_sfr),
745                              "cfu", OBJECT(&s->pmc.cfu_apb), &error_abort);
746  
747      sysbus_realize(sbd, &error_fatal);
748      memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_SFR,
749                                  sysbus_mmio_get_region(sbd, 0));
750  }
751  
752  static void versal_create_crl(Versal *s, qemu_irq *pic)
753  {
754      SysBusDevice *sbd;
755      int i;
756  
757      object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
758                              TYPE_XLNX_VERSAL_CRL);
759      sbd = SYS_BUS_DEVICE(&s->lpd.crl);
760  
761      for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
762          g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
763  
764          object_property_set_link(OBJECT(&s->lpd.crl),
765                                   name, OBJECT(&s->lpd.rpu.cpu[i]),
766                                   &error_abort);
767      }
768  
769      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
770          g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
771  
772          object_property_set_link(OBJECT(&s->lpd.crl),
773                                   name, OBJECT(&s->lpd.iou.gem[i]),
774                                   &error_abort);
775      }
776  
777      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
778          g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
779  
780          object_property_set_link(OBJECT(&s->lpd.crl),
781                                   name, OBJECT(&s->lpd.iou.adma[i]),
782                                   &error_abort);
783      }
784  
785      for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
786          g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
787  
788          object_property_set_link(OBJECT(&s->lpd.crl),
789                                   name, OBJECT(&s->lpd.iou.uart[i]),
790                                   &error_abort);
791      }
792  
793      object_property_set_link(OBJECT(&s->lpd.crl),
794                               "usb", OBJECT(&s->lpd.iou.usb),
795                               &error_abort);
796  
797      sysbus_realize(sbd, &error_fatal);
798      memory_region_add_subregion(&s->mr_ps, MM_CRL,
799                                  sysbus_mmio_get_region(sbd, 0));
800      sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
801  }
802  
803  /* This takes the board allocated linear DDR memory and creates aliases
804   * for each split DDR range/aperture on the Versal address map.
805   */
806  static void versal_map_ddr(Versal *s)
807  {
808      uint64_t size = memory_region_size(s->cfg.mr_ddr);
809      /* Describes the various split DDR access regions.  */
810      static const struct {
811          uint64_t base;
812          uint64_t size;
813      } addr_ranges[] = {
814          { MM_TOP_DDR, MM_TOP_DDR_SIZE },
815          { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
816          { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
817          { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
818      };
819      uint64_t offset = 0;
820      int i;
821  
822      assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
823      for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
824          char *name;
825          uint64_t mapsize;
826  
827          mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
828          name = g_strdup_printf("noc-ddr-range%d", i);
829          /* Create the MR alias.  */
830          memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
831                                   name, s->cfg.mr_ddr,
832                                   offset, mapsize);
833  
834          /* Map it onto the NoC MR.  */
835          memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
836                                      &s->noc.mr_ddr_ranges[i]);
837          offset += mapsize;
838          size -= mapsize;
839          g_free(name);
840      }
841  }
842  
843  static void versal_unimp_area(Versal *s, const char *name,
844                                  MemoryRegion *mr,
845                                  hwaddr base, hwaddr size)
846  {
847      DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
848      MemoryRegion *mr_dev;
849  
850      qdev_prop_set_string(dev, "name", name);
851      qdev_prop_set_uint64(dev, "size", size);
852      object_property_add_child(OBJECT(s), name, OBJECT(dev));
853      sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
854  
855      mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
856      memory_region_add_subregion(mr, base, mr_dev);
857  }
858  
859  static void versal_unimp_sd_emmc_sel(void *opaque, int n, int level)
860  {
861      qemu_log_mask(LOG_UNIMP,
862                    "Selecting between enabling SD mode or eMMC mode on "
863                    "controller %d is not yet implemented\n", n);
864  }
865  
866  static void versal_unimp_qspi_ospi_mux_sel(void *opaque, int n, int level)
867  {
868      qemu_log_mask(LOG_UNIMP,
869                    "Selecting between enabling the QSPI or OSPI linear address "
870                    "region is not yet implemented\n");
871  }
872  
873  static void versal_unimp_irq_parity_imr(void *opaque, int n, int level)
874  {
875      qemu_log_mask(LOG_UNIMP,
876                    "PMC SLCR parity interrupt behaviour "
877                    "is not yet implemented\n");
878  }
879  
880  static void versal_unimp(Versal *s)
881  {
882      qemu_irq gpio_in;
883  
884      versal_unimp_area(s, "psm", &s->mr_ps,
885                          MM_PSM_START, MM_PSM_END - MM_PSM_START);
886      versal_unimp_area(s, "crf", &s->mr_ps,
887                          MM_FPD_CRF, MM_FPD_CRF_SIZE);
888      versal_unimp_area(s, "apu", &s->mr_ps,
889                          MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE);
890      versal_unimp_area(s, "crp", &s->mr_ps,
891                          MM_PMC_CRP, MM_PMC_CRP_SIZE);
892      versal_unimp_area(s, "iou-scntr", &s->mr_ps,
893                          MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
894      versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
895                          MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
896  
897      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel,
898                              "sd-emmc-sel-dummy", 2);
899      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel,
900                              "qspi-ospi-mux-sel-dummy", 1);
901      qdev_init_gpio_in_named(DEVICE(s), versal_unimp_irq_parity_imr,
902                              "irq-parity-imr-dummy", 1);
903  
904      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 0);
905      qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 0,
906                                  gpio_in);
907  
908      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 1);
909      qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 1,
910                                  gpio_in);
911  
912      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "qspi-ospi-mux-sel-dummy", 0);
913      qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
914                                  "qspi-ospi-mux-sel", 0,
915                                  gpio_in);
916  
917      gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0);
918      qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr),
919                                  SYSBUS_DEVICE_GPIO_IRQ, 0,
920                                  gpio_in);
921  }
922  
923  static void versal_realize(DeviceState *dev, Error **errp)
924  {
925      Versal *s = XLNX_VERSAL(dev);
926      qemu_irq pic[XLNX_VERSAL_NR_IRQS];
927  
928      versal_create_apu_cpus(s);
929      versal_create_apu_gic(s, pic);
930      versal_create_rpu_cpus(s);
931      versal_create_uarts(s, pic);
932      versal_create_canfds(s, pic);
933      versal_create_usbs(s, pic);
934      versal_create_gems(s, pic);
935      versal_create_admas(s, pic);
936      versal_create_sds(s, pic);
937      versal_create_pmc_apb_irq_orgate(s, pic);
938      versal_create_rtc(s, pic);
939      versal_create_trng(s, pic);
940      versal_create_xrams(s, pic);
941      versal_create_bbram(s, pic);
942      versal_create_efuse(s, pic);
943      versal_create_pmc_iou_slcr(s, pic);
944      versal_create_ospi(s, pic);
945      versal_create_crl(s, pic);
946      versal_create_cfu(s, pic);
947      versal_map_ddr(s);
948      versal_unimp(s);
949  
950      /* Create the On Chip Memory (OCM).  */
951      memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
952                             MM_OCM_SIZE, &error_fatal);
953  
954      memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
955      memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
956      memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
957                                          &s->lpd.rpu.mr_ps_alias, 0);
958  }
959  
960  static void versal_init(Object *obj)
961  {
962      Versal *s = XLNX_VERSAL(obj);
963  
964      memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
965      memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
966      memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
967      memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
968                               "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
969  }
970  
971  static const Property versal_properties[] = {
972      DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
973                       MemoryRegion *),
974      DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0],
975                        TYPE_CAN_BUS, CanBusState *),
976      DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
977                        TYPE_CAN_BUS, CanBusState *),
978  };
979  
980  static void versal_class_init(ObjectClass *klass, void *data)
981  {
982      DeviceClass *dc = DEVICE_CLASS(klass);
983  
984      dc->realize = versal_realize;
985      device_class_set_props(dc, versal_properties);
986      /* No VMSD since we haven't got any top-level SoC state to save.  */
987  }
988  
989  static const TypeInfo versal_info = {
990      .name = TYPE_XLNX_VERSAL,
991      .parent = TYPE_SYS_BUS_DEVICE,
992      .instance_size = sizeof(Versal),
993      .instance_init = versal_init,
994      .class_init = versal_class_init,
995  };
996  
997  static void versal_register_types(void)
998  {
999      type_register_static(&versal_info);
1000  }
1001  
1002  type_init(versal_register_types);
1003