aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/arm/aspeed_ast27x0.c87
-rw-r--r--include/hw/arm/aspeed_soc.h2
2 files changed, 88 insertions, 1 deletions
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 29e7507..b6876b4 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -20,6 +20,7 @@
#include "sysemu/sysemu.h"
#include "hw/intc/arm_gicv3.h"
#include "qapi/qmp/qlist.h"
+#include "qemu/log.h"
static const hwaddr aspeed_soc_ast2700_memmap[] = {
[ASPEED_DEV_SPI_BOOT] = 0x400000000,
@@ -191,6 +192,90 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
return qdev_get_gpio_in(DEVICE(&a->gic), sc->irqmap[dev]);
}
+static uint64_t aspeed_ram_capacity_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: DRAM read out of ram size, addr:0x%" PRIx64 "\n",
+ __func__, addr);
+ return 0;
+}
+
+static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ AspeedSoCState *s = ASPEED_SOC(opaque);
+ ram_addr_t ram_size;
+ MemTxResult result;
+
+ ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size",
+ &error_abort);
+
+ /*
+ * Emulate ddr capacity hardware behavior.
+ * If writes the data to the address which is beyond the ram size,
+ * it would write the data to the "address % ram_size".
+ */
+ result = address_space_write(&s->dram_as, addr % ram_size,
+ MEMTXATTRS_UNSPECIFIED, &data, 4);
+ if (result != MEMTX_OK) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: DRAM write failed, addr:0x%" HWADDR_PRIx
+ ", data :0x%" PRIx64 "\n",
+ __func__, addr % ram_size, data);
+ }
+}
+
+static const MemoryRegionOps aspeed_ram_capacity_ops = {
+ .read = aspeed_ram_capacity_read,
+ .write = aspeed_ram_capacity_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 8,
+ },
+};
+
+/*
+ * SDMC should be realized first to get correct RAM size and max size
+ * values
+ */
+static bool aspeed_soc_ast2700_dram_init(DeviceState *dev, Error **errp)
+{
+ ram_addr_t ram_size, max_ram_size;
+ Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev);
+ AspeedSoCState *s = ASPEED_SOC(dev);
+ AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+
+ ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size",
+ &error_abort);
+ max_ram_size = object_property_get_uint(OBJECT(&s->sdmc), "max-ram-size",
+ &error_abort);
+
+ memory_region_init(&s->dram_container, OBJECT(s), "ram-container",
+ ram_size);
+ memory_region_add_subregion(&s->dram_container, 0, s->dram_mr);
+ address_space_init(&s->dram_as, s->dram_mr, "dram");
+
+ /*
+ * Add a memory region beyond the RAM region to emulate
+ * ddr capacity hardware behavior.
+ */
+ if (ram_size < max_ram_size) {
+ memory_region_init_io(&a->dram_empty, OBJECT(s),
+ &aspeed_ram_capacity_ops, s,
+ "ram-empty", max_ram_size - ram_size);
+
+ memory_region_add_subregion(s->memory,
+ sc->memmap[ASPEED_DEV_SDRAM] + ram_size,
+ &a->dram_empty);
+ }
+
+ memory_region_add_subregion(s->memory,
+ sc->memmap[ASPEED_DEV_SDRAM], &s->dram_container);
+ return true;
+}
+
static void aspeed_soc_ast2700_init(Object *obj)
{
Aspeed27x0SoCState *a = ASPEED27X0_SOC(obj);
@@ -461,7 +546,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sc->memmap[ASPEED_DEV_SDMC]);
/* RAM */
- if (!aspeed_soc_dram_init(s, errp)) {
+ if (!aspeed_soc_ast2700_dram_init(dev, errp)) {
return;
}
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index caef0d1..849ba37 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -59,6 +59,7 @@ struct AspeedSoCState {
MemoryRegion sram;
MemoryRegion spi_boot_container;
MemoryRegion spi_boot;
+ AddressSpace dram_as;
AspeedRtcState rtc;
AspeedTimerCtrlState timerctrl;
AspeedI2CState i2c;
@@ -129,6 +130,7 @@ struct Aspeed27x0SoCState {
ARMCPU cpu[ASPEED_CPUS_NUM];
AspeedINTCState intc;
GICv3State gic;
+ MemoryRegion dram_empty;
};
#define TYPE_ASPEED27X0_SOC "aspeed27x0-soc"