aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
authorAlistair Francis <alistair.francis@xilinx.com>2016-01-12 14:39:18 -0800
committerPeter Maydell <peter.maydell@linaro.org>2016-01-15 14:34:54 +0000
commitdc3b89ef87dc0ecd5ba435c155ad8511b848d909 (patch)
tree67515fee1d0385193c4ea4c42fa485b2746b9582 /hw/arm
parentdeb2db996cbb9470b39ae1e383791ef34c4eb3c2 (diff)
xlnx-zynqmp: Add support for high DDR memory regions
The Xilinx ZynqMP SoC and EP108 board supports three memory regions: - A 2GB region starting at 0 - A 32GB region starting at 32GB - A 256GB region starting at 768GB This patch adds support for the first two memory regions, which is automatically created based on the size specified by the QEMU memory command line argument. On hardware the physical memory region is one continuous region, it is then mapped into the three different regions by the DDRC. As we don't model the DDRC this is done at startup by QEMU. The board creates the memory region and then passes that memory region to the SoC. The SoC then maps the memory regions. Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com> Message-id: a1e47db941d65733724a300fcd98b74fbeeaaf22.1452637205.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/xlnx-ep108.c40
-rw-r--r--hw/arm/xlnx-zynqmp.c37
2 files changed, 58 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);