xref: /qemu/hw/arm/xlnx-versal.c (revision 7ad36e2e241bd924f774a1f9fb208c102da58e50)
1b89de436SEdgar E. Iglesias /*
2b89de436SEdgar E. Iglesias  * Xilinx Versal SoC model.
3b89de436SEdgar E. Iglesias  *
4b89de436SEdgar E. Iglesias  * Copyright (c) 2018 Xilinx Inc.
5b89de436SEdgar E. Iglesias  * Written by Edgar E. Iglesias
6b89de436SEdgar E. Iglesias  *
7b89de436SEdgar E. Iglesias  * This program is free software; you can redistribute it and/or modify
8b89de436SEdgar E. Iglesias  * it under the terms of the GNU General Public License version 2 or
9b89de436SEdgar E. Iglesias  * (at your option) any later version.
10b89de436SEdgar E. Iglesias  */
11b89de436SEdgar E. Iglesias 
12b89de436SEdgar E. Iglesias #include "qemu/osdep.h"
13b89de436SEdgar E. Iglesias #include "qapi/error.h"
14b89de436SEdgar E. Iglesias #include "qemu/log.h"
150b8fa32fSMarkus Armbruster #include "qemu/module.h"
16b89de436SEdgar E. Iglesias #include "hw/sysbus.h"
17b89de436SEdgar E. Iglesias #include "net/net.h"
18b89de436SEdgar E. Iglesias #include "sysemu/sysemu.h"
19b89de436SEdgar E. Iglesias #include "sysemu/kvm.h"
2012ec8bd5SPeter Maydell #include "hw/arm/boot.h"
21b89de436SEdgar E. Iglesias #include "kvm_arm.h"
22b89de436SEdgar E. Iglesias #include "hw/misc/unimp.h"
23b89de436SEdgar E. Iglesias #include "hw/arm/xlnx-versal.h"
24b89de436SEdgar E. Iglesias 
25b89de436SEdgar E. Iglesias #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
26b89de436SEdgar E. Iglesias #define GEM_REVISION        0x40070106
27b89de436SEdgar E. Iglesias 
28b89de436SEdgar E. Iglesias static void versal_create_apu_cpus(Versal *s)
29b89de436SEdgar E. Iglesias {
30b89de436SEdgar E. Iglesias     int i;
31b89de436SEdgar E. Iglesias 
32b89de436SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
33b89de436SEdgar E. Iglesias         Object *obj;
34b89de436SEdgar E. Iglesias 
359fc7fc4dSMarkus Armbruster         object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
369fc7fc4dSMarkus Armbruster                                 XLNX_VERSAL_ACPU_TYPE);
37ced18d5eSEdgar E. Iglesias         obj = OBJECT(&s->fpd.apu.cpu[i]);
385325cc34SMarkus Armbruster         object_property_set_int(obj, "psci-conduit", s->cfg.psci_conduit,
395325cc34SMarkus Armbruster                                 &error_abort);
40b89de436SEdgar E. Iglesias         if (i) {
41c07c0c37SEdgar E. Iglesias             /* Secondary CPUs start in PSCI powered-down state */
425325cc34SMarkus Armbruster             object_property_set_bool(obj, "start-powered-off", true,
435325cc34SMarkus Armbruster                                      &error_abort);
44b89de436SEdgar E. Iglesias         }
45b89de436SEdgar E. Iglesias 
465325cc34SMarkus Armbruster         object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu),
475325cc34SMarkus Armbruster                                 &error_abort);
485325cc34SMarkus Armbruster         object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr),
49b89de436SEdgar E. Iglesias                                  &error_abort);
50ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(obj), NULL, &error_fatal);
51b89de436SEdgar E. Iglesias     }
52b89de436SEdgar E. Iglesias }
53b89de436SEdgar E. Iglesias 
54b89de436SEdgar E. Iglesias static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
55b89de436SEdgar E. Iglesias {
56b89de436SEdgar E. Iglesias     static const uint64_t addrs[] = {
57b89de436SEdgar E. Iglesias         MM_GIC_APU_DIST_MAIN,
58b89de436SEdgar E. Iglesias         MM_GIC_APU_REDIST_0
59b89de436SEdgar E. Iglesias     };
60b89de436SEdgar E. Iglesias     SysBusDevice *gicbusdev;
61b89de436SEdgar E. Iglesias     DeviceState *gicdev;
62b89de436SEdgar E. Iglesias     int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
63b89de436SEdgar E. Iglesias     int i;
64b89de436SEdgar E. Iglesias 
650074fce6SMarkus Armbruster     object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic,
66b89de436SEdgar E. Iglesias                             gicv3_class_name());
67b89de436SEdgar E. Iglesias     gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
68b89de436SEdgar E. Iglesias     gicdev = DEVICE(&s->fpd.apu.gic);
69b89de436SEdgar E. Iglesias     qdev_prop_set_uint32(gicdev, "revision", 3);
70b89de436SEdgar E. Iglesias     qdev_prop_set_uint32(gicdev, "num-cpu", 2);
71b89de436SEdgar E. Iglesias     qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
72b89de436SEdgar E. Iglesias     qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
73b89de436SEdgar E. Iglesias     qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2);
74b89de436SEdgar E. Iglesias     qdev_prop_set_bit(gicdev, "has-security-extensions", true);
75b89de436SEdgar E. Iglesias 
760074fce6SMarkus Armbruster     sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal);
77b89de436SEdgar E. Iglesias 
78b89de436SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(addrs); i++) {
79b89de436SEdgar E. Iglesias         MemoryRegion *mr;
80b89de436SEdgar E. Iglesias 
81b89de436SEdgar E. Iglesias         mr = sysbus_mmio_get_region(gicbusdev, i);
82b89de436SEdgar E. Iglesias         memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
83b89de436SEdgar E. Iglesias     }
84b89de436SEdgar E. Iglesias 
85b89de436SEdgar E. Iglesias     for (i = 0; i < nr_apu_cpus; i++) {
86ced18d5eSEdgar E. Iglesias         DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]);
87b89de436SEdgar E. Iglesias         int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
88b89de436SEdgar E. Iglesias         qemu_irq maint_irq;
89b89de436SEdgar E. Iglesias         int ti;
90b89de436SEdgar E. Iglesias         /* Mapping from the output timer irq lines from the CPU to the
91b89de436SEdgar E. Iglesias          * GIC PPI inputs.
92b89de436SEdgar E. Iglesias          */
93b89de436SEdgar E. Iglesias         const int timer_irq[] = {
94b89de436SEdgar E. Iglesias             [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
95b89de436SEdgar E. Iglesias             [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
96b89de436SEdgar E. Iglesias             [GTIMER_HYP]  = VERSAL_TIMER_NS_EL2_IRQ,
97b89de436SEdgar E. Iglesias             [GTIMER_SEC]  = VERSAL_TIMER_S_EL1_IRQ,
98b89de436SEdgar E. Iglesias         };
99b89de436SEdgar E. Iglesias 
100b89de436SEdgar E. Iglesias         for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
101b89de436SEdgar E. Iglesias             qdev_connect_gpio_out(cpudev, ti,
102b89de436SEdgar E. Iglesias                                   qdev_get_gpio_in(gicdev,
103b89de436SEdgar E. Iglesias                                                    ppibase + timer_irq[ti]));
104b89de436SEdgar E. Iglesias         }
105b89de436SEdgar E. Iglesias         maint_irq = qdev_get_gpio_in(gicdev,
106b89de436SEdgar E. Iglesias                                         ppibase + VERSAL_GIC_MAINT_IRQ);
107b89de436SEdgar E. Iglesias         qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
108b89de436SEdgar E. Iglesias                                     0, maint_irq);
109b89de436SEdgar E. Iglesias         sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
110b89de436SEdgar E. Iglesias         sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
111b89de436SEdgar E. Iglesias                            qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
112b89de436SEdgar E. Iglesias         sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
113b89de436SEdgar E. Iglesias                            qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
114b89de436SEdgar E. Iglesias         sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
115b89de436SEdgar E. Iglesias                            qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
116b89de436SEdgar E. Iglesias     }
117b89de436SEdgar E. Iglesias 
118b89de436SEdgar E. Iglesias     for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
119b89de436SEdgar E. Iglesias         pic[i] = qdev_get_gpio_in(gicdev, i);
120b89de436SEdgar E. Iglesias     }
121b89de436SEdgar E. Iglesias }
122b89de436SEdgar E. Iglesias 
123b89de436SEdgar E. Iglesias static void versal_create_uarts(Versal *s, qemu_irq *pic)
124b89de436SEdgar E. Iglesias {
125b89de436SEdgar E. Iglesias     int i;
126b89de436SEdgar E. Iglesias 
127b89de436SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
128b89de436SEdgar E. Iglesias         static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
129b89de436SEdgar E. Iglesias         static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
130b89de436SEdgar E. Iglesias         char *name = g_strdup_printf("uart%d", i);
131b89de436SEdgar E. Iglesias         DeviceState *dev;
132b89de436SEdgar E. Iglesias         MemoryRegion *mr;
133b89de436SEdgar E. Iglesias 
1340074fce6SMarkus Armbruster         object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i],
13588052ffdSEdgar E. Iglesias                                 TYPE_PL011);
13688052ffdSEdgar E. Iglesias         dev = DEVICE(&s->lpd.iou.uart[i]);
137b89de436SEdgar E. Iglesias         qdev_prop_set_chr(dev, "chardev", serial_hd(i));
1380074fce6SMarkus Armbruster         sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
139b89de436SEdgar E. Iglesias 
14088052ffdSEdgar E. Iglesias         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
141b89de436SEdgar E. Iglesias         memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
142b89de436SEdgar E. Iglesias 
14388052ffdSEdgar E. Iglesias         sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
144b89de436SEdgar E. Iglesias         g_free(name);
145b89de436SEdgar E. Iglesias     }
146b89de436SEdgar E. Iglesias }
147b89de436SEdgar E. Iglesias 
148b89de436SEdgar E. Iglesias static void versal_create_gems(Versal *s, qemu_irq *pic)
149b89de436SEdgar E. Iglesias {
150b89de436SEdgar E. Iglesias     int i;
151b89de436SEdgar E. Iglesias 
152b89de436SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
153b89de436SEdgar E. Iglesias         static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
154b89de436SEdgar E. Iglesias         static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
155b89de436SEdgar E. Iglesias         char *name = g_strdup_printf("gem%d", i);
156b89de436SEdgar E. Iglesias         NICInfo *nd = &nd_table[i];
157b89de436SEdgar E. Iglesias         DeviceState *dev;
158b89de436SEdgar E. Iglesias         MemoryRegion *mr;
159b89de436SEdgar E. Iglesias 
1600074fce6SMarkus Armbruster         object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i],
1614bd9b59cSEdgar E. Iglesias                                 TYPE_CADENCE_GEM);
1624bd9b59cSEdgar E. Iglesias         dev = DEVICE(&s->lpd.iou.gem[i]);
163*7ad36e2eSMarkus Armbruster         /* FIXME use qdev NIC properties instead of nd_table[] */
164b89de436SEdgar E. Iglesias         if (nd->used) {
165b89de436SEdgar E. Iglesias             qemu_check_nic_model(nd, "cadence_gem");
166b89de436SEdgar E. Iglesias             qdev_set_nic_properties(dev, nd);
167b89de436SEdgar E. Iglesias         }
1685325cc34SMarkus Armbruster         object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
169b89de436SEdgar E. Iglesias                                 &error_abort);
1705325cc34SMarkus Armbruster         object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
171b89de436SEdgar E. Iglesias                                  &error_abort);
1720074fce6SMarkus Armbruster         sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
173b89de436SEdgar E. Iglesias 
1744bd9b59cSEdgar E. Iglesias         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
175b89de436SEdgar E. Iglesias         memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
176b89de436SEdgar E. Iglesias 
1774bd9b59cSEdgar E. Iglesias         sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
178b89de436SEdgar E. Iglesias         g_free(name);
179b89de436SEdgar E. Iglesias     }
180b89de436SEdgar E. Iglesias }
181b89de436SEdgar E. Iglesias 
1828a218651SEdgar E. Iglesias static void versal_create_admas(Versal *s, qemu_irq *pic)
1838a218651SEdgar E. Iglesias {
1848a218651SEdgar E. Iglesias     int i;
1858a218651SEdgar E. Iglesias 
1868a218651SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
1878a218651SEdgar E. Iglesias         char *name = g_strdup_printf("adma%d", i);
1888a218651SEdgar E. Iglesias         DeviceState *dev;
1898a218651SEdgar E. Iglesias         MemoryRegion *mr;
1908a218651SEdgar E. Iglesias 
1910074fce6SMarkus Armbruster         object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i],
192f4e3fa37SEdgar E. Iglesias                                 TYPE_XLNX_ZDMA);
193f4e3fa37SEdgar E. Iglesias         dev = DEVICE(&s->lpd.iou.adma[i]);
1945325cc34SMarkus Armbruster         object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort);
1950074fce6SMarkus Armbruster         sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
1968a218651SEdgar E. Iglesias 
197f4e3fa37SEdgar E. Iglesias         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
1988a218651SEdgar E. Iglesias         memory_region_add_subregion(&s->mr_ps,
1998a218651SEdgar E. Iglesias                                     MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
2008a218651SEdgar E. Iglesias 
201f4e3fa37SEdgar E. Iglesias         sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]);
2028a218651SEdgar E. Iglesias         g_free(name);
2038a218651SEdgar E. Iglesias     }
2048a218651SEdgar E. Iglesias }
2058a218651SEdgar E. Iglesias 
206724c6e12SEdgar E. Iglesias #define SDHCI_CAPABILITIES  0x280737ec6481 /* Same as on ZynqMP.  */
207724c6e12SEdgar E. Iglesias static void versal_create_sds(Versal *s, qemu_irq *pic)
208724c6e12SEdgar E. Iglesias {
209724c6e12SEdgar E. Iglesias     int i;
210724c6e12SEdgar E. Iglesias 
211724c6e12SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) {
212724c6e12SEdgar E. Iglesias         DeviceState *dev;
213724c6e12SEdgar E. Iglesias         MemoryRegion *mr;
214724c6e12SEdgar E. Iglesias 
2150074fce6SMarkus Armbruster         object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i],
216724c6e12SEdgar E. Iglesias                                 TYPE_SYSBUS_SDHCI);
217724c6e12SEdgar E. Iglesias         dev = DEVICE(&s->pmc.iou.sd[i]);
218724c6e12SEdgar E. Iglesias 
2195325cc34SMarkus Armbruster         object_property_set_uint(OBJECT(dev), "sd-spec-version", 3,
220724c6e12SEdgar E. Iglesias                                  &error_fatal);
2215325cc34SMarkus Armbruster         object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES,
2225325cc34SMarkus Armbruster                                  &error_fatal);
2235325cc34SMarkus Armbruster         object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal);
2240074fce6SMarkus Armbruster         sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
225724c6e12SEdgar E. Iglesias 
226724c6e12SEdgar E. Iglesias         mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
227724c6e12SEdgar E. Iglesias         memory_region_add_subregion(&s->mr_ps,
228724c6e12SEdgar E. Iglesias                                     MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr);
229724c6e12SEdgar E. Iglesias 
230724c6e12SEdgar E. Iglesias         sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
231724c6e12SEdgar E. Iglesias                            pic[VERSAL_SD0_IRQ_0 + i * 2]);
232724c6e12SEdgar E. Iglesias     }
233724c6e12SEdgar E. Iglesias }
234724c6e12SEdgar E. Iglesias 
235eb1221c5SEdgar E. Iglesias static void versal_create_rtc(Versal *s, qemu_irq *pic)
236eb1221c5SEdgar E. Iglesias {
237eb1221c5SEdgar E. Iglesias     SysBusDevice *sbd;
238eb1221c5SEdgar E. Iglesias     MemoryRegion *mr;
239eb1221c5SEdgar E. Iglesias 
2405a147c8cSMarkus Armbruster     object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
241eb1221c5SEdgar E. Iglesias                             TYPE_XLNX_ZYNQMP_RTC);
242eb1221c5SEdgar E. Iglesias     sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
2435a147c8cSMarkus Armbruster     sysbus_realize(SYS_BUS_DEVICE(sbd), &error_fatal);
244eb1221c5SEdgar E. Iglesias 
245eb1221c5SEdgar E. Iglesias     mr = sysbus_mmio_get_region(sbd, 0);
246eb1221c5SEdgar E. Iglesias     memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
247eb1221c5SEdgar E. Iglesias 
248eb1221c5SEdgar E. Iglesias     /*
249eb1221c5SEdgar E. Iglesias      * TODO: Connect the ALARM and SECONDS interrupts once our RTC model
250eb1221c5SEdgar E. Iglesias      * supports them.
251eb1221c5SEdgar E. Iglesias      */
252eb1221c5SEdgar E. Iglesias     sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]);
253eb1221c5SEdgar E. Iglesias }
254eb1221c5SEdgar E. Iglesias 
255b89de436SEdgar E. Iglesias /* This takes the board allocated linear DDR memory and creates aliases
256b89de436SEdgar E. Iglesias  * for each split DDR range/aperture on the Versal address map.
257b89de436SEdgar E. Iglesias  */
258b89de436SEdgar E. Iglesias static void versal_map_ddr(Versal *s)
259b89de436SEdgar E. Iglesias {
260b89de436SEdgar E. Iglesias     uint64_t size = memory_region_size(s->cfg.mr_ddr);
261b89de436SEdgar E. Iglesias     /* Describes the various split DDR access regions.  */
262b89de436SEdgar E. Iglesias     static const struct {
263b89de436SEdgar E. Iglesias         uint64_t base;
264b89de436SEdgar E. Iglesias         uint64_t size;
265b89de436SEdgar E. Iglesias     } addr_ranges[] = {
266b89de436SEdgar E. Iglesias         { MM_TOP_DDR, MM_TOP_DDR_SIZE },
267b89de436SEdgar E. Iglesias         { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
268b89de436SEdgar E. Iglesias         { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
269b89de436SEdgar E. Iglesias         { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
270b89de436SEdgar E. Iglesias     };
271b89de436SEdgar E. Iglesias     uint64_t offset = 0;
272b89de436SEdgar E. Iglesias     int i;
273b89de436SEdgar E. Iglesias 
274b89de436SEdgar E. Iglesias     assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
275b89de436SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
276b89de436SEdgar E. Iglesias         char *name;
277b89de436SEdgar E. Iglesias         uint64_t mapsize;
278b89de436SEdgar E. Iglesias 
279b89de436SEdgar E. Iglesias         mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
280b89de436SEdgar E. Iglesias         name = g_strdup_printf("noc-ddr-range%d", i);
281b89de436SEdgar E. Iglesias         /* Create the MR alias.  */
282b89de436SEdgar E. Iglesias         memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
283b89de436SEdgar E. Iglesias                                  name, s->cfg.mr_ddr,
284b89de436SEdgar E. Iglesias                                  offset, mapsize);
285b89de436SEdgar E. Iglesias 
286b89de436SEdgar E. Iglesias         /* Map it onto the NoC MR.  */
287b89de436SEdgar E. Iglesias         memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
288b89de436SEdgar E. Iglesias                                     &s->noc.mr_ddr_ranges[i]);
289b89de436SEdgar E. Iglesias         offset += mapsize;
290b89de436SEdgar E. Iglesias         size -= mapsize;
291b89de436SEdgar E. Iglesias         g_free(name);
292b89de436SEdgar E. Iglesias     }
293b89de436SEdgar E. Iglesias }
294b89de436SEdgar E. Iglesias 
295b89de436SEdgar E. Iglesias static void versal_unimp_area(Versal *s, const char *name,
296b89de436SEdgar E. Iglesias                                 MemoryRegion *mr,
297b89de436SEdgar E. Iglesias                                 hwaddr base, hwaddr size)
298b89de436SEdgar E. Iglesias {
2993e80f690SMarkus Armbruster     DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
300b89de436SEdgar E. Iglesias     MemoryRegion *mr_dev;
301b89de436SEdgar E. Iglesias 
302b89de436SEdgar E. Iglesias     qdev_prop_set_string(dev, "name", name);
303b89de436SEdgar E. Iglesias     qdev_prop_set_uint64(dev, "size", size);
304d2623129SMarkus Armbruster     object_property_add_child(OBJECT(s), name, OBJECT(dev));
3053c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
306b89de436SEdgar E. Iglesias 
307b89de436SEdgar E. Iglesias     mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
308b89de436SEdgar E. Iglesias     memory_region_add_subregion(mr, base, mr_dev);
309b89de436SEdgar E. Iglesias }
310b89de436SEdgar E. Iglesias 
311b89de436SEdgar E. Iglesias static void versal_unimp(Versal *s)
312b89de436SEdgar E. Iglesias {
313b89de436SEdgar E. Iglesias     versal_unimp_area(s, "psm", &s->mr_ps,
314b89de436SEdgar E. Iglesias                         MM_PSM_START, MM_PSM_END - MM_PSM_START);
315b89de436SEdgar E. Iglesias     versal_unimp_area(s, "crl", &s->mr_ps,
316b89de436SEdgar E. Iglesias                         MM_CRL, MM_CRL_SIZE);
317b89de436SEdgar E. Iglesias     versal_unimp_area(s, "crf", &s->mr_ps,
318b89de436SEdgar E. Iglesias                         MM_FPD_CRF, MM_FPD_CRF_SIZE);
319f0138990SEdgar E. Iglesias     versal_unimp_area(s, "crp", &s->mr_ps,
320f0138990SEdgar E. Iglesias                         MM_PMC_CRP, MM_PMC_CRP_SIZE);
321b89de436SEdgar E. Iglesias     versal_unimp_area(s, "iou-scntr", &s->mr_ps,
322b89de436SEdgar E. Iglesias                         MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
323b89de436SEdgar E. Iglesias     versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
324b89de436SEdgar E. Iglesias                         MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
325b89de436SEdgar E. Iglesias }
326b89de436SEdgar E. Iglesias 
327b89de436SEdgar E. Iglesias static void versal_realize(DeviceState *dev, Error **errp)
328b89de436SEdgar E. Iglesias {
329b89de436SEdgar E. Iglesias     Versal *s = XLNX_VERSAL(dev);
330b89de436SEdgar E. Iglesias     qemu_irq pic[XLNX_VERSAL_NR_IRQS];
331b89de436SEdgar E. Iglesias 
332b89de436SEdgar E. Iglesias     versal_create_apu_cpus(s);
333b89de436SEdgar E. Iglesias     versal_create_apu_gic(s, pic);
334b89de436SEdgar E. Iglesias     versal_create_uarts(s, pic);
335b89de436SEdgar E. Iglesias     versal_create_gems(s, pic);
3368a218651SEdgar E. Iglesias     versal_create_admas(s, pic);
337724c6e12SEdgar E. Iglesias     versal_create_sds(s, pic);
338eb1221c5SEdgar E. Iglesias     versal_create_rtc(s, pic);
339b89de436SEdgar E. Iglesias     versal_map_ddr(s);
340b89de436SEdgar E. Iglesias     versal_unimp(s);
341b89de436SEdgar E. Iglesias 
342b89de436SEdgar E. Iglesias     /* Create the On Chip Memory (OCM).  */
343b89de436SEdgar E. Iglesias     memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
344b89de436SEdgar E. Iglesias                            MM_OCM_SIZE, &error_fatal);
345b89de436SEdgar E. Iglesias 
346b89de436SEdgar E. Iglesias     memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
347b89de436SEdgar E. Iglesias     memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
348b89de436SEdgar E. Iglesias }
349b89de436SEdgar E. Iglesias 
350b89de436SEdgar E. Iglesias static void versal_init(Object *obj)
351b89de436SEdgar E. Iglesias {
352b89de436SEdgar E. Iglesias     Versal *s = XLNX_VERSAL(obj);
353b89de436SEdgar E. Iglesias 
354b89de436SEdgar E. Iglesias     memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
355b89de436SEdgar E. Iglesias     memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
356b89de436SEdgar E. Iglesias }
357b89de436SEdgar E. Iglesias 
358b89de436SEdgar E. Iglesias static Property versal_properties[] = {
359b89de436SEdgar E. Iglesias     DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
360b89de436SEdgar E. Iglesias                      MemoryRegion *),
361b89de436SEdgar E. Iglesias     DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
362b89de436SEdgar E. Iglesias     DEFINE_PROP_END_OF_LIST()
363b89de436SEdgar E. Iglesias };
364b89de436SEdgar E. Iglesias 
365b89de436SEdgar E. Iglesias static void versal_class_init(ObjectClass *klass, void *data)
366b89de436SEdgar E. Iglesias {
367b89de436SEdgar E. Iglesias     DeviceClass *dc = DEVICE_CLASS(klass);
368b89de436SEdgar E. Iglesias 
369b89de436SEdgar E. Iglesias     dc->realize = versal_realize;
3704f67d30bSMarc-André Lureau     device_class_set_props(dc, versal_properties);
371b89de436SEdgar E. Iglesias     /* No VMSD since we haven't got any top-level SoC state to save.  */
372b89de436SEdgar E. Iglesias }
373b89de436SEdgar E. Iglesias 
374b89de436SEdgar E. Iglesias static const TypeInfo versal_info = {
375b89de436SEdgar E. Iglesias     .name = TYPE_XLNX_VERSAL,
376b89de436SEdgar E. Iglesias     .parent = TYPE_SYS_BUS_DEVICE,
377b89de436SEdgar E. Iglesias     .instance_size = sizeof(Versal),
378b89de436SEdgar E. Iglesias     .instance_init = versal_init,
379b89de436SEdgar E. Iglesias     .class_init = versal_class_init,
380b89de436SEdgar E. Iglesias };
381b89de436SEdgar E. Iglesias 
382b89de436SEdgar E. Iglesias static void versal_register_types(void)
383b89de436SEdgar E. Iglesias {
384b89de436SEdgar E. Iglesias     type_register_static(&versal_info);
385b89de436SEdgar E. Iglesias }
386b89de436SEdgar E. Iglesias 
387b89de436SEdgar E. Iglesias type_init(versal_register_types);
388