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" 13a55b441bSEdgar E. Iglesias #include "qemu/units.h" 14b89de436SEdgar E. Iglesias #include "qapi/error.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" 24f7c9aecbSFrancisco Iglesias #include "qemu/log.h" 25f7c9aecbSFrancisco Iglesias #include "hw/sysbus.h" 26b89de436SEdgar E. Iglesias 27b89de436SEdgar E. Iglesias #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") 28*67a645a3SEdgar E. Iglesias #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f") 29b89de436SEdgar E. Iglesias #define GEM_REVISION 0x40070106 30b89de436SEdgar E. Iglesias 31f7c9aecbSFrancisco Iglesias #define VERSAL_NUM_PMC_APB_IRQS 3 32868d9680SFrancisco Iglesias #define NUM_OSPI_IRQ_LINES 3 339a6d4918SFrancisco Iglesias 34b89de436SEdgar E. Iglesias static void versal_create_apu_cpus(Versal *s) 35b89de436SEdgar E. Iglesias { 36b89de436SEdgar E. Iglesias int i; 37b89de436SEdgar E. Iglesias 388779d00cSEdgar E. Iglesias object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster, 398779d00cSEdgar E. Iglesias TYPE_CPU_CLUSTER); 408779d00cSEdgar E. Iglesias qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0); 418779d00cSEdgar E. Iglesias 42b89de436SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) { 43b89de436SEdgar E. Iglesias Object *obj; 44b89de436SEdgar E. Iglesias 458779d00cSEdgar E. Iglesias object_initialize_child(OBJECT(&s->fpd.apu.cluster), 468779d00cSEdgar E. Iglesias "apu-cpu[*]", &s->fpd.apu.cpu[i], 479fc7fc4dSMarkus Armbruster XLNX_VERSAL_ACPU_TYPE); 48ced18d5eSEdgar E. Iglesias obj = OBJECT(&s->fpd.apu.cpu[i]); 49b89de436SEdgar E. Iglesias if (i) { 509437a76eSPeter Maydell /* Secondary CPUs start in powered-down state */ 515325cc34SMarkus Armbruster object_property_set_bool(obj, "start-powered-off", true, 525325cc34SMarkus Armbruster &error_abort); 53b89de436SEdgar E. Iglesias } 54b89de436SEdgar E. Iglesias 555325cc34SMarkus Armbruster object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu), 565325cc34SMarkus Armbruster &error_abort); 575325cc34SMarkus Armbruster object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr), 58b89de436SEdgar E. Iglesias &error_abort); 59ce189ab2SMarkus Armbruster qdev_realize(DEVICE(obj), NULL, &error_fatal); 60b89de436SEdgar E. Iglesias } 618779d00cSEdgar E. Iglesias 628779d00cSEdgar E. Iglesias qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal); 63b89de436SEdgar E. Iglesias } 64b89de436SEdgar E. Iglesias 65b89de436SEdgar E. Iglesias static void versal_create_apu_gic(Versal *s, qemu_irq *pic) 66b89de436SEdgar E. Iglesias { 67b89de436SEdgar E. Iglesias static const uint64_t addrs[] = { 68b89de436SEdgar E. Iglesias MM_GIC_APU_DIST_MAIN, 69b89de436SEdgar E. Iglesias MM_GIC_APU_REDIST_0 70b89de436SEdgar E. Iglesias }; 71b89de436SEdgar E. Iglesias SysBusDevice *gicbusdev; 72b89de436SEdgar E. Iglesias DeviceState *gicdev; 73b89de436SEdgar E. Iglesias int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu); 74b89de436SEdgar E. Iglesias int i; 75b89de436SEdgar E. Iglesias 760074fce6SMarkus Armbruster object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic, 77b89de436SEdgar E. Iglesias gicv3_class_name()); 78b89de436SEdgar E. Iglesias gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic); 79b89de436SEdgar E. Iglesias gicdev = DEVICE(&s->fpd.apu.gic); 80b89de436SEdgar E. Iglesias qdev_prop_set_uint32(gicdev, "revision", 3); 814565d826SEdgar E. Iglesias qdev_prop_set_uint32(gicdev, "num-cpu", nr_apu_cpus); 82b89de436SEdgar E. Iglesias qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32); 83b89de436SEdgar E. Iglesias qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1); 844565d826SEdgar E. Iglesias qdev_prop_set_uint32(gicdev, "redist-region-count[0]", nr_apu_cpus); 85b89de436SEdgar E. Iglesias qdev_prop_set_bit(gicdev, "has-security-extensions", true); 86b89de436SEdgar E. Iglesias 870074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal); 88b89de436SEdgar E. Iglesias 89b89de436SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(addrs); i++) { 90b89de436SEdgar E. Iglesias MemoryRegion *mr; 91b89de436SEdgar E. Iglesias 92b89de436SEdgar E. Iglesias mr = sysbus_mmio_get_region(gicbusdev, i); 93b89de436SEdgar E. Iglesias memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr); 94b89de436SEdgar E. Iglesias } 95b89de436SEdgar E. Iglesias 96b89de436SEdgar E. Iglesias for (i = 0; i < nr_apu_cpus; i++) { 97ced18d5eSEdgar E. Iglesias DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]); 98b89de436SEdgar E. Iglesias int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; 99b89de436SEdgar E. Iglesias qemu_irq maint_irq; 100b89de436SEdgar E. Iglesias int ti; 101b89de436SEdgar E. Iglesias /* Mapping from the output timer irq lines from the CPU to the 102b89de436SEdgar E. Iglesias * GIC PPI inputs. 103b89de436SEdgar E. Iglesias */ 104b89de436SEdgar E. Iglesias const int timer_irq[] = { 105b89de436SEdgar E. Iglesias [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ, 106b89de436SEdgar E. Iglesias [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ, 107b89de436SEdgar E. Iglesias [GTIMER_HYP] = VERSAL_TIMER_NS_EL2_IRQ, 108b89de436SEdgar E. Iglesias [GTIMER_SEC] = VERSAL_TIMER_S_EL1_IRQ, 109b89de436SEdgar E. Iglesias }; 110b89de436SEdgar E. Iglesias 111b89de436SEdgar E. Iglesias for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) { 112b89de436SEdgar E. Iglesias qdev_connect_gpio_out(cpudev, ti, 113b89de436SEdgar E. Iglesias qdev_get_gpio_in(gicdev, 114b89de436SEdgar E. Iglesias ppibase + timer_irq[ti])); 115b89de436SEdgar E. Iglesias } 116b89de436SEdgar E. Iglesias maint_irq = qdev_get_gpio_in(gicdev, 117b89de436SEdgar E. Iglesias ppibase + VERSAL_GIC_MAINT_IRQ); 118b89de436SEdgar E. Iglesias qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 119b89de436SEdgar E. Iglesias 0, maint_irq); 120b89de436SEdgar E. Iglesias sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); 121b89de436SEdgar E. Iglesias sysbus_connect_irq(gicbusdev, i + nr_apu_cpus, 122b89de436SEdgar E. Iglesias qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); 123b89de436SEdgar E. Iglesias sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus, 124b89de436SEdgar E. Iglesias qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); 125b89de436SEdgar E. Iglesias sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus, 126b89de436SEdgar E. Iglesias qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); 127b89de436SEdgar E. Iglesias } 128b89de436SEdgar E. Iglesias 129b89de436SEdgar E. Iglesias for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) { 130b89de436SEdgar E. Iglesias pic[i] = qdev_get_gpio_in(gicdev, i); 131b89de436SEdgar E. Iglesias } 132b89de436SEdgar E. Iglesias } 133b89de436SEdgar E. Iglesias 134*67a645a3SEdgar E. Iglesias static void versal_create_rpu_cpus(Versal *s) 135*67a645a3SEdgar E. Iglesias { 136*67a645a3SEdgar E. Iglesias int i; 137*67a645a3SEdgar E. Iglesias 138*67a645a3SEdgar E. Iglesias object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster, 139*67a645a3SEdgar E. Iglesias TYPE_CPU_CLUSTER); 140*67a645a3SEdgar E. Iglesias qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1); 141*67a645a3SEdgar E. Iglesias 142*67a645a3SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { 143*67a645a3SEdgar E. Iglesias Object *obj; 144*67a645a3SEdgar E. Iglesias 145*67a645a3SEdgar E. Iglesias object_initialize_child(OBJECT(&s->lpd.rpu.cluster), 146*67a645a3SEdgar E. Iglesias "rpu-cpu[*]", &s->lpd.rpu.cpu[i], 147*67a645a3SEdgar E. Iglesias XLNX_VERSAL_RCPU_TYPE); 148*67a645a3SEdgar E. Iglesias obj = OBJECT(&s->lpd.rpu.cpu[i]); 149*67a645a3SEdgar E. Iglesias object_property_set_bool(obj, "start-powered-off", true, 150*67a645a3SEdgar E. Iglesias &error_abort); 151*67a645a3SEdgar E. Iglesias 152*67a645a3SEdgar E. Iglesias object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort); 153*67a645a3SEdgar E. Iglesias object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu), 154*67a645a3SEdgar E. Iglesias &error_abort); 155*67a645a3SEdgar E. Iglesias object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr), 156*67a645a3SEdgar E. Iglesias &error_abort); 157*67a645a3SEdgar E. Iglesias qdev_realize(DEVICE(obj), NULL, &error_fatal); 158*67a645a3SEdgar E. Iglesias } 159*67a645a3SEdgar E. Iglesias 160*67a645a3SEdgar E. Iglesias qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal); 161*67a645a3SEdgar E. Iglesias } 162*67a645a3SEdgar E. Iglesias 163b89de436SEdgar E. Iglesias static void versal_create_uarts(Versal *s, qemu_irq *pic) 164b89de436SEdgar E. Iglesias { 165b89de436SEdgar E. Iglesias int i; 166b89de436SEdgar E. Iglesias 167b89de436SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) { 168b89de436SEdgar E. Iglesias static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0}; 169b89de436SEdgar E. Iglesias static const uint64_t addrs[] = { MM_UART0, MM_UART1 }; 170b89de436SEdgar E. Iglesias char *name = g_strdup_printf("uart%d", i); 171b89de436SEdgar E. Iglesias DeviceState *dev; 172b89de436SEdgar E. Iglesias MemoryRegion *mr; 173b89de436SEdgar E. Iglesias 1740074fce6SMarkus Armbruster object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i], 17588052ffdSEdgar E. Iglesias TYPE_PL011); 17688052ffdSEdgar E. Iglesias dev = DEVICE(&s->lpd.iou.uart[i]); 177b89de436SEdgar E. Iglesias qdev_prop_set_chr(dev, "chardev", serial_hd(i)); 1780074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); 179b89de436SEdgar E. Iglesias 18088052ffdSEdgar E. Iglesias mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); 181b89de436SEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, addrs[i], mr); 182b89de436SEdgar E. Iglesias 18388052ffdSEdgar E. Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]); 184b89de436SEdgar E. Iglesias g_free(name); 185b89de436SEdgar E. Iglesias } 186b89de436SEdgar E. Iglesias } 187b89de436SEdgar E. Iglesias 188144677d4SVikram Garhwal static void versal_create_usbs(Versal *s, qemu_irq *pic) 189144677d4SVikram Garhwal { 190144677d4SVikram Garhwal DeviceState *dev; 191144677d4SVikram Garhwal MemoryRegion *mr; 192144677d4SVikram Garhwal 193144677d4SVikram Garhwal object_initialize_child(OBJECT(s), "usb2", &s->lpd.iou.usb, 194144677d4SVikram Garhwal TYPE_XILINX_VERSAL_USB2); 195144677d4SVikram Garhwal dev = DEVICE(&s->lpd.iou.usb); 196144677d4SVikram Garhwal 197144677d4SVikram Garhwal object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps), 198144677d4SVikram Garhwal &error_abort); 199144677d4SVikram Garhwal qdev_prop_set_uint32(dev, "intrs", 1); 200144677d4SVikram Garhwal qdev_prop_set_uint32(dev, "slots", 2); 201144677d4SVikram Garhwal 202144677d4SVikram Garhwal sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); 203144677d4SVikram Garhwal 204144677d4SVikram Garhwal mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); 205144677d4SVikram Garhwal memory_region_add_subregion(&s->mr_ps, MM_USB_0, mr); 206144677d4SVikram Garhwal 207144677d4SVikram Garhwal sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_USB0_IRQ_0]); 208144677d4SVikram Garhwal 209144677d4SVikram Garhwal mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); 210144677d4SVikram Garhwal memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr); 211144677d4SVikram Garhwal } 212144677d4SVikram Garhwal 213b89de436SEdgar E. Iglesias static void versal_create_gems(Versal *s, qemu_irq *pic) 214b89de436SEdgar E. Iglesias { 215b89de436SEdgar E. Iglesias int i; 216b89de436SEdgar E. Iglesias 217b89de436SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) { 218b89de436SEdgar E. Iglesias static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0}; 219b89de436SEdgar E. Iglesias static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 }; 220b89de436SEdgar E. Iglesias char *name = g_strdup_printf("gem%d", i); 221b89de436SEdgar E. Iglesias NICInfo *nd = &nd_table[i]; 222b89de436SEdgar E. Iglesias DeviceState *dev; 223b89de436SEdgar E. Iglesias MemoryRegion *mr; 224b89de436SEdgar E. Iglesias 2250074fce6SMarkus Armbruster object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i], 2264bd9b59cSEdgar E. Iglesias TYPE_CADENCE_GEM); 2274bd9b59cSEdgar E. Iglesias dev = DEVICE(&s->lpd.iou.gem[i]); 2287ad36e2eSMarkus Armbruster /* FIXME use qdev NIC properties instead of nd_table[] */ 229b89de436SEdgar E. Iglesias if (nd->used) { 230b89de436SEdgar E. Iglesias qemu_check_nic_model(nd, "cadence_gem"); 231b89de436SEdgar E. Iglesias qdev_set_nic_properties(dev, nd); 232b89de436SEdgar E. Iglesias } 233dfc38879SBin Meng object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort); 2345325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "num-priority-queues", 2, 235b89de436SEdgar E. Iglesias &error_abort); 2365325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps), 237b89de436SEdgar E. Iglesias &error_abort); 2380074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); 239b89de436SEdgar E. Iglesias 2404bd9b59cSEdgar E. Iglesias mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); 241b89de436SEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, addrs[i], mr); 242b89de436SEdgar E. Iglesias 2434bd9b59cSEdgar E. Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]); 244b89de436SEdgar E. Iglesias g_free(name); 245b89de436SEdgar E. Iglesias } 246b89de436SEdgar E. Iglesias } 247b89de436SEdgar E. Iglesias 2488a218651SEdgar E. Iglesias static void versal_create_admas(Versal *s, qemu_irq *pic) 2498a218651SEdgar E. Iglesias { 2508a218651SEdgar E. Iglesias int i; 2518a218651SEdgar E. Iglesias 2528a218651SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) { 2538a218651SEdgar E. Iglesias char *name = g_strdup_printf("adma%d", i); 2548a218651SEdgar E. Iglesias DeviceState *dev; 2558a218651SEdgar E. Iglesias MemoryRegion *mr; 2568a218651SEdgar E. Iglesias 2570074fce6SMarkus Armbruster object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i], 258f4e3fa37SEdgar E. Iglesias TYPE_XLNX_ZDMA); 259f4e3fa37SEdgar E. Iglesias dev = DEVICE(&s->lpd.iou.adma[i]); 2605325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort); 261783dbab1SPhilippe Mathieu-Daudé object_property_set_link(OBJECT(dev), "dma", 262783dbab1SPhilippe Mathieu-Daudé OBJECT(get_system_memory()), &error_fatal); 2630074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); 2648a218651SEdgar E. Iglesias 265f4e3fa37SEdgar E. Iglesias mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); 2668a218651SEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, 2678a218651SEdgar E. Iglesias MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr); 2688a218651SEdgar E. Iglesias 269f4e3fa37SEdgar E. Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]); 2708a218651SEdgar E. Iglesias g_free(name); 2718a218651SEdgar E. Iglesias } 2728a218651SEdgar E. Iglesias } 2738a218651SEdgar E. Iglesias 274724c6e12SEdgar E. Iglesias #define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */ 275724c6e12SEdgar E. Iglesias static void versal_create_sds(Versal *s, qemu_irq *pic) 276724c6e12SEdgar E. Iglesias { 277724c6e12SEdgar E. Iglesias int i; 278724c6e12SEdgar E. Iglesias 279724c6e12SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) { 280724c6e12SEdgar E. Iglesias DeviceState *dev; 281724c6e12SEdgar E. Iglesias MemoryRegion *mr; 282724c6e12SEdgar E. Iglesias 2830074fce6SMarkus Armbruster object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i], 284724c6e12SEdgar E. Iglesias TYPE_SYSBUS_SDHCI); 285724c6e12SEdgar E. Iglesias dev = DEVICE(&s->pmc.iou.sd[i]); 286724c6e12SEdgar E. Iglesias 2875325cc34SMarkus Armbruster object_property_set_uint(OBJECT(dev), "sd-spec-version", 3, 288724c6e12SEdgar E. Iglesias &error_fatal); 2895325cc34SMarkus Armbruster object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES, 2905325cc34SMarkus Armbruster &error_fatal); 2915325cc34SMarkus Armbruster object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal); 2920074fce6SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); 293724c6e12SEdgar E. Iglesias 294724c6e12SEdgar E. Iglesias mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); 295724c6e12SEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, 296724c6e12SEdgar E. Iglesias MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr); 297724c6e12SEdgar E. Iglesias 298724c6e12SEdgar E. Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, 299724c6e12SEdgar E. Iglesias pic[VERSAL_SD0_IRQ_0 + i * 2]); 300724c6e12SEdgar E. Iglesias } 301724c6e12SEdgar E. Iglesias } 302724c6e12SEdgar E. Iglesias 3039a6d4918SFrancisco Iglesias static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic) 3049a6d4918SFrancisco Iglesias { 3059a6d4918SFrancisco Iglesias DeviceState *orgate; 3069a6d4918SFrancisco Iglesias 3079a6d4918SFrancisco Iglesias /* 3089a6d4918SFrancisco Iglesias * The VERSAL_PMC_APB_IRQ is an 'or' of the interrupts from the following 3099a6d4918SFrancisco Iglesias * models: 3109a6d4918SFrancisco Iglesias * - RTC 3119a6d4918SFrancisco Iglesias * - BBRAM 312f7c9aecbSFrancisco Iglesias * - PMC SLCR 3139a6d4918SFrancisco Iglesias */ 3149a6d4918SFrancisco Iglesias object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate", 3159a6d4918SFrancisco Iglesias &s->pmc.apb_irq_orgate, TYPE_OR_IRQ); 3169a6d4918SFrancisco Iglesias orgate = DEVICE(&s->pmc.apb_irq_orgate); 3179a6d4918SFrancisco Iglesias object_property_set_int(OBJECT(orgate), 3189a6d4918SFrancisco Iglesias "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal); 3199a6d4918SFrancisco Iglesias qdev_realize(orgate, NULL, &error_fatal); 3209a6d4918SFrancisco Iglesias qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]); 3219a6d4918SFrancisco Iglesias } 3229a6d4918SFrancisco Iglesias 323eb1221c5SEdgar E. Iglesias static void versal_create_rtc(Versal *s, qemu_irq *pic) 324eb1221c5SEdgar E. Iglesias { 325eb1221c5SEdgar E. Iglesias SysBusDevice *sbd; 326eb1221c5SEdgar E. Iglesias MemoryRegion *mr; 327eb1221c5SEdgar E. Iglesias 3285a147c8cSMarkus Armbruster object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc, 329eb1221c5SEdgar E. Iglesias TYPE_XLNX_ZYNQMP_RTC); 330eb1221c5SEdgar E. Iglesias sbd = SYS_BUS_DEVICE(&s->pmc.rtc); 3315a147c8cSMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(sbd), &error_fatal); 332eb1221c5SEdgar E. Iglesias 333eb1221c5SEdgar E. Iglesias mr = sysbus_mmio_get_region(sbd, 0); 334eb1221c5SEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr); 335eb1221c5SEdgar E. Iglesias 336eb1221c5SEdgar E. Iglesias /* 337eb1221c5SEdgar E. Iglesias * TODO: Connect the ALARM and SECONDS interrupts once our RTC model 338eb1221c5SEdgar E. Iglesias * supports them. 339eb1221c5SEdgar E. Iglesias */ 3409a6d4918SFrancisco Iglesias sysbus_connect_irq(sbd, 1, 3419a6d4918SFrancisco Iglesias qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0)); 342eb1221c5SEdgar E. Iglesias } 343eb1221c5SEdgar E. Iglesias 344a55b441bSEdgar E. Iglesias static void versal_create_xrams(Versal *s, qemu_irq *pic) 345a55b441bSEdgar E. Iglesias { 346a55b441bSEdgar E. Iglesias int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl); 347a55b441bSEdgar E. Iglesias DeviceState *orgate; 348a55b441bSEdgar E. Iglesias int i; 349a55b441bSEdgar E. Iglesias 350a55b441bSEdgar E. Iglesias /* XRAM IRQs get ORed into a single line. */ 351a55b441bSEdgar E. Iglesias object_initialize_child(OBJECT(s), "xram-irq-orgate", 352a55b441bSEdgar E. Iglesias &s->lpd.xram.irq_orgate, TYPE_OR_IRQ); 353a55b441bSEdgar E. Iglesias orgate = DEVICE(&s->lpd.xram.irq_orgate); 354a55b441bSEdgar E. Iglesias object_property_set_int(OBJECT(orgate), 355a55b441bSEdgar E. Iglesias "num-lines", nr_xrams, &error_fatal); 356a55b441bSEdgar E. Iglesias qdev_realize(orgate, NULL, &error_fatal); 357a55b441bSEdgar E. Iglesias qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]); 358a55b441bSEdgar E. Iglesias 359a55b441bSEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) { 360a55b441bSEdgar E. Iglesias SysBusDevice *sbd; 361a55b441bSEdgar E. Iglesias MemoryRegion *mr; 362a55b441bSEdgar E. Iglesias 363a55b441bSEdgar E. Iglesias object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i], 364a55b441bSEdgar E. Iglesias TYPE_XLNX_XRAM_CTRL); 365a55b441bSEdgar E. Iglesias sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]); 366a55b441bSEdgar E. Iglesias sysbus_realize(sbd, &error_fatal); 367a55b441bSEdgar E. Iglesias 368a55b441bSEdgar E. Iglesias mr = sysbus_mmio_get_region(sbd, 0); 369a55b441bSEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, 370a55b441bSEdgar E. Iglesias MM_XRAMC + i * MM_XRAMC_SIZE, mr); 371a55b441bSEdgar E. Iglesias mr = sysbus_mmio_get_region(sbd, 1); 372a55b441bSEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr); 373a55b441bSEdgar E. Iglesias 374a55b441bSEdgar E. Iglesias sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i)); 375a55b441bSEdgar E. Iglesias } 376a55b441bSEdgar E. Iglesias } 377a55b441bSEdgar E. Iglesias 378393185bcSTong Ho static void versal_create_bbram(Versal *s, qemu_irq *pic) 379393185bcSTong Ho { 380393185bcSTong Ho SysBusDevice *sbd; 381393185bcSTong Ho 382393185bcSTong Ho object_initialize_child_with_props(OBJECT(s), "bbram", &s->pmc.bbram, 383393185bcSTong Ho sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM, 384393185bcSTong Ho &error_fatal, 385393185bcSTong Ho "crc-zpads", "0", 386393185bcSTong Ho NULL); 387393185bcSTong Ho sbd = SYS_BUS_DEVICE(&s->pmc.bbram); 388393185bcSTong Ho 389393185bcSTong Ho sysbus_realize(sbd, &error_fatal); 390393185bcSTong Ho memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL, 391393185bcSTong Ho sysbus_mmio_get_region(sbd, 0)); 3929a6d4918SFrancisco Iglesias sysbus_connect_irq(sbd, 0, 3939a6d4918SFrancisco Iglesias qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1)); 394393185bcSTong Ho } 395393185bcSTong Ho 3965f4910ffSTong Ho static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base) 3975f4910ffSTong Ho { 3985f4910ffSTong Ho SysBusDevice *part = SYS_BUS_DEVICE(dev); 3995f4910ffSTong Ho 4005f4910ffSTong Ho object_property_set_link(OBJECT(part), "efuse", 4015f4910ffSTong Ho OBJECT(&s->pmc.efuse), &error_abort); 4025f4910ffSTong Ho 4035f4910ffSTong Ho sysbus_realize(part, &error_abort); 4045f4910ffSTong Ho memory_region_add_subregion(&s->mr_ps, base, 4055f4910ffSTong Ho sysbus_mmio_get_region(part, 0)); 4065f4910ffSTong Ho } 4075f4910ffSTong Ho 4085f4910ffSTong Ho static void versal_create_efuse(Versal *s, qemu_irq *pic) 4095f4910ffSTong Ho { 4105f4910ffSTong Ho Object *bits = OBJECT(&s->pmc.efuse); 4115f4910ffSTong Ho Object *ctrl = OBJECT(&s->pmc.efuse_ctrl); 4125f4910ffSTong Ho Object *cache = OBJECT(&s->pmc.efuse_cache); 4135f4910ffSTong Ho 4145f4910ffSTong Ho object_initialize_child(OBJECT(s), "efuse-ctrl", &s->pmc.efuse_ctrl, 4155f4910ffSTong Ho TYPE_XLNX_VERSAL_EFUSE_CTRL); 4165f4910ffSTong Ho 4175f4910ffSTong Ho object_initialize_child(OBJECT(s), "efuse-cache", &s->pmc.efuse_cache, 4185f4910ffSTong Ho TYPE_XLNX_VERSAL_EFUSE_CACHE); 4195f4910ffSTong Ho 4205f4910ffSTong Ho object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits, 4215f4910ffSTong Ho sizeof(s->pmc.efuse), 4225f4910ffSTong Ho TYPE_XLNX_EFUSE, &error_abort, 4235f4910ffSTong Ho "efuse-nr", "3", 4245f4910ffSTong Ho "efuse-size", "8192", 4255f4910ffSTong Ho NULL); 4265f4910ffSTong Ho 4275f4910ffSTong Ho qdev_realize(DEVICE(bits), NULL, &error_abort); 4285f4910ffSTong Ho versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL); 4295f4910ffSTong Ho versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE); 4305f4910ffSTong Ho 4315f4910ffSTong Ho sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]); 4325f4910ffSTong Ho } 4335f4910ffSTong Ho 434f7c9aecbSFrancisco Iglesias static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic) 435f7c9aecbSFrancisco Iglesias { 436f7c9aecbSFrancisco Iglesias SysBusDevice *sbd; 437f7c9aecbSFrancisco Iglesias 438f7c9aecbSFrancisco Iglesias object_initialize_child(OBJECT(s), "versal-pmc-iou-slcr", &s->pmc.iou.slcr, 439f7c9aecbSFrancisco Iglesias TYPE_XILINX_VERSAL_PMC_IOU_SLCR); 440f7c9aecbSFrancisco Iglesias 441f7c9aecbSFrancisco Iglesias sbd = SYS_BUS_DEVICE(&s->pmc.iou.slcr); 442f7c9aecbSFrancisco Iglesias sysbus_realize(sbd, &error_fatal); 443f7c9aecbSFrancisco Iglesias 444f7c9aecbSFrancisco Iglesias memory_region_add_subregion(&s->mr_ps, MM_PMC_PMC_IOU_SLCR, 445f7c9aecbSFrancisco Iglesias sysbus_mmio_get_region(sbd, 0)); 446f7c9aecbSFrancisco Iglesias 447f7c9aecbSFrancisco Iglesias sysbus_connect_irq(sbd, 0, 448f7c9aecbSFrancisco Iglesias qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2)); 449f7c9aecbSFrancisco Iglesias } 450f7c9aecbSFrancisco Iglesias 451868d9680SFrancisco Iglesias static void versal_create_ospi(Versal *s, qemu_irq *pic) 452868d9680SFrancisco Iglesias { 453868d9680SFrancisco Iglesias SysBusDevice *sbd; 454868d9680SFrancisco Iglesias MemoryRegion *mr_dac; 455868d9680SFrancisco Iglesias qemu_irq ospi_mux_sel; 456868d9680SFrancisco Iglesias DeviceState *orgate; 457868d9680SFrancisco Iglesias 458868d9680SFrancisco Iglesias memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s), 459868d9680SFrancisco Iglesias "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE); 460868d9680SFrancisco Iglesias 461868d9680SFrancisco Iglesias object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi, 462868d9680SFrancisco Iglesias TYPE_XILINX_VERSAL_OSPI); 463868d9680SFrancisco Iglesias 464868d9680SFrancisco Iglesias mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1); 465868d9680SFrancisco Iglesias memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac); 466868d9680SFrancisco Iglesias 467868d9680SFrancisco Iglesias /* Create the OSPI destination DMA */ 468868d9680SFrancisco Iglesias object_initialize_child(OBJECT(s), "versal-ospi-dma-dst", 469868d9680SFrancisco Iglesias &s->pmc.iou.ospi.dma_dst, 470868d9680SFrancisco Iglesias TYPE_XLNX_CSU_DMA); 471868d9680SFrancisco Iglesias 472868d9680SFrancisco Iglesias object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst), 473868d9680SFrancisco Iglesias "dma", OBJECT(get_system_memory()), 474868d9680SFrancisco Iglesias &error_abort); 475868d9680SFrancisco Iglesias 476868d9680SFrancisco Iglesias sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst); 477868d9680SFrancisco Iglesias sysbus_realize(sbd, &error_fatal); 478868d9680SFrancisco Iglesias 479868d9680SFrancisco Iglesias memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST, 480868d9680SFrancisco Iglesias sysbus_mmio_get_region(sbd, 0)); 481868d9680SFrancisco Iglesias 482868d9680SFrancisco Iglesias /* Create the OSPI source DMA */ 483868d9680SFrancisco Iglesias object_initialize_child(OBJECT(s), "versal-ospi-dma-src", 484868d9680SFrancisco Iglesias &s->pmc.iou.ospi.dma_src, 485868d9680SFrancisco Iglesias TYPE_XLNX_CSU_DMA); 486868d9680SFrancisco Iglesias 487868d9680SFrancisco Iglesias object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst", 488868d9680SFrancisco Iglesias false, &error_abort); 489868d9680SFrancisco Iglesias 490868d9680SFrancisco Iglesias object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src), 491868d9680SFrancisco Iglesias "dma", OBJECT(mr_dac), &error_abort); 492868d9680SFrancisco Iglesias 493868d9680SFrancisco Iglesias object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src), 494868d9680SFrancisco Iglesias "stream-connected-dma", 495868d9680SFrancisco Iglesias OBJECT(&s->pmc.iou.ospi.dma_dst), 496868d9680SFrancisco Iglesias &error_abort); 497868d9680SFrancisco Iglesias 498868d9680SFrancisco Iglesias sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src); 499868d9680SFrancisco Iglesias sysbus_realize(sbd, &error_fatal); 500868d9680SFrancisco Iglesias 501868d9680SFrancisco Iglesias memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC, 502868d9680SFrancisco Iglesias sysbus_mmio_get_region(sbd, 0)); 503868d9680SFrancisco Iglesias 504868d9680SFrancisco Iglesias /* Realize the OSPI */ 505868d9680SFrancisco Iglesias object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src", 506868d9680SFrancisco Iglesias OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort); 507868d9680SFrancisco Iglesias 508868d9680SFrancisco Iglesias sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi); 509868d9680SFrancisco Iglesias sysbus_realize(sbd, &error_fatal); 510868d9680SFrancisco Iglesias 511868d9680SFrancisco Iglesias memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI, 512868d9680SFrancisco Iglesias sysbus_mmio_get_region(sbd, 0)); 513868d9680SFrancisco Iglesias 514868d9680SFrancisco Iglesias memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC, 515868d9680SFrancisco Iglesias &s->pmc.iou.ospi.linear_mr); 516868d9680SFrancisco Iglesias 517868d9680SFrancisco Iglesias /* ospi_mux_sel */ 518868d9680SFrancisco Iglesias ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi), 519868d9680SFrancisco Iglesias "ospi-mux-sel", 0); 520868d9680SFrancisco Iglesias qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0, 521868d9680SFrancisco Iglesias ospi_mux_sel); 522868d9680SFrancisco Iglesias 523868d9680SFrancisco Iglesias /* OSPI irq */ 524868d9680SFrancisco Iglesias object_initialize_child(OBJECT(s), "ospi-irq-orgate", 525868d9680SFrancisco Iglesias &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ); 526868d9680SFrancisco Iglesias object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate), 527868d9680SFrancisco Iglesias "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal); 528868d9680SFrancisco Iglesias 529868d9680SFrancisco Iglesias orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate); 530868d9680SFrancisco Iglesias qdev_realize(orgate, NULL, &error_fatal); 531868d9680SFrancisco Iglesias 532868d9680SFrancisco Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0, 533868d9680SFrancisco Iglesias qdev_get_gpio_in(orgate, 0)); 534868d9680SFrancisco Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0, 535868d9680SFrancisco Iglesias qdev_get_gpio_in(orgate, 1)); 536868d9680SFrancisco Iglesias sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0, 537868d9680SFrancisco Iglesias qdev_get_gpio_in(orgate, 2)); 538868d9680SFrancisco Iglesias 539868d9680SFrancisco Iglesias qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); 540868d9680SFrancisco Iglesias } 541868d9680SFrancisco Iglesias 542b89de436SEdgar E. Iglesias /* This takes the board allocated linear DDR memory and creates aliases 543b89de436SEdgar E. Iglesias * for each split DDR range/aperture on the Versal address map. 544b89de436SEdgar E. Iglesias */ 545b89de436SEdgar E. Iglesias static void versal_map_ddr(Versal *s) 546b89de436SEdgar E. Iglesias { 547b89de436SEdgar E. Iglesias uint64_t size = memory_region_size(s->cfg.mr_ddr); 548b89de436SEdgar E. Iglesias /* Describes the various split DDR access regions. */ 549b89de436SEdgar E. Iglesias static const struct { 550b89de436SEdgar E. Iglesias uint64_t base; 551b89de436SEdgar E. Iglesias uint64_t size; 552b89de436SEdgar E. Iglesias } addr_ranges[] = { 553b89de436SEdgar E. Iglesias { MM_TOP_DDR, MM_TOP_DDR_SIZE }, 554b89de436SEdgar E. Iglesias { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE }, 555b89de436SEdgar E. Iglesias { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE }, 556b89de436SEdgar E. Iglesias { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE } 557b89de436SEdgar E. Iglesias }; 558b89de436SEdgar E. Iglesias uint64_t offset = 0; 559b89de436SEdgar E. Iglesias int i; 560b89de436SEdgar E. Iglesias 561b89de436SEdgar E. Iglesias assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges)); 562b89de436SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) { 563b89de436SEdgar E. Iglesias char *name; 564b89de436SEdgar E. Iglesias uint64_t mapsize; 565b89de436SEdgar E. Iglesias 566b89de436SEdgar E. Iglesias mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size; 567b89de436SEdgar E. Iglesias name = g_strdup_printf("noc-ddr-range%d", i); 568b89de436SEdgar E. Iglesias /* Create the MR alias. */ 569b89de436SEdgar E. Iglesias memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s), 570b89de436SEdgar E. Iglesias name, s->cfg.mr_ddr, 571b89de436SEdgar E. Iglesias offset, mapsize); 572b89de436SEdgar E. Iglesias 573b89de436SEdgar E. Iglesias /* Map it onto the NoC MR. */ 574b89de436SEdgar E. Iglesias memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base, 575b89de436SEdgar E. Iglesias &s->noc.mr_ddr_ranges[i]); 576b89de436SEdgar E. Iglesias offset += mapsize; 577b89de436SEdgar E. Iglesias size -= mapsize; 578b89de436SEdgar E. Iglesias g_free(name); 579b89de436SEdgar E. Iglesias } 580b89de436SEdgar E. Iglesias } 581b89de436SEdgar E. Iglesias 582b89de436SEdgar E. Iglesias static void versal_unimp_area(Versal *s, const char *name, 583b89de436SEdgar E. Iglesias MemoryRegion *mr, 584b89de436SEdgar E. Iglesias hwaddr base, hwaddr size) 585b89de436SEdgar E. Iglesias { 5863e80f690SMarkus Armbruster DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); 587b89de436SEdgar E. Iglesias MemoryRegion *mr_dev; 588b89de436SEdgar E. Iglesias 589b89de436SEdgar E. Iglesias qdev_prop_set_string(dev, "name", name); 590b89de436SEdgar E. Iglesias qdev_prop_set_uint64(dev, "size", size); 591d2623129SMarkus Armbruster object_property_add_child(OBJECT(s), name, OBJECT(dev)); 5923c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 593b89de436SEdgar E. Iglesias 594b89de436SEdgar E. Iglesias mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); 595b89de436SEdgar E. Iglesias memory_region_add_subregion(mr, base, mr_dev); 596b89de436SEdgar E. Iglesias } 597b89de436SEdgar E. Iglesias 598f7c9aecbSFrancisco Iglesias static void versal_unimp_sd_emmc_sel(void *opaque, int n, int level) 599f7c9aecbSFrancisco Iglesias { 600f7c9aecbSFrancisco Iglesias qemu_log_mask(LOG_UNIMP, 601f7c9aecbSFrancisco Iglesias "Selecting between enabling SD mode or eMMC mode on " 602f7c9aecbSFrancisco Iglesias "controller %d is not yet implemented\n", n); 603f7c9aecbSFrancisco Iglesias } 604f7c9aecbSFrancisco Iglesias 605f7c9aecbSFrancisco Iglesias static void versal_unimp_qspi_ospi_mux_sel(void *opaque, int n, int level) 606f7c9aecbSFrancisco Iglesias { 607f7c9aecbSFrancisco Iglesias qemu_log_mask(LOG_UNIMP, 608f7c9aecbSFrancisco Iglesias "Selecting between enabling the QSPI or OSPI linear address " 609f7c9aecbSFrancisco Iglesias "region is not yet implemented\n"); 610f7c9aecbSFrancisco Iglesias } 611f7c9aecbSFrancisco Iglesias 612f7c9aecbSFrancisco Iglesias static void versal_unimp_irq_parity_imr(void *opaque, int n, int level) 613f7c9aecbSFrancisco Iglesias { 614f7c9aecbSFrancisco Iglesias qemu_log_mask(LOG_UNIMP, 615f7c9aecbSFrancisco Iglesias "PMC SLCR parity interrupt behaviour " 616f7c9aecbSFrancisco Iglesias "is not yet implemented\n"); 617f7c9aecbSFrancisco Iglesias } 618f7c9aecbSFrancisco Iglesias 619b89de436SEdgar E. Iglesias static void versal_unimp(Versal *s) 620b89de436SEdgar E. Iglesias { 621f7c9aecbSFrancisco Iglesias qemu_irq gpio_in; 622f7c9aecbSFrancisco Iglesias 623b89de436SEdgar E. Iglesias versal_unimp_area(s, "psm", &s->mr_ps, 624b89de436SEdgar E. Iglesias MM_PSM_START, MM_PSM_END - MM_PSM_START); 625b89de436SEdgar E. Iglesias versal_unimp_area(s, "crl", &s->mr_ps, 626b89de436SEdgar E. Iglesias MM_CRL, MM_CRL_SIZE); 627b89de436SEdgar E. Iglesias versal_unimp_area(s, "crf", &s->mr_ps, 628b89de436SEdgar E. Iglesias MM_FPD_CRF, MM_FPD_CRF_SIZE); 6299a0fcb7fSTong Ho versal_unimp_area(s, "apu", &s->mr_ps, 6309a0fcb7fSTong Ho MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE); 631f0138990SEdgar E. Iglesias versal_unimp_area(s, "crp", &s->mr_ps, 632f0138990SEdgar E. Iglesias MM_PMC_CRP, MM_PMC_CRP_SIZE); 633b89de436SEdgar E. Iglesias versal_unimp_area(s, "iou-scntr", &s->mr_ps, 634b89de436SEdgar E. Iglesias MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE); 635b89de436SEdgar E. Iglesias versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, 636b89de436SEdgar E. Iglesias MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE); 637f7c9aecbSFrancisco Iglesias 638f7c9aecbSFrancisco Iglesias qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel, 639f7c9aecbSFrancisco Iglesias "sd-emmc-sel-dummy", 2); 640f7c9aecbSFrancisco Iglesias qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel, 641f7c9aecbSFrancisco Iglesias "qspi-ospi-mux-sel-dummy", 1); 642f7c9aecbSFrancisco Iglesias qdev_init_gpio_in_named(DEVICE(s), versal_unimp_irq_parity_imr, 643f7c9aecbSFrancisco Iglesias "irq-parity-imr-dummy", 1); 644f7c9aecbSFrancisco Iglesias 645f7c9aecbSFrancisco Iglesias gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 0); 646f7c9aecbSFrancisco Iglesias qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 0, 647f7c9aecbSFrancisco Iglesias gpio_in); 648f7c9aecbSFrancisco Iglesias 649f7c9aecbSFrancisco Iglesias gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 1); 650f7c9aecbSFrancisco Iglesias qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 1, 651f7c9aecbSFrancisco Iglesias gpio_in); 652f7c9aecbSFrancisco Iglesias 653f7c9aecbSFrancisco Iglesias gpio_in = qdev_get_gpio_in_named(DEVICE(s), "qspi-ospi-mux-sel-dummy", 0); 654f7c9aecbSFrancisco Iglesias qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), 655f7c9aecbSFrancisco Iglesias "qspi-ospi-mux-sel", 0, 656f7c9aecbSFrancisco Iglesias gpio_in); 657f7c9aecbSFrancisco Iglesias 658f7c9aecbSFrancisco Iglesias gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0); 659f7c9aecbSFrancisco Iglesias qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), 660f7c9aecbSFrancisco Iglesias SYSBUS_DEVICE_GPIO_IRQ, 0, 661f7c9aecbSFrancisco Iglesias gpio_in); 662b89de436SEdgar E. Iglesias } 663b89de436SEdgar E. Iglesias 664b89de436SEdgar E. Iglesias static void versal_realize(DeviceState *dev, Error **errp) 665b89de436SEdgar E. Iglesias { 666b89de436SEdgar E. Iglesias Versal *s = XLNX_VERSAL(dev); 667b89de436SEdgar E. Iglesias qemu_irq pic[XLNX_VERSAL_NR_IRQS]; 668b89de436SEdgar E. Iglesias 669b89de436SEdgar E. Iglesias versal_create_apu_cpus(s); 670b89de436SEdgar E. Iglesias versal_create_apu_gic(s, pic); 671*67a645a3SEdgar E. Iglesias versal_create_rpu_cpus(s); 672b89de436SEdgar E. Iglesias versal_create_uarts(s, pic); 673144677d4SVikram Garhwal versal_create_usbs(s, pic); 674b89de436SEdgar E. Iglesias versal_create_gems(s, pic); 6758a218651SEdgar E. Iglesias versal_create_admas(s, pic); 676724c6e12SEdgar E. Iglesias versal_create_sds(s, pic); 6779a6d4918SFrancisco Iglesias versal_create_pmc_apb_irq_orgate(s, pic); 678eb1221c5SEdgar E. Iglesias versal_create_rtc(s, pic); 679a55b441bSEdgar E. Iglesias versal_create_xrams(s, pic); 680393185bcSTong Ho versal_create_bbram(s, pic); 6815f4910ffSTong Ho versal_create_efuse(s, pic); 682f7c9aecbSFrancisco Iglesias versal_create_pmc_iou_slcr(s, pic); 683868d9680SFrancisco Iglesias versal_create_ospi(s, pic); 684b89de436SEdgar E. Iglesias versal_map_ddr(s); 685b89de436SEdgar E. Iglesias versal_unimp(s); 686b89de436SEdgar E. Iglesias 687b89de436SEdgar E. Iglesias /* Create the On Chip Memory (OCM). */ 688b89de436SEdgar E. Iglesias memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm", 689b89de436SEdgar E. Iglesias MM_OCM_SIZE, &error_fatal); 690b89de436SEdgar E. Iglesias 691b89de436SEdgar E. Iglesias memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0); 692b89de436SEdgar E. Iglesias memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0); 693*67a645a3SEdgar E. Iglesias memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0, 694*67a645a3SEdgar E. Iglesias &s->lpd.rpu.mr_ps_alias, 0); 695b89de436SEdgar E. Iglesias } 696b89de436SEdgar E. Iglesias 697b89de436SEdgar E. Iglesias static void versal_init(Object *obj) 698b89de436SEdgar E. Iglesias { 699b89de436SEdgar E. Iglesias Versal *s = XLNX_VERSAL(obj); 700b89de436SEdgar E. Iglesias 701b89de436SEdgar E. Iglesias memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX); 702*67a645a3SEdgar E. Iglesias memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX); 703b89de436SEdgar E. Iglesias memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX); 704*67a645a3SEdgar E. Iglesias memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s), 705*67a645a3SEdgar E. Iglesias "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX); 706b89de436SEdgar E. Iglesias } 707b89de436SEdgar E. Iglesias 708b89de436SEdgar E. Iglesias static Property versal_properties[] = { 709b89de436SEdgar E. Iglesias DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION, 710b89de436SEdgar E. Iglesias MemoryRegion *), 711b89de436SEdgar E. Iglesias DEFINE_PROP_END_OF_LIST() 712b89de436SEdgar E. Iglesias }; 713b89de436SEdgar E. Iglesias 714b89de436SEdgar E. Iglesias static void versal_class_init(ObjectClass *klass, void *data) 715b89de436SEdgar E. Iglesias { 716b89de436SEdgar E. Iglesias DeviceClass *dc = DEVICE_CLASS(klass); 717b89de436SEdgar E. Iglesias 718b89de436SEdgar E. Iglesias dc->realize = versal_realize; 7194f67d30bSMarc-André Lureau device_class_set_props(dc, versal_properties); 720b89de436SEdgar E. Iglesias /* No VMSD since we haven't got any top-level SoC state to save. */ 721b89de436SEdgar E. Iglesias } 722b89de436SEdgar E. Iglesias 723b89de436SEdgar E. Iglesias static const TypeInfo versal_info = { 724b89de436SEdgar E. Iglesias .name = TYPE_XLNX_VERSAL, 725b89de436SEdgar E. Iglesias .parent = TYPE_SYS_BUS_DEVICE, 726b89de436SEdgar E. Iglesias .instance_size = sizeof(Versal), 727b89de436SEdgar E. Iglesias .instance_init = versal_init, 728b89de436SEdgar E. Iglesias .class_init = versal_class_init, 729b89de436SEdgar E. Iglesias }; 730b89de436SEdgar E. Iglesias 731b89de436SEdgar E. Iglesias static void versal_register_types(void) 732b89de436SEdgar E. Iglesias { 733b89de436SEdgar E. Iglesias type_register_static(&versal_info); 734b89de436SEdgar E. Iglesias } 735b89de436SEdgar E. Iglesias 736b89de436SEdgar E. Iglesias type_init(versal_register_types); 737