* [PATCH v1 0/9] Add AST2700 support
@ 2024-03-04 9:12 Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 1/9] aspeed/wdt: " Jamin Lin via
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:12 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
Changes from v1:
The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC.
Test steps:
1. Download openbmc image for AST2700 from
https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.00
https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.00/
ast2700-default-obmc.tar.gz
2. untar ast2700-default-obmc.tar.gz
```
tar -xf ast2700-default-obmc.tar.gz
```
3. Run and the contents of scripts as following
IMGDIR=ast2700-default
UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
UBOOT_DTB_ADDR=$((0x400000000 + ${UBOOT_SIZE}))
qemu-system-aarch64 -M ast2700-evb -nographic\
-device loader,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\
-device loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\
-device loader,addr=0x430000000,file=${IMGDIR}/bl31.bin,force-raw=on\
-device loader,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
-device loader,addr=0x430000000,cpu-num=0\
-device loader,addr=0x430000000,cpu-num=1\
-device loader,addr=0x430000000,cpu-num=2\
-device loader,addr=0x430000000,cpu-num=3\
-smp 4\
-drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
-serial mon:stdio\
-snapshot
Known Issue:
1. QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
but not support Shared Peripheral Interrupt (SPI), yet.
Added work around in INTC patch to set GICINT132[18]
which was BMC UART interrupt if it received GICINT132, so users are
able to type any key from keyboard to trigger GICINT132 interrupt
until AST2700 boot into login prompt. It is a temporary solution.
If users encounter boot stck and no booting log,
please type any key from keyboard.
Jamin Lin (9):
aspeed/wdt: Add AST2700 support
aspeed/sli: Add AST2700 support
aspeed/sdmc: Add AST2700 support
aspeed/smc: Add AST2700 support
aspeed/scu: Add AST2700 support
aspeed/intc: Add AST2700 support
aspeed/soc: Add AST2700 support
aspeed: Add an AST2700 eval board
aspeed/soc: fix incorrect dram size for AST2700
hw/arm/aspeed.c | 32 ++
hw/arm/aspeed_ast27x0.c | 554 +++++++++++++++++++++++++++++++
hw/arm/meson.build | 1 +
hw/intc/aspeed_intc.c | 135 ++++++++
hw/intc/meson.build | 1 +
hw/misc/aspeed_scu.c | 306 ++++++++++++++++-
hw/misc/aspeed_sdmc.c | 215 ++++++++++--
hw/misc/aspeed_sli.c | 179 ++++++++++
hw/misc/meson.build | 3 +-
hw/misc/trace-events | 11 +
hw/ssi/aspeed_smc.c | 326 ++++++++++++++++--
hw/ssi/trace-events | 2 +-
hw/watchdog/wdt_aspeed.c | 24 ++
include/hw/arm/aspeed_soc.h | 27 +-
include/hw/intc/aspeed_vic.h | 29 ++
include/hw/misc/aspeed_scu.h | 47 ++-
include/hw/misc/aspeed_sdmc.h | 4 +-
include/hw/misc/aspeed_sli.h | 32 ++
include/hw/ssi/aspeed_smc.h | 1 +
include/hw/watchdog/wdt_aspeed.h | 3 +-
20 files changed, 1880 insertions(+), 52 deletions(-)
create mode 100644 hw/arm/aspeed_ast27x0.c
create mode 100644 hw/intc/aspeed_intc.c
create mode 100644 hw/misc/aspeed_sli.c
create mode 100644 include/hw/misc/aspeed_sli.h
--
2.25.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v1 1/9] aspeed/wdt: Add AST2700 support
2024-03-04 9:12 [PATCH v1 0/9] Add AST2700 support Jamin Lin via
@ 2024-03-04 9:12 ` Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 2/9] aspeed/sli: " Jamin Lin via
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:12 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 wdt controller is similiar to AST2600's wdt, but
the AST2700 has 8 watchdogs, and they each have a 0x80 of registers.
Introduce ast2700 object class and increse the number of regs(offset) of
ast2700 model.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/watchdog/wdt_aspeed.c | 24 ++++++++++++++++++++++++
include/hw/watchdog/wdt_aspeed.h | 3 ++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index d70b656f8e..75685c5647 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -422,12 +422,36 @@ static const TypeInfo aspeed_1030_wdt_info = {
.class_init = aspeed_1030_wdt_class_init,
};
+static void aspeed_2700_wdt_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 Watchdog Controller";
+ awc->iosize = 0x80;
+ awc->ext_pulse_width_mask = 0xfffff; /* TODO */
+ awc->reset_ctrl_reg = AST2600_SCU_RESET_CONTROL1;
+ awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
+ awc->wdt_reload = aspeed_wdt_reload_1mhz;
+ awc->sanitize_ctrl = aspeed_2600_sanitize_ctrl;
+ awc->default_status = 0x014FB180;
+ awc->default_reload_value = 0x014FB180;
+}
+
+static const TypeInfo aspeed_2700_wdt_info = {
+ .name = TYPE_ASPEED_2700_WDT,
+ .parent = TYPE_ASPEED_WDT,
+ .instance_size = sizeof(AspeedWDTState),
+ .class_init = aspeed_2700_wdt_class_init,
+};
+
static void wdt_aspeed_register_types(void)
{
type_register_static(&aspeed_wdt_info);
type_register_static(&aspeed_2400_wdt_info);
type_register_static(&aspeed_2500_wdt_info);
type_register_static(&aspeed_2600_wdt_info);
+ type_register_static(&aspeed_2700_wdt_info);
type_register_static(&aspeed_1030_wdt_info);
}
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
index e90ef86651..830b0a7936 100644
--- a/include/hw/watchdog/wdt_aspeed.h
+++ b/include/hw/watchdog/wdt_aspeed.h
@@ -19,9 +19,10 @@ OBJECT_DECLARE_TYPE(AspeedWDTState, AspeedWDTClass, ASPEED_WDT)
#define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
#define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
#define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600"
+#define TYPE_ASPEED_2700_WDT TYPE_ASPEED_WDT "-ast2700"
#define TYPE_ASPEED_1030_WDT TYPE_ASPEED_WDT "-ast1030"
-#define ASPEED_WDT_REGS_MAX (0x30 / 4)
+#define ASPEED_WDT_REGS_MAX (0x80 / 4)
struct AspeedWDTState {
/*< private >*/
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v1 2/9] aspeed/sli: Add AST2700 support
2024-03-04 9:12 [PATCH v1 0/9] Add AST2700 support Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 1/9] aspeed/wdt: " Jamin Lin via
@ 2024-03-04 9:12 ` Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 3/9] aspeed/sdmc: " Jamin Lin via
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:12 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 SLI engine is designed to accelerate the
throughput between cross-die connections.
It have CPU_SLI at CPU die and IO_SLI at IO die.
Introduce new ast2700_sli and ast2700_sliio class
with instance_init and realize handlers.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/misc/aspeed_sli.c | 179 +++++++++++++++++++++++++++++++++++
hw/misc/meson.build | 3 +-
hw/misc/trace-events | 7 ++
include/hw/misc/aspeed_sli.h | 32 +++++++
4 files changed, 220 insertions(+), 1 deletion(-)
create mode 100644 hw/misc/aspeed_sli.c
create mode 100644 include/hw/misc/aspeed_sli.h
diff --git a/hw/misc/aspeed_sli.c b/hw/misc/aspeed_sli.c
new file mode 100644
index 0000000000..4af42f145c
--- /dev/null
+++ b/hw/misc/aspeed_sli.c
@@ -0,0 +1,179 @@
+/*
+ * ASPEED SLI Controller
+ *
+ * Copyright (C) 2024 ASPEED Technology Inc.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/aspeed_sli.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+#define SLI_REGION_SIZE 0x500
+#define TO_REG(addr) ((addr) >> 2)
+
+static uint64_t aspeed_sli_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ AspeedSLIState *s = ASPEED_SLI(opaque);
+ int reg = TO_REG(addr);
+
+ if (reg >= ARRAY_SIZE(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return 0;
+ }
+
+ trace_aspeed_sli_read(addr, size, s->regs[reg]);
+ return s->regs[reg];
+}
+
+static void aspeed_sli_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ AspeedSLIState *s = ASPEED_SLI(opaque);
+ int reg = TO_REG(addr);
+
+ if (reg >= ARRAY_SIZE(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return;
+ }
+
+ trace_aspeed_sli_write(addr, size, data);
+ s->regs[reg] = data;
+}
+
+static uint64_t aspeed_sliio_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ AspeedSLIState *s = ASPEED_SLI(opaque);
+ int reg = TO_REG(addr);
+
+ if (reg >= ARRAY_SIZE(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return 0;
+ }
+
+ trace_aspeed_sliio_read(addr, size, s->regs[reg]);
+ return s->regs[reg];
+}
+
+static void aspeed_sliio_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ AspeedSLIState *s = ASPEED_SLI(opaque);
+ int reg = TO_REG(addr);
+
+ if (reg >= ARRAY_SIZE(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return;
+ }
+
+ trace_aspeed_sliio_write(addr, size, data);
+ s->regs[reg] = data;
+}
+
+static const MemoryRegionOps aspeed_sli_ops = {
+ .read = aspeed_sli_read,
+ .write = aspeed_sli_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
+};
+
+static const MemoryRegionOps aspeed_sliio_ops = {
+ .read = aspeed_sliio_read,
+ .write = aspeed_sliio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
+};
+
+static void aspeed_sli_realize(DeviceState *dev, Error **errp)
+{
+ AspeedSLIState *s = ASPEED_SLI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sli_ops, s,
+ TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+ sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void aspeed_sliio_realize(DeviceState *dev, Error **errp)
+{
+ AspeedSLIState *s = ASPEED_SLI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sliio_ops, s,
+ TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+ sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void aspeed_sli_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "Aspeed SLI Controller";
+ dc->realize = aspeed_sli_realize;
+}
+
+static const TypeInfo aspeed_sli_info = {
+ .name = TYPE_ASPEED_SLI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AspeedSLIState),
+ .class_init = aspeed_sli_class_init,
+ .class_size = sizeof(AspeedSLIClass),
+ .abstract = true,
+};
+
+static void aspeed_2700_sli_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "AST2700 SLI Controller";
+}
+
+static void aspeed_2700_sliio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "AST2700 I/O SLI Controller";
+ dc->realize = aspeed_sliio_realize;
+}
+
+static const TypeInfo aspeed_2700_sli_info = {
+ .name = TYPE_ASPEED_2700_SLI,
+ .parent = TYPE_ASPEED_SLI,
+ .class_init = aspeed_2700_sli_class_init,
+};
+
+static const TypeInfo aspeed_2700_sliio_info = {
+ .name = TYPE_ASPEED_2700_SLIIO,
+ .parent = TYPE_ASPEED_SLI,
+ .class_init = aspeed_2700_sliio_class_init,
+};
+
+static void aspeed_sli_register_types(void)
+{
+ type_register_static(&aspeed_sli_info);
+ type_register_static(&aspeed_2700_sli_info);
+ type_register_static(&aspeed_2700_sliio_info);
+}
+
+type_init(aspeed_sli_register_types);
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 746686835b..790f05525a 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -137,7 +137,8 @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_sbc.c',
'aspeed_sdmc.c',
'aspeed_xdma.c',
- 'aspeed_peci.c'))
+ 'aspeed_peci.c',
+ 'aspeed_sli.c'))
system_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
system_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 5f5bc92222..07010a7ea6 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -341,3 +341,10 @@ djmemc_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRI
# iosb.c
iosb_read(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
iosb_write(int reg, uint64_t value, unsigned int size) "reg=0x%x value=0x%"PRIx64" size=%u"
+
+# aspeed_sli.c
+aspeed_sli_write(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_sli_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_sliio_write(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+aspeed_sliio_read(uint64_t offset, unsigned int size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
+
diff --git a/include/hw/misc/aspeed_sli.h b/include/hw/misc/aspeed_sli.h
new file mode 100644
index 0000000000..15892950e2
--- /dev/null
+++ b/include/hw/misc/aspeed_sli.h
@@ -0,0 +1,32 @@
+/*
+ * ASPEED SLI Controller
+ *
+ * Copyright (C) 2024 ASPEED Technology Inc.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef ASPEED_SLI_H
+#define ASPEED_SLI_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_SLI "aspeed.sli"
+#define TYPE_ASPEED_2700_SLI TYPE_ASPEED_SLI "-ast2700"
+#define TYPE_ASPEED_2700_SLIIO TYPE_ASPEED_SLI "io" "-ast2700"
+OBJECT_DECLARE_TYPE(AspeedSLIState, AspeedSLIClass, ASPEED_SLI)
+
+#define ASPEED_SLI_NR_REGS (0x500 >> 2)
+
+struct AspeedSLIState {
+ SysBusDevice parent;
+ MemoryRegion iomem;
+
+ uint32_t regs[ASPEED_SLI_NR_REGS];
+};
+
+struct AspeedSLIClass {
+ SysBusDeviceClass parent_class;
+};
+
+#endif /* ASPEED_SLI_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v1 3/9] aspeed/sdmc: Add AST2700 support
2024-03-04 9:12 [PATCH v1 0/9] Add AST2700 support Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 1/9] aspeed/wdt: " Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 2/9] aspeed/sli: " Jamin Lin via
@ 2024-03-04 9:12 ` Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 6/9] aspeed/intc: " Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 9/9] aspeed/soc: fix incorrect dram size for AST2700 Jamin Lin via
4 siblings, 0 replies; 6+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:12 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
The SDRAM memory controller(DRAMC) controls the access to external
DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
The DRAM memory controller of AST2700 is not backward compatible
to previous chips such AST2600, AST2500 and AST2400.
Max memory is now 8GiB on the AST2700. Introduce new
aspeed_2700_sdmc and class with read/write operation and
reset handlers.
Define DRAMC necessary protected registers and
unprotected registers for AST2700 and increase
the register set to 0x1000.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/misc/aspeed_sdmc.c | 215 ++++++++++++++++++++++++++++++----
include/hw/misc/aspeed_sdmc.h | 4 +-
2 files changed, 198 insertions(+), 21 deletions(-)
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 64cd1a81dc..63fb7936c4 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -27,6 +27,7 @@
#define PROT_SOFTLOCKED 0x00
#define PROT_KEY_UNLOCK 0xFC600309
+#define PROT_2700_KEY_UNLOCK 0x1688A8A8
#define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */
/* Configuration Register */
@@ -54,6 +55,46 @@
#define R_DRAM_TIME (0x8c / 4)
#define R_ECC_ERR_INJECT (0xb4 / 4)
+/* AST2700 Register */
+#define R_2700_PROT (0x00 / 4)
+#define R_INT_STATUS (0x04 / 4)
+#define R_INT_CLEAR (0x08 / 4)
+#define R_INT_MASK (0x0c / 4)
+#define R_MAIN_CONF (0x10 / 4)
+#define R_MAIN_CONTROL (0x14 / 4)
+#define R_MAIN_STATUS (0x18 / 4)
+#define R_ERR_STATUS (0x1c / 4)
+#define R_ECC_FAIL_STATUS (0x78 / 4)
+#define R_ECC_FAIL_ADDR (0x7c / 4)
+#define R_ECC_TESTING_CONTROL (0x80 / 4)
+#define R_PROT_REGION_LOCK_STATUS (0x94 / 4)
+#define R_TEST_FAIL_ADDR (0xd4 / 4)
+#define R_TEST_FAIL_D0 (0xd8 / 4)
+#define R_TEST_FAIL_D1 (0xdc / 4)
+#define R_TEST_FAIL_D2 (0xe0 / 4)
+#define R_TEST_FAIL_D3 (0xe4 / 4)
+#define R_DBG_STATUS (0xf4 / 4)
+#define R_PHY_INTERFACE_STATUS (0xf8 / 4)
+#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4)
+#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4)
+#define R_PORT0_INTERFACE_MONITOR1 (0x244 / 4)
+#define R_PORT0_INTERFACE_MONITOR2 (0x248 / 4)
+#define R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4)
+#define R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4)
+#define R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4)
+#define R_PORT2_INTERFACE_MONITOR0 (0x340 / 4)
+#define R_PORT2_INTERFACE_MONITOR1 (0x344 / 4)
+#define R_PORT2_INTERFACE_MONITOR2 (0x348 / 4)
+#define R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4)
+#define R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4)
+#define R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4)
+#define R_PORT4_INTERFACE_MONITOR0 (0x440 / 4)
+#define R_PORT4_INTERFACE_MONITOR1 (0x444 / 4)
+#define R_PORT4_INTERFACE_MONITOR2 (0x448 / 4)
+#define R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4)
+#define R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4)
+#define R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4)
+
/*
* Configuration register Ox4 (for Aspeed AST2400 SOC)
*
@@ -76,10 +117,6 @@
#define ASPEED_SDMC_VGA_32MB 0x2
#define ASPEED_SDMC_VGA_64MB 0x3
#define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
-#define ASPEED_SDMC_DRAM_64MB 0x0
-#define ASPEED_SDMC_DRAM_128MB 0x1
-#define ASPEED_SDMC_DRAM_256MB 0x2
-#define ASPEED_SDMC_DRAM_512MB 0x3
#define ASPEED_SDMC_READONLY_MASK \
(ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
@@ -100,22 +137,24 @@
#define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs from AST2400 */
#define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs from AST2400 */
-/* DRAM size definitions differs */
-#define ASPEED_SDMC_AST2500_128MB 0x0
-#define ASPEED_SDMC_AST2500_256MB 0x1
-#define ASPEED_SDMC_AST2500_512MB 0x2
-#define ASPEED_SDMC_AST2500_1024MB 0x3
-
-#define ASPEED_SDMC_AST2600_256MB 0x0
-#define ASPEED_SDMC_AST2600_512MB 0x1
-#define ASPEED_SDMC_AST2600_1024MB 0x2
-#define ASPEED_SDMC_AST2600_2048MB 0x3
-
#define ASPEED_SDMC_AST2500_READONLY_MASK \
(ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \
ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
+/*
+ * Main Configuration register Ox10 (for Aspeed AST2700 SOC and higher)
+ *
+ */
+#define ASPEED_SDMC_AST2700_RESERVED 0xFFFF2082 /* 31:16, 13, 7, 1 */
+#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8)
+#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6)
+#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE (1 << 5)
+#define ASPEED_SDMC_AST2700_DRAM_SIZE(x) ((x & 0x7) << 2)
+
+#define ASPEED_SDMC_AST2700_READONLY_MASK \
+ (ASPEED_SDMC_AST2700_RESERVED)
+
static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
{
AspeedSDMCState *s = ASPEED_SDMC(opaque);
@@ -231,7 +270,10 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
AspeedSDMCState *s = ASPEED_SDMC(dev);
AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
- assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
+ if (!asc->is_bus64bit) {
+ assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
+ }
+
s->max_ram_size = asc->max_ram_size;
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
@@ -311,7 +353,8 @@ static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data)
{
if (reg == R_PROT) {
- s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
+ s->regs[reg] =
+ (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
return;
}
@@ -369,7 +412,8 @@ static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data)
{
if (reg == R_PROT) {
- s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
+ s->regs[reg] =
+ (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED : PROT_SOFTLOCKED;
return;
}
@@ -449,8 +493,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
}
if (s->regs[R_PROT] == PROT_HARDLOCKED) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n",
- __func__);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked until system reset!\n",
+ __func__);
return;
}
@@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info = {
.class_init = aspeed_2600_sdmc_class_init,
};
+static void aspeed_2700_sdmc_reset(DeviceState *dev)
+{
+ AspeedSDMCState *s = ASPEED_SDMC(dev);
+ AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ /* Set ram size bit and defaults values */
+ s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
+ s->regs[R_2700_PROT] = PROT_UNLOCKED;
+}
+
+static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
+{
+ uint32_t fixed_conf = ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
+ ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
+
+ /* Make sure readonly bits are kept */
+ data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
+
+ return data | fixed_conf;
+}
+
+static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
+ uint32_t data)
+{
+ /* Unprotected registers */
+ switch (reg) {
+ case R_INT_STATUS:
+ case R_INT_CLEAR:
+ case R_INT_MASK:
+ case R_MAIN_STATUS:
+ case R_ERR_STATUS:
+ case R_ECC_FAIL_STATUS:
+ case R_ECC_FAIL_ADDR:
+ case R_PROT_REGION_LOCK_STATUS:
+ case R_TEST_FAIL_ADDR:
+ case R_TEST_FAIL_D0:
+ case R_TEST_FAIL_D1:
+ case R_TEST_FAIL_D2:
+ case R_TEST_FAIL_D3:
+ case R_DBG_STATUS:
+ case R_PHY_INTERFACE_STATUS:
+ case R_GRAPHIC_MEM_BASE_ADDR:
+ case R_PORT0_INTERFACE_MONITOR0:
+ case R_PORT0_INTERFACE_MONITOR1:
+ case R_PORT0_INTERFACE_MONITOR2:
+ case R_PORT1_INTERFACE_MONITOR0:
+ case R_PORT1_INTERFACE_MONITOR1:
+ case R_PORT1_INTERFACE_MONITOR2:
+ case R_PORT2_INTERFACE_MONITOR0:
+ case R_PORT2_INTERFACE_MONITOR1:
+ case R_PORT2_INTERFACE_MONITOR2:
+ case R_PORT3_INTERFACE_MONITOR0:
+ case R_PORT3_INTERFACE_MONITOR1:
+ case R_PORT3_INTERFACE_MONITOR2:
+ case R_PORT4_INTERFACE_MONITOR0:
+ case R_PORT4_INTERFACE_MONITOR1:
+ case R_PORT4_INTERFACE_MONITOR2:
+ case R_PORT5_INTERFACE_MONITOR0:
+ case R_PORT5_INTERFACE_MONITOR1:
+ case R_PORT5_INTERFACE_MONITOR2:
+ s->regs[reg] = data;
+ return;
+ }
+
+ if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked until system reset!\n",
+ __func__);
+ return;
+ }
+
+ if (reg != R_2700_PROT && s->regs[R_2700_PROT] == PROT_SOFTLOCKED) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked! (write to MCR%02x blocked)\n",
+ __func__, reg * 4);
+ return;
+ }
+
+ switch (reg) {
+ case R_2700_PROT:
+ if (data == PROT_2700_KEY_UNLOCK) {
+ data = PROT_UNLOCKED;
+ } else if (data == PROT_KEY_HARDLOCK) {
+ data = PROT_HARDLOCKED;
+ } else {
+ data = PROT_SOFTLOCKED;
+ }
+ break;
+ case R_MAIN_CONF:
+ data = aspeed_2700_sdmc_compute_conf(s, data);
+ break;
+ case R_MAIN_STATUS:
+ /* Will never return 'busy'. */
+ data &= ~PHY_BUSY_STATE;
+ break;
+ default:
+ break;
+ }
+
+ s->regs[reg] = data;
+}
+
+static const uint64_t
+ aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
+ 2048 * MiB, 4096 * MiB, 8192 * MiB, 0};
+
+static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 SDRAM Memory Controller";
+ dc->reset = aspeed_2700_sdmc_reset;
+
+ asc->is_bus64bit = true;
+ asc->max_ram_size = 8 * GiB;
+ asc->compute_conf = aspeed_2700_sdmc_compute_conf;
+ asc->write = aspeed_2700_sdmc_write;
+ asc->valid_ram_sizes = aspeed_2700_ram_sizes;
+}
+
+static const TypeInfo aspeed_2700_sdmc_info = {
+ .name = TYPE_ASPEED_2700_SDMC,
+ .parent = TYPE_ASPEED_SDMC,
+ .class_init = aspeed_2700_sdmc_class_init,
+};
+
static void aspeed_sdmc_register_types(void)
{
type_register_static(&aspeed_sdmc_info);
type_register_static(&aspeed_2400_sdmc_info);
type_register_static(&aspeed_2500_sdmc_info);
type_register_static(&aspeed_2600_sdmc_info);
+ type_register_static(&aspeed_2700_sdmc_info);
}
type_init(aspeed_sdmc_register_types);
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index ec2d59a14f..6df2f0a3b7 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
#define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
#define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
#define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
+#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
/*
* SDMC has 174 documented registers. In addition the u-boot device tree
@@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
* time, and the other is in the DDR-PHY IP which is used during DDR-PHY
* training.
*/
-#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
+#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
struct AspeedSDMCState {
/*< private >*/
@@ -51,6 +52,7 @@ struct AspeedSDMCClass {
const uint64_t *valid_ram_sizes;
uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
+ bool is_bus64bit;
};
#endif /* ASPEED_SDMC_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v1 6/9] aspeed/intc: Add AST2700 support
2024-03-04 9:12 [PATCH v1 0/9] Add AST2700 support Jamin Lin via
` (2 preceding siblings ...)
2024-03-04 9:12 ` [PATCH v1 3/9] aspeed/sdmc: " Jamin Lin via
@ 2024-03-04 9:12 ` Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 9/9] aspeed/soc: fix incorrect dram size for AST2700 Jamin Lin via
4 siblings, 0 replies; 6+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:12 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 interrupt controller(INTC) provides hardware interrupt interfaces
to interrupt of processors PSP, SSP and TSP. In INTC, each interrupt of
INT 128 to INT136 combines 32 interrupts.
Introduce a new aspeed_intc class with instance_init and realize handlers.
QEMU supports ARM Generic Interrupt Controller, version 3(GICv3)
but not support Shared Peripheral Interrupt (SPI), yet.
This patch added work around to set GICINT132[18] which was BMC UART interrupt
if it received GICINT132, so users are able to type any key from keyboard to
trigger GICINT132 interrupt until AST2700 boot into login prompt.
It is a temporary solution.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/intc/aspeed_intc.c | 135 +++++++++++++++++++++++++++++++++++
hw/intc/meson.build | 1 +
include/hw/intc/aspeed_vic.h | 29 ++++++++
3 files changed, 165 insertions(+)
create mode 100644 hw/intc/aspeed_intc.c
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
new file mode 100644
index 0000000000..851d43363b
--- /dev/null
+++ b/hw/intc/aspeed_intc.c
@@ -0,0 +1,135 @@
+/*
+ * ASPEED INTC Controller
+ *
+ * Copyright (C) 2024 ASPEED Technology Inc.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/intc/aspeed_vic.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/intc/arm_gicv3.h"
+#include "trace.h"
+
+#define ASPEED_INTC_NR_IRQS 128
+#define ASPEED_INTC_SIZE 0x4000
+#define TO_REG(N) (N >> 2)
+
+uint64_t regs[ASPEED_INTC_SIZE];
+
+static void aspeed_intc_set_irq(void *opaque, int irq, int level)
+{
+}
+
+static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned size)
+{
+ AspeedINTCState *s = ASPEED_INTC(opaque);
+ GICv3State *gic = ARM_GICV3(s->gic);
+
+ uint64_t value = 0;
+ switch (TO_REG(offset)) {
+ case TO_REG(0x1404):
+ /* BMC UART interript is GICINT132[18] */
+ if (gic && gicv3_gicd_level_test(gic, 164)) {
+ value = BIT(18);
+ }
+ break;
+ default:
+ value = regs[TO_REG(offset)];
+ break;
+ }
+
+ return value;
+}
+
+static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
+ unsigned size)
+{
+ AspeedINTCState *s = ASPEED_INTC(opaque);
+ GICv3State *gic = ARM_GICV3(s->gic);
+
+ switch (TO_REG(offset)) {
+ case TO_REG(0x1400):
+ regs[TO_REG(offset)] = data;
+ if (regs[TO_REG(offset)]) {
+ gicv3_gicd_enabled_set(gic, 164);
+ } else {
+ gicv3_gicd_enabled_clear(gic, 164);
+ }
+ break;
+ case TO_REG(0x1404):
+ regs[TO_REG(offset)] &= ~(data);
+ gicv3_gicd_level_clear(gic, 164);
+ break;
+ default:
+ regs[TO_REG(offset)] = data;
+ break;
+ }
+}
+
+static const MemoryRegionOps aspeed_intc_ops = {
+ .read = aspeed_intc_read,
+ .write = aspeed_intc_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .valid.unaligned = false,
+};
+
+static void aspeed_intc_realize(DeviceState *dev, Error **errp)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ AspeedINTCState *s = ASPEED_INTC(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
+ TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->fiq);
+}
+
+static void aspeed_intc_reset(DeviceState *dev)
+{
+ AspeedINTCState *s = ASPEED_INTC(dev);
+
+ s->level = 0;
+ s->raw = 0;
+ s->select = 0;
+ s->enable = 0;
+ s->trigger = 0;
+ s->sense = 0x1F07FFF8FFFFULL;
+ s->dual_edge = 0xF800070000ULL;
+ s->event = 0x5F07FFF8FFFFULL;
+}
+
+static void aspeed_intc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = aspeed_intc_realize;
+ dc->reset = aspeed_intc_reset;
+ dc->desc = "ASPEED Interrupt Controller for AST27x0";
+ dc->vmsd = NULL;
+}
+
+static const TypeInfo aspeed_intc_info = {
+ .name = TYPE_ASPEED_INTC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AspeedINTCState),
+ .class_init = aspeed_intc_class_init,
+};
+
+static void aspeed_intc_register_types(void)
+{
+ type_register_static(&aspeed_intc_info);
+}
+
+type_init(aspeed_intc_register_types);
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index ed355941d1..f5c574f584 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -14,6 +14,7 @@ system_ss.add(when: 'CONFIG_ARM_GICV3_TCG', if_true: files(
))
system_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c'))
+system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_intc.c'))
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c'))
system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
diff --git a/include/hw/intc/aspeed_vic.h b/include/hw/intc/aspeed_vic.h
index 68d6ab997a..673a11d7fd 100644
--- a/include/hw/intc/aspeed_vic.h
+++ b/include/hw/intc/aspeed_vic.h
@@ -17,6 +17,7 @@
#include "qom/object.h"
#define TYPE_ASPEED_VIC "aspeed.vic"
+#define TYPE_ASPEED_INTC "aspeed.intc"
OBJECT_DECLARE_SIMPLE_TYPE(AspeedVICState, ASPEED_VIC)
#define ASPEED_VIC_NR_IRQS 51
@@ -46,4 +47,32 @@ struct AspeedVICState {
uint64_t event;
};
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedINTCState, ASPEED_INTC)
+
+struct AspeedINTCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ DeviceState *gic;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq irq;
+ qemu_irq fiq;
+
+ uint64_t level;
+ uint64_t raw;
+ uint64_t select;
+ uint64_t enable;
+ uint64_t trigger;
+
+ /* 0=edge, 1=level */
+ uint64_t sense;
+
+ /* 0=single-edge, 1=dual-edge */
+ uint64_t dual_edge;
+
+ /* 0=low-sensitive/falling-edge, 1=high-sensitive/rising-edge */
+ uint64_t event;
+};
+
#endif /* ASPEED_VIC_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v1 9/9] aspeed/soc: fix incorrect dram size for AST2700
2024-03-04 9:12 [PATCH v1 0/9] Add AST2700 support Jamin Lin via
` (3 preceding siblings ...)
2024-03-04 9:12 ` [PATCH v1 6/9] aspeed/intc: " Jamin Lin via
@ 2024-03-04 9:12 ` Jamin Lin via
4 siblings, 0 replies; 6+ messages in thread
From: Jamin Lin via @ 2024-03-04 9:12 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Andrew Jeffery,
Joel Stanley, Alistair Francis, open list:ASPEED BMCs,
open list:All patches CC here
Cc: jamin_lin, troy_lee, yunlin.tang
AST2700 dram size calculation is not back compatible AST2600.
According to the DDR capacity hardware behavior,
if users write the data to address which is beyond the ram size,
it would write the data to address 0.
For example:
a. sdram base address "0x4 00000000"
b. sdram size is 1 GiB
The available address range is from "0x4 00000000" to "0x4 40000000".
If users write 0xdeadbeef to address "0x6 00000000",
the value of DRAM address 0 (base address 0x4 00000000) should be 0xdeadbeef.
Adds aspeed_soc_ast2700_dram_init to calculation the dram size and add
memory I/O whose address range is from max_ram_size - ram_size to max_ram_size
and its read/write handler to emulate DDR capacity hardware behavior.
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/arm/aspeed_ast27x0.c | 94 ++++++++++++++++++++++++++++++++++++-
include/hw/arm/aspeed_soc.h | 1 +
2 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index c120994e5c..b78ae9369e 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,
@@ -118,6 +119,97 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
return qdev_get_gpio_in(a->intc.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: read @%" PRIx64 " out of ram size\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);
+ uint32_t test_pattern = 0xdeadbeef;
+ bool invalid_pattern = true;
+ uint32_t *ram_ptr;
+ int sz;
+
+ ram_ptr = memory_region_get_ram_ptr(s->dram_mr);
+
+ /*
+ * Emulate ddr capacity hardware behavior.
+ * If writes the test_pattern to address which is beyond the ram size,
+ * it would write the test_pattern to address 0.
+ */
+ for (sz = 4; sz > 0 ; sz--) {
+ test_pattern = (test_pattern << 4) + sz;
+ if (data == test_pattern) {
+ ram_ptr[0] = test_pattern;
+ invalid_pattern = false;
+ break;
+ }
+ }
+
+ if (invalid_pattern) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: write invalid pattern @%" PRIx64
+ " to addr @%" HWADDR_PRIx "]\n",
+ __func__, data, addr);
+ }
+}
+
+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);
+
+ /*
+ * 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);
@@ -362,7 +454,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 fab5abff9e..fae49f205b 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -126,6 +126,7 @@ struct Aspeed27x0SoCState {
ARMCPU cpu[ASPEED_CPUS_NUM];
AspeedINTCState intc;
+ MemoryRegion dram_empty;
};
#define TYPE_ASPEED27X0_SOC "aspeed27x0-soc"
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-03-04 9:14 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-04 9:12 [PATCH v1 0/9] Add AST2700 support Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 1/9] aspeed/wdt: " Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 2/9] aspeed/sli: " Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 3/9] aspeed/sdmc: " Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 6/9] aspeed/intc: " Jamin Lin via
2024-03-04 9:12 ` [PATCH v1 9/9] aspeed/soc: fix incorrect dram size for AST2700 Jamin Lin via
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).