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