diff options
-rw-r--r-- | hw/arm/xlnx-ep108.c | 40 | ||||
-rw-r--r-- | hw/arm/xlnx-zynqmp.c | 37 | ||||
-rw-r--r-- | include/hw/arm/xlnx-zynqmp.h | 12 |
3 files changed, 70 insertions, 19 deletions
diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c index 73e60876e8..9099025a79 100644 --- a/hw/arm/xlnx-ep108.c +++ b/hw/arm/xlnx-ep108.c @@ -25,42 +25,44 @@ typedef struct XlnxEP108 { MemoryRegion ddr_ram; } XlnxEP108; -/* Max 2GB RAM */ -#define EP108_MAX_RAM_SIZE 0x80000000ull - static struct arm_boot_info xlnx_ep108_binfo; static void xlnx_ep108_init(MachineState *machine) { XlnxEP108 *s = g_new0(XlnxEP108, 1); Error *err = NULL; + uint64_t ram_size = machine->ram_size; + + /* Create the memory region to pass to the SoC */ + if (ram_size > XLNX_ZYNQMP_MAX_RAM_SIZE) { + error_report("ERROR: RAM size 0x%" PRIx64 " above max supported of " + "0x%llx", ram_size, + XLNX_ZYNQMP_MAX_RAM_SIZE); + exit(1); + } + + if (ram_size < 0x08000000) { + qemu_log("WARNING: RAM size 0x%" PRIx64 " is small for EP108", + ram_size); + } + + memory_region_allocate_system_memory(&s->ddr_ram, NULL, "ddr-ram", + ram_size); object_initialize(&s->soc, sizeof(s->soc), TYPE_XLNX_ZYNQMP); object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), &error_abort); + object_property_set_link(OBJECT(&s->soc), OBJECT(&s->ddr_ram), + "ddr-ram", &error_abort); + object_property_set_bool(OBJECT(&s->soc), true, "realized", &err); if (err) { error_report_err(err); exit(1); } - if (machine->ram_size > EP108_MAX_RAM_SIZE) { - error_report("WARNING: RAM size " RAM_ADDR_FMT " above max supported, " - "reduced to %llx", machine->ram_size, EP108_MAX_RAM_SIZE); - machine->ram_size = EP108_MAX_RAM_SIZE; - } - - if (machine->ram_size < 0x08000000) { - qemu_log("WARNING: RAM size " RAM_ADDR_FMT " is small for EP108", - machine->ram_size); - } - - memory_region_allocate_system_memory(&s->ddr_ram, NULL, "ddr-ram", - machine->ram_size); - memory_region_add_subregion(get_system_memory(), 0, &s->ddr_ram); - - xlnx_ep108_binfo.ram_size = machine->ram_size; + xlnx_ep108_binfo.ram_size = ram_size; xlnx_ep108_binfo.kernel_filename = machine->kernel_filename; xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline; xlnx_ep108_binfo.initrd_filename = machine->initrd_filename; diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 20a3b2b093..f26efd802a 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -90,6 +90,11 @@ static void xlnx_zynqmp_init(Object *obj) &error_abort); } + object_property_add_link(obj, "ddr-ram", TYPE_MEMORY_REGION, + (Object **)&s->ddr_ram, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); @@ -119,10 +124,42 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) XlnxZynqMPState *s = XLNX_ZYNQMP(dev); MemoryRegion *system_memory = get_system_memory(); uint8_t i; + uint64_t ram_size; const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]"; + ram_addr_t ddr_low_size, ddr_high_size; qemu_irq gic_spi[GIC_NUM_SPI_INTR]; Error *err = NULL; + ram_size = memory_region_size(s->ddr_ram); + + /* Create the DDR Memory Regions. User friendly checks should happen at + * the board level + */ + if (ram_size > XLNX_ZYNQMP_MAX_LOW_RAM_SIZE) { + /* The RAM size is above the maximum available for the low DDR. + * Create the high DDR memory region as well. + */ + assert(ram_size <= XLNX_ZYNQMP_MAX_RAM_SIZE); + ddr_low_size = XLNX_ZYNQMP_MAX_LOW_RAM_SIZE; + ddr_high_size = ram_size - XLNX_ZYNQMP_MAX_LOW_RAM_SIZE; + + memory_region_init_alias(&s->ddr_ram_high, NULL, + "ddr-ram-high", s->ddr_ram, + ddr_low_size, ddr_high_size); + memory_region_add_subregion(get_system_memory(), + XLNX_ZYNQMP_HIGH_RAM_START, + &s->ddr_ram_high); + } else { + /* RAM must be non-zero */ + assert(ram_size); + ddr_low_size = ram_size; + } + + memory_region_init_alias(&s->ddr_ram_low, NULL, + "ddr-ram-low", s->ddr_ram, + 0, ddr_low_size); + memory_region_add_subregion(get_system_memory(), 0, &s->ddr_ram_low); + /* Create the four OCM banks */ for (i = 0; i < XLNX_ZYNQMP_NUM_OCM_BANKS; i++) { char *ocm_name = g_strdup_printf("zynqmp.ocm_ram_bank_%d", i); diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index d1160920cc..1eba937964 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -51,6 +51,14 @@ #define XLNX_ZYNQMP_GIC_REGION_SIZE 0x1000 #define XLNX_ZYNQMP_GIC_ALIASES (0x10000 / XLNX_ZYNQMP_GIC_REGION_SIZE - 1) +#define XLNX_ZYNQMP_MAX_LOW_RAM_SIZE 0x80000000ull + +#define XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE 0x800000000ull +#define XLNX_ZYNQMP_HIGH_RAM_START 0x800000000ull + +#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \ + XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE) + typedef struct XlnxZynqMPState { /*< private >*/ DeviceState parent_obj; @@ -60,8 +68,12 @@ typedef struct XlnxZynqMPState { ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS]; GICState gic; MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES]; + MemoryRegion ocm_ram[XLNX_ZYNQMP_NUM_OCM_BANKS]; + MemoryRegion *ddr_ram; + MemoryRegion ddr_ram_low, ddr_ram_high; + CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; SysbusAHCIState sata; |