[PATCH v3 16/16] docs:aspeed: Add AST2700 Evaluation board

2024-04-16 Thread Jamin Lin via
Add AST2700 Evaluation board and its boot command.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 docs/system/arm/aspeed.rst | 39 ++
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
index b2dea54eed..320ff2a4cd 100644
--- a/docs/system/arm/aspeed.rst
+++ b/docs/system/arm/aspeed.rst
@@ -1,11 +1,12 @@
-Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``)
-==
+Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``, 
``ast2700-evb``)
+===
 
 The QEMU Aspeed machines model BMCs of various OpenPOWER systems and
 Aspeed evaluation boards. They are based on different releases of the
 Aspeed SoC : the AST2400 integrating an ARM926EJ-S CPU (400MHz), the
-AST2500 with an ARM1176JZS CPU (800MHz) and more recently the AST2600
-with dual cores ARM Cortex-A7 CPUs (1.2GHz).
+AST2500 with an ARM1176JZS CPU (800MHz), the AST2600
+with dual cores ARM Cortex-A7 CPUs (1.2GHz) and more recently the AST2700
+with quad cores ARM Cortex-A35 64 bits CPUs (1.6GHz)
 
 The SoC comes with RAM, Gigabit ethernet, USB, SD/MMC, USB, SPI, I2C,
 etc.
@@ -38,6 +39,10 @@ AST2600 SoC based machines :
 - ``qcom-dc-scm-v1-bmc``   Qualcomm DC-SCM V1 BMC
 - ``qcom-firework-bmc``Qualcomm Firework BMC
 
+AST2700 SoC based machines :
+
+- ``ast2700-evb``  Aspeed AST2700 Evaluation board (Cortex-A35)
+
 Supported devices
 -
 
@@ -66,6 +71,7 @@ Supported devices
  * eMMC Boot Controller (dummy)
  * PECI Controller (minimal)
  * I3C Controller
+ * Internal Bridge Controller (SLI dummy)
 
 
 Missing devices
@@ -95,6 +101,10 @@ or directly from the OpenBMC GitHub release repository :
 
https://github.com/openbmc/openbmc/releases
 
+or directly from the ASPEED Forked OpenBMC GitHub release repository :
+
+   https://github.com/AspeedTech-BMC/openbmc/releases
+
 To boot a kernel directly from a Linux build tree:
 
 .. code-block:: bash
@@ -164,6 +174,27 @@ under Linux), use :
 
   -M ast2500-evb,bmc-console=uart3
 
+
+Boot the AST2700 machine from the flash image, use an MTD drive :
+
+.. code-block:: bash
+
+  IMGDIR=ast2700-default
+  UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
+
+  $ qemu-system-aarch64 -M ast2700-evb \
+   -device 
loader,force-raw=on,addr=0x4,file=${IMGDIR}/u-boot-nodtb.bin \
+   -device loader,force-raw=on,addr=$((0x4 + 
${UBOOT_SIZE})),file=u-boot.dtb \
+   -device loader,force-raw=on,addr=0x43000,file=${IMGDIR}/bl31.bin \
+   -device 
loader,force-raw=on,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin \
+   -device loader,cpu-num=0,addr=0x43000 \
+   -device loader,cpu-num=1,addr=0x43000 \
+   -device loader,cpu-num=2,addr=0x43000 \
+   -device loader,cpu-num=3,addr=0x43000 \
+   -smp 4 \
+   -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd \
+   -nographic
+
 Aspeed minibmc family boards (``ast1030-evb``)
 ==
 
-- 
2.25.1




[PATCH v3 11/16] aspeed/intc: Add AST2700 support

2024-04-16 Thread Jamin Lin via
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.

So far, this model only supports GICINT128 to GICINT136.
It creates 9 GICINT or-gates to connect 32 interrupts sources
from GICINT128 to GICINT136 as IRQ GPIO-OUTPUT pins.
Then, this model registers IRQ handler with its IRQ GPIO-INPUT pins which
connect to GICINT or-gates. And creates 9 GICINT IRQ GPIO-OUTPUT pins which
connect to GIC device with GIC IRQ 128 to 136.

If one interrupt source from GICINT128 to GICINT136
set irq, the OR-GATE irq callback function is called and set irq to INTC by
OR-GATE GPIO-OUTPUT pins. Then, the INTC irq callback function is called and
set irq to GIC by its GICINT IRQ GPIO-OUTPUT pins. Finally, the GIC irq
callback function is called and set irq to CPUs and
CPUs execute Interrupt Service Routine (ISR).

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/intc/aspeed_intc.c | 269 ++
 hw/intc/meson.build   |   1 +
 hw/intc/trace-events  |   6 +
 include/hw/intc/aspeed_intc.h |  35 +
 4 files changed, 311 insertions(+)
 create mode 100644 hw/intc/aspeed_intc.c
 create mode 100644 include/hw/intc/aspeed_intc.h

diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
new file mode 100644
index 00..df31900d56
--- /dev/null
+++ b/hw/intc/aspeed_intc.c
@@ -0,0 +1,269 @@
+/*
+ * ASPEED INTC Controller
+ *
+ * Copyright (C) 2024 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/intc/aspeed_intc.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"
+#include "hw/registerfields.h"
+#include "qapi/error.h"
+
+/* INTC Registers */
+REG32(GICINT128_EN, 0x1000)
+REG32(GICINT128_STATUS, 0x1004)
+REG32(GICINT129_EN, 0x1100)
+REG32(GICINT129_STATUS, 0x1104)
+REG32(GICINT130_EN, 0x1200)
+REG32(GICINT130_STATUS, 0x1204)
+REG32(GICINT131_EN, 0x1300)
+REG32(GICINT131_STATUS, 0x1304)
+REG32(GICINT132_EN, 0x1400)
+REG32(GICINT132_STATUS, 0x1404)
+REG32(GICINT133_EN, 0x1500)
+REG32(GICINT133_STATUS, 0x1504)
+REG32(GICINT134_EN, 0x1600)
+REG32(GICINT134_STATUS, 0x1604)
+REG32(GICINT135_EN, 0x1700)
+REG32(GICINT135_STATUS, 0x1704)
+REG32(GICINT136_EN, 0x1800)
+REG32(GICINT136_STATUS, 0x1804)
+
+#define GICINT_EN_BASE R_GICINT128_EN
+
+/*
+ * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
+ * Utilize "address & 0x0f00" to get the gicint_out index and
+ * its gic irq.
+ */
+static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
+{
+uint32_t gicint_enable_addr = GICINT_EN_BASE + ((0x100 * irq) >> 2);
+uint32_t gicint_status_addr = gicint_enable_addr + (0x4 >> 2);
+
+if (s->trigger[irq]) {
+if (!level && !s->regs[gicint_status_addr]) {
+/* clear irq */
+trace_aspeed_intc_update_irq(irq, 0);
+qemu_set_irq(s->gicint_out[irq], 0);
+s->trigger[irq] = false;
+}
+} else {
+if (s->new_gicint_status[irq]) {
+/* set irq */
+trace_aspeed_intc_update_irq(irq, 1);
+s->regs[gicint_status_addr] = s->new_gicint_status[irq];
+s->new_gicint_status[irq] = 0;
+qemu_set_irq(s->gicint_out[irq], 1);
+s->trigger[irq] = true;
+}
+}
+}
+
+/*
+ * The value of irq should be 0 to ASPEED_INTC_NR_GICS.
+ * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
+ */
+static void aspeed_intc_set_irq(void *opaque, int irq, int level)
+{
+AspeedINTCState *s = (AspeedINTCState *)opaque;
+uint32_t gicint_enable_addr = GICINT_EN_BASE + ((0x100 * irq) >> 2);
+uint32_t enable = s->regs[gicint_enable_addr];
+int i;
+
+if (irq > ASPEED_INTC_NR_GICS) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
+  __func__, irq);
+return;
+}
+
+trace_aspeed_intc_set_irq(irq, level);
+
+for (i = 0; i < 32; i++) {
+if (s->gicint_orgate[irq].levels[i]) {
+if (enable & BIT(i)) {
+s->new_gicint_status[irq] |= BIT(i);
+}
+}
+}
+
+aspeed_intc_update(s, irq, level);
+}
+
+static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int 
size)
+{
+AspeedINTCState *s = ASPEED_INTC(opaque);
+uint32_t addr = offset >> 2;
+uint32_t value = 0;
+
+if (addr >= ASPEED_INTC_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+  __func__, offset);

[PATCH v3 13/16] aspeed: Add an AST2700 eval board

2024-04-16 Thread Jamin Lin via
AST2700 CPU is ARM Cortex-A35 which is 64 bits.
Add TARGET_AARCH64 to build this machine.

According to the design of ast2700, it has a bootmcu(riscv-32) which
is used for executing SPL.
Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.

Currently, qemu not support emulate two CPU architectures
at the same machine. Therefore, qemu will only support
to emulate CPU(cortex-a35) side for ast2700

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 93ca87fda2..40dc0e4c76 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -178,6 +178,12 @@ struct AspeedMachineState {
 #define AST2600_EVB_HW_STRAP1 0x00C0
 #define AST2600_EVB_HW_STRAP2 0x0003
 
+#ifdef TARGET_AARCH64
+/* AST2700 evb hardware value */
+#define AST2700_EVB_HW_STRAP1 0x00C0
+#define AST2700_EVB_HW_STRAP2 0x0003
+#endif
+
 /* Tacoma hardware value */
 #define TACOMA_BMC_HW_STRAP1  0x
 #define TACOMA_BMC_HW_STRAP2  0x0040
@@ -1588,6 +1594,26 @@ static void 
aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
 aspeed_machine_class_init_cpus_defaults(mc);
 }
 
+#ifdef TARGET_AARCH64
+static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+mc->desc = "Aspeed AST2700 EVB (Cortex-A35)";
+amc->soc_name  = "ast2700-a0";
+amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
+amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
+amc->fmc_model = "w25q01jvq";
+amc->spi_model = "w25q512jv";
+amc->num_cs= 2;
+amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON;
+amc->uart_default = ASPEED_DEV_UART12;
+mc->default_ram_size = 1 * GiB;
+aspeed_machine_class_init_cpus_defaults(mc);
+}
+#endif
+
 static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
  void *data)
 {
@@ -1711,6 +1737,12 @@ static const TypeInfo aspeed_machine_types[] = {
 .name   = MACHINE_TYPE_NAME("ast1030-evb"),
 .parent = TYPE_ASPEED_MACHINE,
 .class_init = aspeed_minibmc_machine_ast1030_evb_class_init,
+#ifdef TARGET_AARCH64
+}, {
+.name  = MACHINE_TYPE_NAME("ast2700-evb"),
+.parent= TYPE_ASPEED_MACHINE,
+.class_init= aspeed_machine_ast2700_evb_class_init,
+#endif
 }, {
 .name  = TYPE_ASPEED_MACHINE,
 .parent= TYPE_MACHINE,
-- 
2.25.1




[PATCH v3 15/16] test/avocado/machine_aspeed.py: Add AST2700 test case

2024-04-16 Thread Jamin Lin via
Add a test case to test Aspeed OpenBMC SDK v09.01 on AST2700 board.

It loads u-boot-nodtb.bin, u-boot.dtb, tfa and optee-os
images to dram first which base address is 0x4.
Then, boot and launch 4 cpu cores.

```
qemu-system-aarch64 -machine ast2700-evb
-device loader,force-raw=on,addr=0x4,file=workdir/u-boot-nodtb.bin \
-device loader,force-raw=on,addr=uboot_dtb_load_addr,file=u-boot.dtb\
-device loader,force-raw=on,addr=0x43000,file=workdir/bl31.bin\
-device loader,force-raw=on,addr=0x43008,file=workdir/optee/tee-raw.bin\
-device loader,cpu-num=0,addr=0x43000 \
-device loader,cpu-num=1,addr=0x43000 \
-device loader,cpu-num=2,addr=0x43000 \
-device loader,cpu-num=3,addr=0x43000 \
-smp 4 \
-drive file=workdir/image-bmc,format=raw,if=mtd
```

A test image is downloaded from the ASPEED Forked OpenBMC GitHub release 
repository :
https://github.com/AspeedTech-BMC/openbmc/releases/

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 tests/avocado/machine_aspeed.py | 62 +
 1 file changed, 62 insertions(+)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index cec0181424..3a20644fb2 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -311,6 +311,17 @@ def do_test_arm_aspeed_sdk_start(self, image):
 self, 'boot', '## Loading kernel from FIT Image')
 self.wait_for_console_pattern('Starting kernel ...')
 
+def do_test_aarch64_aspeed_sdk_start(self, image):
+self.vm.set_console()
+self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw')
+
+self.vm.launch()
+
+self.wait_for_console_pattern('U-Boot 2023.10')
+self.wait_for_console_pattern('## Loading kernel from FIT Image')
+self.wait_for_console_pattern('Starting kernel ...')
+self.wait_for_console_pattern("systemd[1]: Hostname set to")
+
 @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on 
GitLab')
 
 def test_arm_ast2500_evb_sdk(self):
@@ -375,3 +386,54 @@ def test_arm_ast2600_evb_sdk(self):
  'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32');
 year = time.strftime("%Y")
 self.ssh_command_output_contains('/sbin/hwclock -f /dev/rtc1', year);
+
+def test_aarch64_ast2700_evb_sdk_v09_01(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:ast2700-evb
+"""
+
+image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
+ 'download/v09.01/ast2700-default-obmc.tar.gz')
+image_hash = 
'b1cc0fd73c7650d34c9c8459a243f52a91e9e27144b8608b2645ab19461d1e07'
+image_path = self.fetch_asset(image_url, asset_hash=image_hash,
+  algorithm='sha256')
+archive.extract(image_path, self.workdir)
+
+num_cpu = 4
+image_dir = self.workdir + '/ast2700-default/'
+uboot_size = os.path.getsize(image_dir + 'u-boot-nodtb.bin')
+uboot_dtb_load_addr = hex(0x4 + uboot_size)
+
+load_images_list = [
+{
+'addr': '0x4',
+'file': image_dir + 'u-boot-nodtb.bin'
+},
+{
+'addr': str(uboot_dtb_load_addr),
+'file': image_dir + 'u-boot.dtb'
+},
+{
+'addr': '0x43000',
+'file': image_dir + 'bl31.bin'
+},
+{
+'addr': '0x43008',
+'file': image_dir + 'optee/tee-raw.bin'
+}
+]
+
+for load_image in load_images_list:
+addr = load_image['addr']
+file = load_image['file']
+self.vm.add_args('-device',
+ f'loader,force-raw=on,addr={addr},file={file}')
+
+for i in range(num_cpu):
+self.vm.add_args('-device',
+ f'loader,addr=0x43000,cpu-num={i}')
+
+self.vm.add_args('-smp', str(num_cpu))
+self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')
+
-- 
2.25.1




[PATCH v3 03/16] aspeed/sdmc: remove redundant macros

2024-04-16 Thread Jamin Lin via
These macros are no longer used for ASPEED SOCs, so removes them.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_sdmc.c | 15 ---
 1 file changed, 15 deletions(-)

diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 64cd1a81dc..74279bbe8e 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -76,10 +76,6 @@
 #define ASPEED_SDMC_VGA_32MB0x2
 #define ASPEED_SDMC_VGA_64MB0x3
 #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,17 +96,6 @@
 #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 |\
-- 
2.25.1




[PATCH v3 01/16] aspeed/wdt: Add AST2700 support

2024-04-16 Thread Jamin Lin via
AST2700 wdt controller is similiar to AST2600's wdt, but
the AST2700 has 8 watchdogs, and they each have 0x80 of registers.
Introduce ast2700 object class and increase the number of regs(offset) of
ast2700 model.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 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 = 0xf; /* 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(_wdt_info);
 type_register_static(_2400_wdt_info);
 type_register_static(_2500_wdt_info);
 type_register_static(_2600_wdt_info);
+type_register_static(_2700_wdt_info);
 type_register_static(_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




[PATCH v3 14/16] aspeed/soc: fix incorrect dram size for AST2700

2024-04-16 Thread Jamin Lin via
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 "
b. sdram size is 1 GiB
The available address range is from "0x4 " to "0x4 4000".
If users write 0xdeadbeef to address "0x6 ",
the value of DRAM address 0 (base address 0x4 ) should be 0xdeadbeef.

Add aspeed_soc_ast2700_dram_init to calculate 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 
Signed-off-by: Jamin Lin 
---
 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 754c963230..38858e4fde 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]  =  0x4,
@@ -191,6 +192,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(>sdmc), "ram-size",
+_abort);
+max_ram_size = object_property_get_uint(OBJECT(>sdmc), "max-ram-size",
+_abort);
+
+memory_region_init(>dram_container, OBJECT(s), "ram-container",
+   ram_size);
+memory_region_add_subregion(>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(>dram_empty, OBJECT(s),
+  _ram_capacity_ops, s,
+  "ram-empty", max_ram_size - ram_size);
+
+memory_region_add_subregion(s->memory,
+sc->memmap[ASPEED_DEV_SDRAM] + ram_size,
+>dram_empty);
+}
+
+memory_region_add_subregion(s->memory,
+  sc->memmap[ASPEED_DEV_SDRAM], >dram_container);
+return true;
+}
+
 static void aspeed_soc_ast2700_init(Object *obj)
 {
 Aspeed27x0SoCState *a = ASPEED27X0_SOC(obj);
@@ -454,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 9f177b6037..9dbf48f873 

[PATCH v3 07/16] aspeed/smc: fix dma moving incorrect data length issue

2024-04-16 Thread Jamin Lin via
DMA length is from 1 byte to 32MB for AST2600 and AST10x0
and DMA length is from 4 bytes to 32MB for AST2500.

In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
data for AST2600 and AST10x0 and 4 bytes data for AST2500.
To support all ASPEED SOCs, adds dma_start_length parameter to store
the start length, add helper routines function to compute the dma length
and update DMA_LENGTH mask to "1FF" to fix dma moving
incorrect data length issue.

Currently, only supports dma length 4 bytes aligned.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/ssi/aspeed_smc.c | 52 -
 include/hw/ssi/aspeed_smc.h |  1 +
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 8a8d77b480..71abc7a2d8 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -178,13 +178,17 @@
  * DMA flash addresses should be 4 bytes aligned and the valid address
  * range is 0x2000 - 0x2FFF.
  *
- * DMA length is from 4 bytes to 32MB
+ * DMA length is from 4 bytes to 32MB (AST2500)
  *   0: 4 bytes
  *   0x7F: 32M bytes
+ *
+ * DMA length is from 1 byte to 32MB (AST2600, AST10x0)
+ *   0: 1 byte
+ *   0x1FF: 32M bytes
  */
 #define DMA_DRAM_ADDR(asc, val)   ((val) & (asc)->dma_dram_mask)
 #define DMA_FLASH_ADDR(asc, val)  ((val) & (asc)->dma_flash_mask)
-#define DMA_LENGTH(val) ((val) & 0x01FC)
+#define DMA_LENGTH(val) ((val) & 0x01FF)
 
 /* Flash opcodes. */
 #define SPI_OP_READ   0x03/* Read data bytes (low frequency) */
@@ -843,6 +847,24 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState 
*s)
 }
 }
 
+static uint32_t aspeed_smc_dma_len(AspeedSMCState *s)
+{
+AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+uint32_t dma_len;
+uint32_t extra;
+
+dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
+
+/* dma length 4 bytes aligned */
+extra = dma_len % 4;
+
+if (extra != 0) {
+dma_len += 4 - extra;
+}
+
+return dma_len;
+}
+
 /*
  * Accumulate the result of the reads to provide a checksum that will
  * be used to validate the read timing settings.
@@ -850,6 +872,7 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState 
*s)
 static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 {
 MemTxResult result;
+uint32_t dma_len;
 uint32_t data;
 
 if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
@@ -861,7 +884,9 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 aspeed_smc_dma_calibration(s);
 }
 
-while (s->regs[R_DMA_LEN]) {
+dma_len = aspeed_smc_dma_len(s);
+
+while (dma_len) {
 data = address_space_ldl_le(>flash_as, s->regs[R_DMA_FLASH_ADDR],
 MEMTXATTRS_UNSPECIFIED, );
 if (result != MEMTX_OK) {
@@ -877,7 +902,8 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
  */
 s->regs[R_DMA_CHECKSUM] += data;
 s->regs[R_DMA_FLASH_ADDR] += 4;
-s->regs[R_DMA_LEN] -= 4;
+dma_len -= 4;
+s->regs[R_DMA_LEN] = dma_len;
 }
 
 if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
@@ -889,14 +915,17 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 static void aspeed_smc_dma_rw(AspeedSMCState *s)
 {
 MemTxResult result;
+uint32_t dma_len;
 uint32_t data;
 
+dma_len = aspeed_smc_dma_len(s);
+
 trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
 "write" : "read",
 s->regs[R_DMA_FLASH_ADDR],
 s->regs[R_DMA_DRAM_ADDR],
-s->regs[R_DMA_LEN]);
-while (s->regs[R_DMA_LEN]) {
+dma_len);
+while (dma_len) {
 if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
 data = address_space_ldl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR],
 MEMTXATTRS_UNSPECIFIED, );
@@ -937,7 +966,8 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
  */
 s->regs[R_DMA_FLASH_ADDR] += 4;
 s->regs[R_DMA_DRAM_ADDR] += 4;
-s->regs[R_DMA_LEN] -= 4;
+dma_len -= 4;
+s->regs[R_DMA_LEN] = dma_len;
 s->regs[R_DMA_CHECKSUM] += data;
 }
 }
@@ -1381,6 +1411,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass 
*klass, void *data)
 asc->features  = ASPEED_SMC_FEATURE_DMA;
 asc->dma_flash_mask= 0x0FFC;
 asc->dma_dram_mask = 0x1FFC;
+asc->dma_start_length  = 4;
 asc->nregs = ASPEED_SMC_R_MAX;
 asc->segment_to_reg= aspeed_smc_segment_to_reg;
 asc->reg_to_segment= aspeed_smc_reg_to_segment;
@@ -1464,6 +1495,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass 
*klass, void *data)
 asc->features  = ASPEED_SMC_FEATURE_DMA;
 asc->dma_flash_mask= 0x0FFC;
 asc->dma_dram_mask = 0x3FFC;
+asc->dma_start_length  = 4;

[PATCH v3 09/16] aspeed/smc: Add AST2700 support

2024-04-16 Thread Jamin Lin via
AST2700 fmc/spi controller's address decoding unit is 64KB
and only bits [31:16] are used for decoding. Introduce seg_to_reg
and reg_to_seg handlers for ast2700 fmc/spi controller.
In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/ssi/aspeed_smc.c | 222 +++-
 1 file changed, 220 insertions(+), 2 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index a67cac3d0f..e768e5463c 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -185,7 +185,7 @@
  *   0: 4 bytes
  *   0x7F: 32M bytes
  *
- * DMA length is from 1 byte to 32MB (AST2600, AST10x0)
+ * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700)
  *   0: 1 byte
  *   0x1FF: 32M bytes
  */
@@ -670,7 +670,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-.max_access_size = 4,
+.max_access_size = 8,
 },
 };
 
@@ -1951,6 +1951,220 @@ static const TypeInfo aspeed_1030_spi2_info = {
 .class_init = aspeed_1030_spi2_class_init,
 };
 
+/*
+ * The FMC Segment Registers of the AST2700 have a 64KB unit.
+ * Only bits [31:16] are used for decoding.
+ */
+#define AST2700_SEG_ADDR_MASK 0x
+
+static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState *s,
+   const AspeedSegments *seg)
+{
+uint32_t reg = 0;
+
+/* Disabled segments have a nil register */
+if (!seg->size) {
+return 0;
+}
+
+reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset */
+reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /* end offset 
*/
+return reg;
+}
+
+static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s,
+   uint32_t reg, AspeedSegments *seg)
+{
+uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK;
+uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK;
+AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+
+if (reg) {
+seg->addr = asc->flash_window_base + start_offset;
+seg->size = end_offset + (64 * KiB) - start_offset;
+} else {
+seg->addr = asc->flash_window_base;
+seg->size = 0;
+}
+}
+
+static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = {
+[R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 |
+CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1),
+[R_CE_CTRL] = 0xaa00,
+[R_CTRL0] = 0x406b0641,
+[R_CTRL1] = 0x0400,
+[R_CTRL2] = 0x0400,
+[R_CTRL3] = 0x0400,
+[R_SEG_ADDR0] = 0x0800,
+[R_SEG_ADDR1] = 0x1800,
+[R_SEG_ADDR2] = 0x,
+[R_SEG_ADDR3] = 0x,
+[R_DUMMY_DATA] = 0x0001,
+[R_DMA_DRAM_ADDR_HIGH] = 0x,
+[R_TIMINGS] = 0x007b,
+};
+
+static const AspeedSegments aspeed_2700_fmc_segments[] = {
+{ 0x0, 128 * MiB }, /* start address is readonly */
+{ 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
+{ 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
+{ 0x0, 0 }, /* disabled */
+};
+
+static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
+
+dc->desc   = "Aspeed 2700 FMC Controller";
+asc->r_conf= R_CONF;
+asc->r_ce_ctrl = R_CE_CTRL;
+asc->r_ctrl0   = R_CTRL0;
+asc->r_timings = R_TIMINGS;
+asc->nregs_timings = 3;
+asc->conf_enable_w0= CONF_ENABLE_W0;
+asc->cs_num_max= 3;
+asc->segments  = aspeed_2700_fmc_segments;
+asc->segment_addr_mask = 0x;
+asc->resets= aspeed_2700_fmc_resets;
+asc->flash_window_base = 0x1;
+asc->flash_window_size = 1 * GiB;
+asc->features  = ASPEED_SMC_FEATURE_DMA |
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+asc->dma_flash_mask= 0x2FFC;
+asc->dma_dram_mask = 0xFFFC;
+asc->dma_start_length  = 1;
+asc->nregs = ASPEED_SMC_R_MAX;
+asc->segment_to_reg= aspeed_2700_smc_segment_to_reg;
+asc->reg_to_segment= aspeed_2700_smc_reg_to_segment;
+asc->dma_ctrl  = aspeed_2600_smc_dma_ctrl;
+}
+
+static const TypeInfo aspeed_2700_fmc_info = {
+.name =  "aspeed.fmc-ast2700",
+.parent = TYPE_ASPEED_SMC,
+.class_init = aspeed_2700_fmc_class_init,
+};
+
+static const AspeedSegments aspeed_2700_spi0_segments[] = {
+{ 0x0, 128 * MiB }, /* start address is readonly */
+{ 128 * MiB, 128 * MiB }, /* start address is readonly */
+{ 0x0, 0 }, /* disabled */
+};
+
+static void aspeed_2700_spi0_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+AspeedSMCClass *asc = 

[PATCH v3 02/16] aspeed/sli: Add AST2700 support

2024-04-16 Thread Jamin Lin via
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 dummy AST2700 SLI and SLIIO models.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_sli.c | 178 +++
 hw/misc/meson.build  |   3 +-
 hw/misc/trace-events |   7 ++
 include/hw/misc/aspeed_sli.h |  31 ++
 4 files changed, 218 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 00..e84fd6a4ca
--- /dev/null
+++ b/hw/misc/aspeed_sli.c
@@ -0,0 +1,178 @@
+/*
+ * ASPEED SLI Controller
+ *
+ * Copyright (C) 2024 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#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(>iomem, OBJECT(s), _sli_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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(>iomem, OBJECT(s), _sliio_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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, 

[PATCH v3 12/16] aspeed/soc: Add AST2700 support

2024-04-16 Thread Jamin Lin via
Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35 CPU).

AST2700 SOC and its interrupt controller are too complex to handle
in the common Aspeed SoC framework. We introduce a new ast2700
class with instance_init and realize handlers.

AST2700 is a 64 bits quad core cpus and support 8 watchdog.
Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8.
In addition, update AspeedSocState to support scuio, sli, sliio and intc.

Add TYPE_ASPEED27X0_SOC machine type.

The SDMC controller is unlocked at SPL stage.
At present, only supports to emulate booting
start from u-boot stage. Set SDMC controller
unlocked by default.

In INTC, each interrupt of INT 128 to INT 136 combines 32 interrupts.
It connect GICINT IRQ GPIO-OUTPUT pins to GIC device with irq 128 to 136.
And, if a device irq is 128 to 136, its irq GPIO-OUTPUT pin is connected to
GICINT or-gates instead of GIC device.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed_ast27x0.c | 554 
 hw/arm/meson.build  |   1 +
 include/hw/arm/aspeed_soc.h |  26 +-
 3 files changed, 579 insertions(+), 2 deletions(-)
 create mode 100644 hw/arm/aspeed_ast27x0.c

diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
new file mode 100644
index 00..754c963230
--- /dev/null
+++ b/hw/arm/aspeed_ast27x0.c
@@ -0,0 +1,554 @@
+/*
+ * ASPEED SoC 27x0 family
+ *
+ * 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.
+ *
+ * Implementation extracted from the AST2600 and adapted for AST27x0.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/misc/unimp.h"
+#include "hw/arm/aspeed_soc.h"
+#include "qemu/module.h"
+#include "qemu/error-report.h"
+#include "hw/i2c/aspeed_i2c.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/intc/arm_gicv3.h"
+#include "qapi/qmp/qlist.h"
+
+static const hwaddr aspeed_soc_ast2700_memmap[] = {
+[ASPEED_DEV_SPI_BOOT]  =  0x4,
+[ASPEED_DEV_SRAM]  =  0x1000,
+[ASPEED_DEV_SDMC]  =  0x12C0,
+[ASPEED_DEV_SCU]   =  0x12C02000,
+[ASPEED_DEV_SCUIO] =  0x14C02000,
+[ASPEED_DEV_UART0] =  0X14C33000,
+[ASPEED_DEV_UART1] =  0X14C33100,
+[ASPEED_DEV_UART2] =  0X14C33200,
+[ASPEED_DEV_UART3] =  0X14C33300,
+[ASPEED_DEV_UART4] =  0X12C1A000,
+[ASPEED_DEV_UART5] =  0X14C33400,
+[ASPEED_DEV_UART6] =  0X14C33500,
+[ASPEED_DEV_UART7] =  0X14C33600,
+[ASPEED_DEV_UART8] =  0X14C33700,
+[ASPEED_DEV_UART9] =  0X14C33800,
+[ASPEED_DEV_UART10]=  0X14C33900,
+[ASPEED_DEV_UART11]=  0X14C33A00,
+[ASPEED_DEV_UART12]=  0X14C33B00,
+[ASPEED_DEV_WDT]   =  0x14C37000,
+[ASPEED_DEV_VUART] =  0X14C3,
+[ASPEED_DEV_FMC]   =  0x1400,
+[ASPEED_DEV_SPI0]  =  0x1401,
+[ASPEED_DEV_SPI1]  =  0x1402,
+[ASPEED_DEV_SPI2]  =  0x1403,
+[ASPEED_DEV_SDRAM] =  0x4,
+[ASPEED_DEV_MII1]  =  0x1404,
+[ASPEED_DEV_MII2]  =  0x14040008,
+[ASPEED_DEV_MII3]  =  0x14040010,
+[ASPEED_DEV_ETH1]  =  0x1405,
+[ASPEED_DEV_ETH2]  =  0x1406,
+[ASPEED_DEV_ETH3]  =  0x1407,
+[ASPEED_DEV_EMMC]  =  0x1209,
+[ASPEED_DEV_INTC]  =  0x1210,
+[ASPEED_DEV_SLI]   =  0x12C17000,
+[ASPEED_DEV_SLIIO] =  0x14C1E000,
+[ASPEED_GIC_DIST]  =  0x1220,
+[ASPEED_GIC_REDIST]=  0x1228,
+};
+
+#define AST2700_MAX_IRQ 288
+
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
+static const int aspeed_soc_ast2700_irqmap[] = {
+[ASPEED_DEV_UART0] = 132,
+[ASPEED_DEV_UART1] = 132,
+[ASPEED_DEV_UART2] = 132,
+[ASPEED_DEV_UART3] = 132,
+[ASPEED_DEV_UART4] = 8,
+[ASPEED_DEV_UART5] = 132,
+[ASPEED_DEV_UART6] = 132,
+[ASPEED_DEV_UART7] = 132,
+[ASPEED_DEV_UART8] = 132,
+[ASPEED_DEV_UART9] = 132,
+[ASPEED_DEV_UART10]= 132,
+[ASPEED_DEV_UART11]= 132,
+[ASPEED_DEV_UART12]= 132,
+[ASPEED_DEV_FMC]   = 131,
+[ASPEED_DEV_SDMC]  = 0,
+[ASPEED_DEV_SCU]   = 12,
+[ASPEED_DEV_ADC]   = 130,
+[ASPEED_DEV_XDMA]  = 5,
+[ASPEED_DEV_EMMC]  = 15,
+[ASPEED_DEV_GPIO]  = 11,
+[ASPEED_DEV_GPIO_1_8V] = 130,
+[ASPEED_DEV_RTC]   = 13,
+[ASPEED_DEV_TIMER1]= 16,
+[ASPEED_DEV_TIMER2]= 17,
+[ASPEED_DEV_TIMER3]= 18,
+[ASPEED_DEV_TIMER4]= 19,
+[ASPEED_DEV_TIMER5]= 20,
+[ASPEED_DEV_TIMER6]= 21,
+[ASPEED_DEV_TIMER7]= 22,
+[ASPEED_DEV_TIMER8]= 23,
+[ASPEED_DEV_WDT]   = 131,
+[ASPEED_DEV_PWM]   = 131,
+[ASPEED_DEV_LPC]   = 128,
+[ASPEED_DEV_IBT]   = 128,
+[ASPEED_DEV_I2C]   = 

[PATCH v3 05/16] aspeed/sdmc: Add AST2700 support

2024-04-16 Thread Jamin Lin via
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.

Add unlocked property to change controller protected status.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_sdmc.c | 190 +-
 include/hw/misc/aspeed_sdmc.h |   5 +-
 2 files changed, 193 insertions(+), 2 deletions(-)

diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 873d67c592..69a34903db 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -27,6 +27,7 @@
 #define   PROT_SOFTLOCKED0x00
 
 #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)
  *
@@ -101,6 +142,19 @@
  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_RESERVED0x2082 /* 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);
@@ -216,7 +270,7 @@ 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 */
+assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
 s->max_ram_size = asc->max_ram_size;
 
 memory_region_init_io(>iomem, OBJECT(s), _sdmc_ops, s,
@@ -236,6 +290,7 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
 
 static Property aspeed_sdmc_properties[] = {
 DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0),
+DEFINE_PROP_BOOL("unlocked", AspeedSDMCState, unlocked, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -500,12 +555,145 @@ 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, 

[PATCH v3 10/16] aspeed/scu: Add AST2700 support

2024-04-16 Thread Jamin Lin via
AST2700 have two SCU controllers which are SCU and SCUIO.
Both SCU and SCUIO registers are not compatible previous SOCs
, introduces new registers and adds ast2700 scu, sucio class init handler.

The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
the pclk divider selection of SCU is defined in SCU280[25:23].
Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
and trace-event for AST2700 SCU and SCUIO.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
Reviewed-by: Cédric Le Goater 
---
 hw/misc/aspeed_scu.c | 306 ++-
 hw/misc/trace-events |   4 +
 include/hw/misc/aspeed_scu.h |  47 +-
 3 files changed, 351 insertions(+), 6 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 1ac04b6cb0..eb38ea8e19 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -134,6 +134,48 @@
 
 #define AST2600_CLK TO_REG(0x40)
 
+#define AST2700_SILICON_REV   TO_REG(0x00)
+#define AST2700_HW_STRAP1 TO_REG(0x10)
+#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
+#define AST2700_HW_STRAP1_LOCKTO_REG(0x20)
+#define AST2700_HW_STRAP1_SEC1TO_REG(0x24)
+#define AST2700_HW_STRAP1_SEC2TO_REG(0x28)
+#define AST2700_HW_STRAP1_SEC3TO_REG(0x2C)
+
+#define AST2700_SCU_CLK_SEL_1   TO_REG(0x280)
+#define AST2700_SCU_HPLL_PARAM  TO_REG(0x300)
+#define AST2700_SCU_HPLL_EXT_PARAM  TO_REG(0x304)
+#define AST2700_SCU_DPLL_PARAM  TO_REG(0x308)
+#define AST2700_SCU_DPLL_EXT_PARAM  TO_REG(0x30c)
+#define AST2700_SCU_MPLL_PARAM  TO_REG(0x310)
+#define AST2700_SCU_MPLL_EXT_PARAM  TO_REG(0x314)
+#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
+#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
+#define AST2700_SCU_CRT1CLK_PARAM   TO_REG(0x340)
+#define AST2700_SCU_CRT2CLK_PARAM   TO_REG(0x350)
+#define AST2700_SCU_MPHYCLK_PARAM   TO_REG(0x360)
+#define AST2700_SCU_FREQ_CNTR   TO_REG(0x3b0)
+#define AST2700_SCU_CPU_SCRATCH_0   TO_REG(0x780)
+#define AST2700_SCU_CPU_SCRATCH_1   TO_REG(0x784)
+
+#define AST2700_SCUIO_CLK_STOP_CTL_1TO_REG(0x240)
+#define AST2700_SCUIO_CLK_STOP_CLR_1TO_REG(0x244)
+#define AST2700_SCUIO_CLK_STOP_CTL_2TO_REG(0x260)
+#define AST2700_SCUIO_CLK_STOP_CLR_2TO_REG(0x264)
+#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
+#define AST2700_SCUIO_HPLL_PARAMTO_REG(0x300)
+#define AST2700_SCUIO_HPLL_EXT_PARAMTO_REG(0x304)
+#define AST2700_SCUIO_APLL_PARAMTO_REG(0x310)
+#define AST2700_SCUIO_APLL_EXT_PARAMTO_REG(0x314)
+#define AST2700_SCUIO_DPLL_PARAMTO_REG(0x320)
+#define AST2700_SCUIO_DPLL_EXT_PARAMTO_REG(0x324)
+#define AST2700_SCUIO_DPLL_PARAM_READ   TO_REG(0x328)
+#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
+#define AST2700_SCUIO_UARTCLK_GEN   TO_REG(0x330)
+#define AST2700_SCUIO_HUARTCLK_GEN  TO_REG(0x334)
+#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+
 #define SCU_IO_REGION_SIZE 0x1000
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
@@ -244,6 +286,25 @@ static uint32_t 
aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
 / asc->apb_divider;
 }
 
+static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
+
+return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
+   / asc->apb_divider;
+}
+
+static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
+
+return hpll /
+(SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
+/ asc->apb_divider;
+}
+
 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 {
 AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr 
offset, unsigned size)
 
 switch (reg) {
 case RNG_DATA:
-/* On hardware, RNG_DATA works regardless of
+/*
+ * On hardware, RNG_DATA works regardless of
  * the state of the enable bit in RNG_CTRL
  */
 s->regs[RNG_DATA] = aspeed_scu_get_random();
@@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
 AST2600_A3_SILICON_REV,
 AST1030_A0_SILICON_REV,
 AST1030_A1_SILICON_REV,
+AST2700_A0_SILICON_REV,
+AST2720_A0_SILICON_REV,
+AST2750_A0_SILICON_REV,
 };
 
 bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
 .class_init = aspeed_2600_scu_class_init,
 };
 
+static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+AspeedSCUState *s = ASPEED_SCU(opaque);
+int reg = TO_REG(offset);
+
+if (reg >= 

[PATCH v3 08/16] aspeed/smc: support 64 bits dma dram address

2024-04-16 Thread Jamin Lin via
AST2700 support the maximum dram size is 8GiB
and has a "DMA DRAM Side Address High Part(0x7C)"
register to support 64 bits dma dram address.
Add helper routines functions to compute the dma dram
address, new features and update trace-event
to support 64 bits dram address.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/ssi/aspeed_smc.c | 66 +++--
 hw/ssi/trace-events |  2 +-
 2 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 71abc7a2d8..a67cac3d0f 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -132,6 +132,9 @@
 #define   FMC_WDT2_CTRL_BOOT_SOURCE  BIT(4) /* O: primary 1: alternate */
 #define   FMC_WDT2_CTRL_EN   BIT(0)
 
+/* DMA DRAM Side Address High Part (AST2700) */
+#define R_DMA_DRAM_ADDR_HIGH   (0x7c / 4)
+
 /* DMA Control/Status Register */
 #define R_DMA_CTRL(0x80 / 4)
 #define   DMA_CTRL_REQUEST  (1 << 31)
@@ -187,6 +190,7 @@
  *   0x1FF: 32M bytes
  */
 #define DMA_DRAM_ADDR(asc, val)   ((val) & (asc)->dma_dram_mask)
+#define DMA_DRAM_ADDR_HIGH(val)   ((val) & 0xf)
 #define DMA_FLASH_ADDR(asc, val)  ((val) & (asc)->dma_flash_mask)
 #define DMA_LENGTH(val) ((val) & 0x01FF)
 
@@ -207,6 +211,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
 #define ASPEED_SMC_FEATURE_DMA   0x1
 #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
 #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
+#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
 
 static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
 {
@@ -218,6 +223,11 @@ static inline bool aspeed_smc_has_wdt_control(const 
AspeedSMCClass *asc)
 return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
 }
 
+static inline bool aspeed_smc_has_dma_dram_addr_high(const AspeedSMCClass *asc)
+{
+return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
+}
+
 #define aspeed_smc_error(fmt, ...)  \
 qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
 
@@ -747,6 +757,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, 
unsigned int size)
 (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) ||
+(aspeed_smc_has_dma(asc) &&
+ aspeed_smc_has_dma_dram_addr_high(asc) &&
+ addr == R_DMA_DRAM_ADDR_HIGH) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
 (addr >= R_SEG_ADDR0 &&
@@ -847,6 +860,23 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState 
*s)
 }
 }
 
+static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s)
+{
+AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+uint64_t dram_addr_high;
+uint64_t dma_dram_addr;
+
+if (aspeed_smc_has_dma_dram_addr_high(asc)) {
+dram_addr_high = s->regs[R_DMA_DRAM_ADDR_HIGH];
+dram_addr_high <<= 32;
+dma_dram_addr = dram_addr_high | s->regs[R_DMA_DRAM_ADDR];
+} else {
+dma_dram_addr = s->regs[R_DMA_DRAM_ADDR];
+}
+
+return dma_dram_addr;
+}
+
 static uint32_t aspeed_smc_dma_len(AspeedSMCState *s)
 {
 AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
@@ -914,24 +944,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 
 static void aspeed_smc_dma_rw(AspeedSMCState *s)
 {
+AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+uint64_t dram_addr_high;
+uint64_t dma_dram_addr;
+uint64_t dram_addr;
 MemTxResult result;
 uint32_t dma_len;
 uint32_t data;
 
 dma_len = aspeed_smc_dma_len(s);
+dma_dram_addr = aspeed_smc_dma_dram_addr(s);
+
+if (aspeed_smc_has_dma_dram_addr_high(asc)) {
+dram_addr = dma_dram_addr - s->dram_mr->container->addr;
+} else {
+dram_addr = dma_dram_addr;
+}
 
 trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
 "write" : "read",
 s->regs[R_DMA_FLASH_ADDR],
-s->regs[R_DMA_DRAM_ADDR],
+dram_addr,
 dma_len);
 while (dma_len) {
 if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
-data = address_space_ldl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR],
+data = address_space_ldl_le(>dram_as, dram_addr,
 MEMTXATTRS_UNSPECIFIED, );
 if (result != MEMTX_OK) {
-aspeed_smc_error("DRAM read failed @%08x",
- s->regs[R_DMA_DRAM_ADDR]);
+aspeed_smc_error("DRAM read failed @%" PRIx64, dram_addr);
 return;
 }
 
@@ -951,11 +991,10 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
 return;
 }
 
-address_space_stl_le(>dram_as, 

[PATCH v3 06/16] aspeed/smc: correct device description

2024-04-16 Thread Jamin Lin via
Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/ssi/aspeed_smc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 6e1a84c197..8a8d77b480 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -1448,7 +1448,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass 
*klass, void *data)
 DeviceClass *dc = DEVICE_CLASS(klass);
 AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
 
-dc->desc   = "Aspeed 2600 FMC Controller";
+dc->desc   = "Aspeed 2500 FMC Controller";
 asc->r_conf= R_CONF;
 asc->r_ce_ctrl = R_CE_CTRL;
 asc->r_ctrl0   = R_CTRL0;
@@ -1486,7 +1486,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass 
*klass, void *data)
 DeviceClass *dc = DEVICE_CLASS(klass);
 AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
 
-dc->desc   = "Aspeed 2600 SPI1 Controller";
+dc->desc   = "Aspeed 2500 SPI1 Controller";
 asc->r_conf= R_CONF;
 asc->r_ce_ctrl = R_CE_CTRL;
 asc->r_ctrl0   = R_CTRL0;
@@ -1521,7 +1521,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass 
*klass, void *data)
 DeviceClass *dc = DEVICE_CLASS(klass);
 AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass);
 
-dc->desc   = "Aspeed 2600 SPI2 Controller";
+dc->desc   = "Aspeed 2500 SPI2 Controller";
 asc->r_conf= R_CONF;
 asc->r_ce_ctrl = R_CE_CTRL;
 asc->r_ctrl0   = R_CTRL0;
-- 
2.25.1




[PATCH v3 04/16] aspeed/sdmc: fix coding style

2024-04-16 Thread Jamin Lin via
Fix coding style issues from checkpatch.pl

Test command:
scripts/checkpatch.pl --no-tree -f hw/misc/aspeed_sdmc.c

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_sdmc.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 74279bbe8e..873d67c592 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -296,7 +296,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;
 }
 
@@ -354,7 +355,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;
 }
 
@@ -434,8 +436,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;
 }
 
-- 
2.25.1




[PATCH v3 00/16] Add AST2700 support

2024-04-16 Thread Jamin Lin via
Changes from v1:
The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC.

Changes from v2:
- replace is_aarch64 with is_bus64bit for sdmc patch review.
- fix incorrect dram size for AST2700

Changes from v3:
- Add AST2700 Evaluation board in ASPEED document
- Add avocado test cases for AST2700 Evaluation board
- Fix reviewers review issues and add reviewers suggestions
- Implement INTC model GICINT 128 to GICINT136 for AST2700

Test steps:
1. Download the latest openbmc image for AST2700 from AspeedTech-BMC/openbmc
   repository, https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.01
   link: 
https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.01/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=$((0x4 + ${UBOOT_SIZE}))

qemu-system-aarch64 -M ast2700-evb -nographic\
 -device loader,addr=0x4,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=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\
 -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
 -device loader,addr=0x43000,cpu-num=0\
 -device loader,addr=0x43000,cpu-num=1\
 -device loader,addr=0x43000,cpu-num=2\
 -device loader,addr=0x43000,cpu-num=3\
 -smp 4\
 -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\
 -serial mon:stdio\
 -snapshot

Jamin Lin (16):
  aspeed/wdt: Add AST2700 support
  aspeed/sli: Add AST2700 support
  aspeed/sdmc: remove redundant macros
  aspeed/sdmc: fix coding style
  aspeed/sdmc: Add AST2700 support
  aspeed/smc: correct device description
  aspeed/smc: fix dma moving incorrect data length issue
  aspeed/smc: support 64 bits dma dram address
  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
  test/avocado/machine_aspeed.py: Add AST2700 test case
  docs:aspeed: Add AST2700 Evaluation board

 docs/system/arm/aspeed.rst   |  39 +-
 hw/arm/aspeed.c  |  32 ++
 hw/arm/aspeed_ast27x0.c  | 646 +++
 hw/arm/meson.build   |   1 +
 hw/intc/aspeed_intc.c| 269 +
 hw/intc/meson.build  |   1 +
 hw/intc/trace-events |   6 +
 hw/misc/aspeed_scu.c | 306 ++-
 hw/misc/aspeed_sdmc.c| 216 ++-
 hw/misc/aspeed_sli.c | 178 +
 hw/misc/meson.build  |   3 +-
 hw/misc/trace-events |  11 +
 hw/ssi/aspeed_smc.c  | 344 +++-
 hw/ssi/trace-events  |   2 +-
 hw/watchdog/wdt_aspeed.c |  24 ++
 include/hw/arm/aspeed_soc.h  |  27 +-
 include/hw/intc/aspeed_intc.h|  35 ++
 include/hw/misc/aspeed_scu.h |  47 ++-
 include/hw/misc/aspeed_sdmc.h|   5 +-
 include/hw/misc/aspeed_sli.h |  31 ++
 include/hw/ssi/aspeed_smc.h  |   1 +
 include/hw/watchdog/wdt_aspeed.h |   3 +-
 tests/avocado/machine_aspeed.py  |  62 +++
 23 files changed, 2234 insertions(+), 55 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/intc/aspeed_intc.h
 create mode 100644 include/hw/misc/aspeed_sli.h

-- 
2.25.1




[PATCH v2 6/9] aspeed/intc: Add AST2700 support

2024-03-04 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _intc_ops, s,
+  TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+sysbus_init_mmio(sbd, >iomem);
+
+qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+sysbus_init_irq(sbd, >irq);
+sysbus_init_irq(sbd, >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 = 0x1F07FFF8ULL;
+s->dual_edge = 0xF80007ULL;
+s->event = 0x5F07FFF8ULL;
+}
+
+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(_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: 

[PATCH v2 4/9] aspeed/smc: Add AST2700 support

2024-03-04 Thread Jamin Lin via
AST2700 fmc/spi controller's address decoding unit is 64KB
and only bits [31:16] are used for decoding. Introduce seg_to_reg
and reg_to_seg handlers for ast2700 fmc/spi controller.
In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler.

AST2700 support the maximum dram size is 8GiB.
Update dma_rw function and trace-event to support 64 bits dram
address. DMA length is from 1 byte to 32MB for AST2700, AST2600 and AST10x0
and DMA length is from 4 bytes to 32MB for AST2500.

In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
data for AST2700, AST2600 and AST10x0 and 4 bytes data for AST2500.
To support all ASPEED SOCs, adds dma_start_length parameter to store
the start length and update DMA_LENGTH mask to "1FF" to fix dma moving
incorrect data length issue.

Currently, dma_rw function only supports length 4 bytes aligned.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/ssi/aspeed_smc.c | 326 +---
 hw/ssi/trace-events |   2 +-
 include/hw/ssi/aspeed_smc.h |   1 +
 3 files changed, 309 insertions(+), 20 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 3c93936fd1..73121edf2b 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -131,6 +131,9 @@
 #define   FMC_WDT2_CTRL_BOOT_SOURCE  BIT(4) /* O: primary 1: alternate */
 #define   FMC_WDT2_CTRL_EN   BIT(0)
 
+/* DMA DRAM Side Address High Part (AST2700) */
+#define R_DMA_DRAM_ADDR_HIGH   (0x7c / 4)
+
 /* DMA Control/Status Register */
 #define R_DMA_CTRL(0x80 / 4)
 #define   DMA_CTRL_REQUEST  (1 << 31)
@@ -177,13 +180,18 @@
  * DMA flash addresses should be 4 bytes aligned and the valid address
  * range is 0x2000 - 0x2FFF.
  *
- * DMA length is from 4 bytes to 32MB
+ * DMA length is from 4 bytes to 32MB (AST2500)
  *   0: 4 bytes
  *   0x7F: 32M bytes
+ *
+ * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700)
+ *   0: 1 byte
+ *   0x1FF: 32M bytes
  */
 #define DMA_DRAM_ADDR(asc, val)   ((val) & (asc)->dma_dram_mask)
+#define DMA_DRAM_ADDR_HIGH(val)   ((val) & 0xf)
 #define DMA_FLASH_ADDR(asc, val)  ((val) & (asc)->dma_flash_mask)
-#define DMA_LENGTH(val) ((val) & 0x01FC)
+#define DMA_LENGTH(val) ((val) & 0x01FF)
 
 /* Flash opcodes. */
 #define SPI_OP_READ   0x03/* Read data bytes (low frequency) */
@@ -202,6 +210,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
 #define ASPEED_SMC_FEATURE_DMA   0x1
 #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
 #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
+#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
 
 static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
 {
@@ -213,6 +222,11 @@ static inline bool aspeed_smc_has_wdt_control(const 
AspeedSMCClass *asc)
 return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
 }
 
+static inline bool aspeed_smc_has_dma_dram_addr_high(const AspeedSMCClass *asc)
+{
+return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
+}
+
 #define aspeed_smc_error(fmt, ...)  \
 qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
 
@@ -655,7 +669,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-.max_access_size = 4,
+.max_access_size = 8,
 },
 };
 
@@ -734,6 +748,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, 
unsigned int size)
 (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) ||
+(aspeed_smc_has_dma(asc) &&
+ aspeed_smc_has_dma_dram_addr_high(asc) &&
+ addr == R_DMA_DRAM_ADDR_HIGH) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
 (addr >= R_SEG_ADDR0 &&
@@ -840,8 +857,11 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState 
*s)
  */
 static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 {
+AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
 MemTxResult result;
+uint32_t dma_len;
 uint32_t data;
+uint32_t extra;
 
 if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
 aspeed_smc_error("invalid direction for DMA checksum");
@@ -852,7 +872,14 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 aspeed_smc_dma_calibration(s);
 }
 
-while (s->regs[R_DMA_LEN]) {
+dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
+/* dma length 4 bytes aligned */
+extra = dma_len % 4;
+if (extra != 0) {
+dma_len += 4 - extra;
+}
+
+while (dma_len) {
 data = address_space_ldl_le(>flash_as, s->regs[R_DMA_FLASH_ADDR],
 MEMTXATTRS_UNSPECIFIED, );
 if (result != MEMTX_OK) {
@@ -868,7 +895,8 @@ 

[PATCH v2 0/9] Add AST2700 support

2024-03-04 Thread Jamin Lin via
Changes from v1:
The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC.

Changes from v2:
- replace is_aarch64 with is_bus64bit for sdmc patch review.
- fix incorrect dram size for AST2700

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=$((0x4 + ${UBOOT_SIZE}))

qemu-system-aarch64 -M ast2700-evb -nographic\
 -device loader,addr=0x4,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=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\
 -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
 -device loader,addr=0x43000,cpu-num=0\
 -device loader,addr=0x43000,cpu-num=1\
 -device loader,addr=0x43000,cpu-num=2\
 -device loader,addr=0x43000,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




[PATCH v2 3/9] aspeed/sdmc: Add AST2700 support

2024-03-04 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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_SOFTLOCKED0x00
 
 #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_32MB0x2
 #define ASPEED_SDMC_VGA_64MB0x3
 #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_RESERVED0x2082 /* 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   \
+ 

[PATCH v2 5/9] aspeed/scu: Add AST2700 support

2024-03-04 Thread Jamin Lin via
AST2700 have two SCU controllers which are SCU and SCUIO.
Both SCU and SCUIO registers are not compatible previous SOCs
, introduces new registers and adds ast2700 scu, sucio class init handler.

The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
the pclk divider selection of SCU is defined in SCU280[25:23].
Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
and trace-event for AST2700 SCU and SCUIO.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_scu.c | 306 ++-
 hw/misc/trace-events |   4 +
 include/hw/misc/aspeed_scu.h |  47 +-
 3 files changed, 351 insertions(+), 6 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 1ac04b6cb0..eb38ea8e19 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -134,6 +134,48 @@
 
 #define AST2600_CLK TO_REG(0x40)
 
+#define AST2700_SILICON_REV   TO_REG(0x00)
+#define AST2700_HW_STRAP1 TO_REG(0x10)
+#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
+#define AST2700_HW_STRAP1_LOCKTO_REG(0x20)
+#define AST2700_HW_STRAP1_SEC1TO_REG(0x24)
+#define AST2700_HW_STRAP1_SEC2TO_REG(0x28)
+#define AST2700_HW_STRAP1_SEC3TO_REG(0x2C)
+
+#define AST2700_SCU_CLK_SEL_1   TO_REG(0x280)
+#define AST2700_SCU_HPLL_PARAM  TO_REG(0x300)
+#define AST2700_SCU_HPLL_EXT_PARAM  TO_REG(0x304)
+#define AST2700_SCU_DPLL_PARAM  TO_REG(0x308)
+#define AST2700_SCU_DPLL_EXT_PARAM  TO_REG(0x30c)
+#define AST2700_SCU_MPLL_PARAM  TO_REG(0x310)
+#define AST2700_SCU_MPLL_EXT_PARAM  TO_REG(0x314)
+#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
+#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
+#define AST2700_SCU_CRT1CLK_PARAM   TO_REG(0x340)
+#define AST2700_SCU_CRT2CLK_PARAM   TO_REG(0x350)
+#define AST2700_SCU_MPHYCLK_PARAM   TO_REG(0x360)
+#define AST2700_SCU_FREQ_CNTR   TO_REG(0x3b0)
+#define AST2700_SCU_CPU_SCRATCH_0   TO_REG(0x780)
+#define AST2700_SCU_CPU_SCRATCH_1   TO_REG(0x784)
+
+#define AST2700_SCUIO_CLK_STOP_CTL_1TO_REG(0x240)
+#define AST2700_SCUIO_CLK_STOP_CLR_1TO_REG(0x244)
+#define AST2700_SCUIO_CLK_STOP_CTL_2TO_REG(0x260)
+#define AST2700_SCUIO_CLK_STOP_CLR_2TO_REG(0x264)
+#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
+#define AST2700_SCUIO_HPLL_PARAMTO_REG(0x300)
+#define AST2700_SCUIO_HPLL_EXT_PARAMTO_REG(0x304)
+#define AST2700_SCUIO_APLL_PARAMTO_REG(0x310)
+#define AST2700_SCUIO_APLL_EXT_PARAMTO_REG(0x314)
+#define AST2700_SCUIO_DPLL_PARAMTO_REG(0x320)
+#define AST2700_SCUIO_DPLL_EXT_PARAMTO_REG(0x324)
+#define AST2700_SCUIO_DPLL_PARAM_READ   TO_REG(0x328)
+#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
+#define AST2700_SCUIO_UARTCLK_GEN   TO_REG(0x330)
+#define AST2700_SCUIO_HUARTCLK_GEN  TO_REG(0x334)
+#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+
 #define SCU_IO_REGION_SIZE 0x1000
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
@@ -244,6 +286,25 @@ static uint32_t 
aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
 / asc->apb_divider;
 }
 
+static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
+
+return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
+   / asc->apb_divider;
+}
+
+static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
+
+return hpll /
+(SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
+/ asc->apb_divider;
+}
+
 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 {
 AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr 
offset, unsigned size)
 
 switch (reg) {
 case RNG_DATA:
-/* On hardware, RNG_DATA works regardless of
+/*
+ * On hardware, RNG_DATA works regardless of
  * the state of the enable bit in RNG_CTRL
  */
 s->regs[RNG_DATA] = aspeed_scu_get_random();
@@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
 AST2600_A3_SILICON_REV,
 AST1030_A0_SILICON_REV,
 AST1030_A1_SILICON_REV,
+AST2700_A0_SILICON_REV,
+AST2720_A0_SILICON_REV,
+AST2750_A0_SILICON_REV,
 };
 
 bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
 .class_init = aspeed_2600_scu_class_init,
 };
 
+static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+AspeedSCUState *s = ASPEED_SCU(opaque);
+int reg = TO_REG(offset);
+
+if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+  

[PATCH v1 6/9] aspeed/intc: Add AST2700 support

2024-03-04 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _intc_ops, s,
+  TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+sysbus_init_mmio(sbd, >iomem);
+
+qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+sysbus_init_irq(sbd, >irq);
+sysbus_init_irq(sbd, >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 = 0x1F07FFF8ULL;
+s->dual_edge = 0xF80007ULL;
+s->event = 0x5F07FFF8ULL;
+}
+
+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(_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: 

[PATCH v1 9/9] aspeed/soc: fix incorrect dram size for AST2700

2024-03-04 Thread Jamin Lin via
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 "
b. sdram size is 1 GiB
The available address range is from "0x4 " to "0x4 4000".
If users write 0xdeadbeef to address "0x6 ",
the value of DRAM address 0 (base address 0x4 ) 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 
Signed-off-by: Jamin Lin 
---
 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]  =  0x4,
@@ -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(>sdmc), "ram-size",
+_abort);
+max_ram_size = object_property_get_uint(OBJECT(>sdmc), "max-ram-size",
+_abort);
+
+memory_region_init(>dram_container, OBJECT(s), "ram-container",
+   ram_size);
+memory_region_add_subregion(>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(>dram_empty, OBJECT(s),
+  _ram_capacity_ops, s,
+  "ram-empty", max_ram_size - ram_size);
+
+memory_region_add_subregion(s->memory,
+sc->memmap[ASPEED_DEV_SDRAM] + ram_size,
+>dram_empty);
+}
+
+memory_region_add_subregion(s->memory,
+  sc->memmap[ASPEED_DEV_SDRAM], >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 

[PATCH v1 0/9] Add AST2700 support

2024-03-04 Thread Jamin Lin via
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=$((0x4 + ${UBOOT_SIZE}))

qemu-system-aarch64 -M ast2700-evb -nographic\
 -device loader,addr=0x4,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=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\
 -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
 -device loader,addr=0x43000,cpu-num=0\
 -device loader,addr=0x43000,cpu-num=1\
 -device loader,addr=0x43000,cpu-num=2\
 -device loader,addr=0x43000,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




[PATCH v1 2/9] aspeed/sli: Add AST2700 support

2024-03-04 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _sli_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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(>iomem, OBJECT(s), _sliio_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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);

[PATCH v1 1/9] aspeed/wdt: Add AST2700 support

2024-03-04 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 = 0xf; /* 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(_wdt_info);
 type_register_static(_2400_wdt_info);
 type_register_static(_2500_wdt_info);
 type_register_static(_2600_wdt_info);
+type_register_static(_2700_wdt_info);
 type_register_static(_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




[PATCH v1 3/9] aspeed/sdmc: Add AST2700 support

2024-03-04 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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_SOFTLOCKED0x00
 
 #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_32MB0x2
 #define ASPEED_SDMC_VGA_64MB0x3
 #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_RESERVED0x2082 /* 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   \
+ 

[PATCH v1 8/8] aspeed: Add an AST2700 eval board

2024-02-29 Thread Jamin Lin via
AST2700 CPU is ARM Cortex-A35 which is 64 bits.
Add TARGET_AARCH64 to build this machine.

According to the design of ast2700, it has a bootmcu(riscv-32) which
is used for executing SPL.
Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.

Currently, qemu not support emulate two CPU architectures
at the same machine. Therefore, qemu will only support
to emulate CPU(cortex-a35) side for ast2700

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 8854581ca8..4544026d14 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -178,6 +178,12 @@ struct AspeedMachineState {
 #define AST2600_EVB_HW_STRAP1 0x00C0
 #define AST2600_EVB_HW_STRAP2 0x0003
 
+#ifdef TARGET_AARCH64
+/* AST2700 evb hardware value */
+#define AST2700_EVB_HW_STRAP1 0x00C0
+#define AST2700_EVB_HW_STRAP2 0x0003
+#endif
+
 /* Tacoma hardware value */
 #define TACOMA_BMC_HW_STRAP1  0x
 #define TACOMA_BMC_HW_STRAP2  0x0040
@@ -1588,6 +1594,26 @@ static void 
aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
 aspeed_machine_class_init_cpus_defaults(mc);
 }
 
+#ifdef TARGET_AARCH64
+static void aspeed_machine_ast2700_evb_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+mc->desc = "Aspeed AST2700 EVB (Cortex-A35)";
+amc->soc_name  = "ast2700-a0";
+amc->hw_strap1 = AST2700_EVB_HW_STRAP1;
+amc->hw_strap2 = AST2700_EVB_HW_STRAP2;
+amc->fmc_model = "w25q01jvq";
+amc->spi_model = "w25q512jv";
+amc->num_cs= 2;
+amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON;
+amc->uart_default = ASPEED_DEV_UART12;
+mc->default_ram_size = 1 * GiB;
+aspeed_machine_class_init_cpus_defaults(mc);
+}
+#endif
+
 static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
  void *data)
 {
@@ -1711,6 +1737,12 @@ static const TypeInfo aspeed_machine_types[] = {
 .name   = MACHINE_TYPE_NAME("ast1030-evb"),
 .parent = TYPE_ASPEED_MACHINE,
 .class_init = aspeed_minibmc_machine_ast1030_evb_class_init,
+#ifdef TARGET_AARCH64
+}, {
+.name  = MACHINE_TYPE_NAME("ast2700-evb"),
+.parent= TYPE_ASPEED_MACHINE,
+.class_init= aspeed_machine_ast2700_evb_class_init,
+#endif
 }, {
 .name  = TYPE_ASPEED_MACHINE,
 .parent= TYPE_MACHINE,
-- 
2.25.1




[PATCH v1 5/8] aspeed/scu: Add AST2700 support

2024-02-29 Thread Jamin Lin via
AST2700 have two SCU controllers which are SCU and SCUIO.
Both SCU and SCUIO registers are not compatible previous SOCs
, introduces new registers and adds ast2700 scu, sucio class init handler.

The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
the pclk divider selection of SCU is defined in SCU280[25:23].
Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
and trace-event for AST2700 SCU and SCUIO.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_scu.c | 306 ++-
 hw/misc/trace-events |   4 +
 include/hw/misc/aspeed_scu.h |  47 +-
 3 files changed, 351 insertions(+), 6 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 1ac04b6cb0..eb38ea8e19 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -134,6 +134,48 @@
 
 #define AST2600_CLK TO_REG(0x40)
 
+#define AST2700_SILICON_REV   TO_REG(0x00)
+#define AST2700_HW_STRAP1 TO_REG(0x10)
+#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
+#define AST2700_HW_STRAP1_LOCKTO_REG(0x20)
+#define AST2700_HW_STRAP1_SEC1TO_REG(0x24)
+#define AST2700_HW_STRAP1_SEC2TO_REG(0x28)
+#define AST2700_HW_STRAP1_SEC3TO_REG(0x2C)
+
+#define AST2700_SCU_CLK_SEL_1   TO_REG(0x280)
+#define AST2700_SCU_HPLL_PARAM  TO_REG(0x300)
+#define AST2700_SCU_HPLL_EXT_PARAM  TO_REG(0x304)
+#define AST2700_SCU_DPLL_PARAM  TO_REG(0x308)
+#define AST2700_SCU_DPLL_EXT_PARAM  TO_REG(0x30c)
+#define AST2700_SCU_MPLL_PARAM  TO_REG(0x310)
+#define AST2700_SCU_MPLL_EXT_PARAM  TO_REG(0x314)
+#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
+#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
+#define AST2700_SCU_CRT1CLK_PARAM   TO_REG(0x340)
+#define AST2700_SCU_CRT2CLK_PARAM   TO_REG(0x350)
+#define AST2700_SCU_MPHYCLK_PARAM   TO_REG(0x360)
+#define AST2700_SCU_FREQ_CNTR   TO_REG(0x3b0)
+#define AST2700_SCU_CPU_SCRATCH_0   TO_REG(0x780)
+#define AST2700_SCU_CPU_SCRATCH_1   TO_REG(0x784)
+
+#define AST2700_SCUIO_CLK_STOP_CTL_1TO_REG(0x240)
+#define AST2700_SCUIO_CLK_STOP_CLR_1TO_REG(0x244)
+#define AST2700_SCUIO_CLK_STOP_CTL_2TO_REG(0x260)
+#define AST2700_SCUIO_CLK_STOP_CLR_2TO_REG(0x264)
+#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
+#define AST2700_SCUIO_HPLL_PARAMTO_REG(0x300)
+#define AST2700_SCUIO_HPLL_EXT_PARAMTO_REG(0x304)
+#define AST2700_SCUIO_APLL_PARAMTO_REG(0x310)
+#define AST2700_SCUIO_APLL_EXT_PARAMTO_REG(0x314)
+#define AST2700_SCUIO_DPLL_PARAMTO_REG(0x320)
+#define AST2700_SCUIO_DPLL_EXT_PARAMTO_REG(0x324)
+#define AST2700_SCUIO_DPLL_PARAM_READ   TO_REG(0x328)
+#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
+#define AST2700_SCUIO_UARTCLK_GEN   TO_REG(0x330)
+#define AST2700_SCUIO_HUARTCLK_GEN  TO_REG(0x334)
+#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+
 #define SCU_IO_REGION_SIZE 0x1000
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
@@ -244,6 +286,25 @@ static uint32_t 
aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
 / asc->apb_divider;
 }
 
+static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
+
+return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
+   / asc->apb_divider;
+}
+
+static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
+
+return hpll /
+(SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
+/ asc->apb_divider;
+}
+
 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 {
 AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr 
offset, unsigned size)
 
 switch (reg) {
 case RNG_DATA:
-/* On hardware, RNG_DATA works regardless of
+/*
+ * On hardware, RNG_DATA works regardless of
  * the state of the enable bit in RNG_CTRL
  */
 s->regs[RNG_DATA] = aspeed_scu_get_random();
@@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
 AST2600_A3_SILICON_REV,
 AST1030_A0_SILICON_REV,
 AST1030_A1_SILICON_REV,
+AST2700_A0_SILICON_REV,
+AST2720_A0_SILICON_REV,
+AST2750_A0_SILICON_REV,
 };
 
 bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
 .class_init = aspeed_2600_scu_class_init,
 };
 
+static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+AspeedSCUState *s = ASPEED_SCU(opaque);
+int reg = TO_REG(offset);
+
+if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+  

[PATCH v1 0/8] Add AST2700 support

2024-02-29 Thread Jamin Lin via
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=$((0x4 + ${UBOOT_SIZE}))

qemu-system-aarch64 -M ast2700-evb -nographic -m 8G\
 -device loader,addr=0x4,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=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\
 -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
 -device loader,addr=0x43000,cpu-num=0\
 -device loader,addr=0x43000,cpu-num=1\
 -device loader,addr=0x43000,cpu-num=2\
 -device loader,addr=0x43000,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.

2. It is required to add "-m 8G" to set the dram size 8G.
AST2700 dram size calculation is not compatible AST2600.
According to the DDR hardware capacity behavior, if users write the
data at address which is over than the supported size, it would set
the data at address 0.
For example:
a. sdram base address "0x4 "
b. sdram size is 1GiB
The available address range is from "0x4 " to "0x4 4000".
If users write 0xdeadbeef at address "0x6 ", the value of
DRAM address 0 (base address 0x4 ) should be 0xdeadbeef.
Please see ast2700_sdrammc_calc_size in
https://github.com/AspeedTech-BMC/u-boot/blob/v00.05.00/drivers/ram/aspeed/
sdram_ast2700.c

It seems we should create a new function instead of aspeed_soc_dram_init
to support AST2700.
https://github.com/qemu/qemu/blob/master/hw/arm/aspeed_soc_common.c

Jamin Lin (8):
  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

 hw/arm/aspeed.c  |  32 +++
 hw/arm/aspeed_ast27x0.c  | 462 +++
 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  |  26 +-
 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, 1787 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




[PATCH v1 2/8] aspeed/sli: Add AST2700 support

2024-02-29 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _sli_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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(>iomem, OBJECT(s), _sliio_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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);

[PATCH v1 6/8] aspeed/intc: Add AST2700 support

2024-02-29 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _intc_ops, s,
+  TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+sysbus_init_mmio(sbd, >iomem);
+
+qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+sysbus_init_irq(sbd, >irq);
+sysbus_init_irq(sbd, >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 = 0x1F07FFF8ULL;
+s->dual_edge = 0xF80007ULL;
+s->event = 0x5F07FFF8ULL;
+}
+
+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(_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: 

[PATCH v1 1/8] aspeed/wdt: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 = 0xf; /* 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(_wdt_info);
 type_register_static(_2400_wdt_info);
 type_register_static(_2500_wdt_info);
 type_register_static(_2600_wdt_info);
+type_register_static(_2700_wdt_info);
 type_register_static(_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




[PATCH v1 2/8] aspeed/sli: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _sli_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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(>iomem, OBJECT(s), _sliio_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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);

[PATCH v1 5/8] aspeed/scu: Add AST2700 support

2024-02-28 Thread Jamin Lin via
AST2700 have two SCU controllers which are SCU and SCUIO.
Both SCU and SCUIO registers are not compatible previous SOCs
, introduces new registers and adds ast2700 scu, sucio class init handler.

The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
the pclk divider selection of SCU is defined in SCU280[25:23].
Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
and trace-event for AST2700 SCU and SCUIO.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_scu.c | 306 ++-
 hw/misc/trace-events |   4 +
 include/hw/misc/aspeed_scu.h |  47 +-
 3 files changed, 351 insertions(+), 6 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 1ac04b6cb0..eb38ea8e19 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -134,6 +134,48 @@
 
 #define AST2600_CLK TO_REG(0x40)
 
+#define AST2700_SILICON_REV   TO_REG(0x00)
+#define AST2700_HW_STRAP1 TO_REG(0x10)
+#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
+#define AST2700_HW_STRAP1_LOCKTO_REG(0x20)
+#define AST2700_HW_STRAP1_SEC1TO_REG(0x24)
+#define AST2700_HW_STRAP1_SEC2TO_REG(0x28)
+#define AST2700_HW_STRAP1_SEC3TO_REG(0x2C)
+
+#define AST2700_SCU_CLK_SEL_1   TO_REG(0x280)
+#define AST2700_SCU_HPLL_PARAM  TO_REG(0x300)
+#define AST2700_SCU_HPLL_EXT_PARAM  TO_REG(0x304)
+#define AST2700_SCU_DPLL_PARAM  TO_REG(0x308)
+#define AST2700_SCU_DPLL_EXT_PARAM  TO_REG(0x30c)
+#define AST2700_SCU_MPLL_PARAM  TO_REG(0x310)
+#define AST2700_SCU_MPLL_EXT_PARAM  TO_REG(0x314)
+#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
+#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
+#define AST2700_SCU_CRT1CLK_PARAM   TO_REG(0x340)
+#define AST2700_SCU_CRT2CLK_PARAM   TO_REG(0x350)
+#define AST2700_SCU_MPHYCLK_PARAM   TO_REG(0x360)
+#define AST2700_SCU_FREQ_CNTR   TO_REG(0x3b0)
+#define AST2700_SCU_CPU_SCRATCH_0   TO_REG(0x780)
+#define AST2700_SCU_CPU_SCRATCH_1   TO_REG(0x784)
+
+#define AST2700_SCUIO_CLK_STOP_CTL_1TO_REG(0x240)
+#define AST2700_SCUIO_CLK_STOP_CLR_1TO_REG(0x244)
+#define AST2700_SCUIO_CLK_STOP_CTL_2TO_REG(0x260)
+#define AST2700_SCUIO_CLK_STOP_CLR_2TO_REG(0x264)
+#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
+#define AST2700_SCUIO_HPLL_PARAMTO_REG(0x300)
+#define AST2700_SCUIO_HPLL_EXT_PARAMTO_REG(0x304)
+#define AST2700_SCUIO_APLL_PARAMTO_REG(0x310)
+#define AST2700_SCUIO_APLL_EXT_PARAMTO_REG(0x314)
+#define AST2700_SCUIO_DPLL_PARAMTO_REG(0x320)
+#define AST2700_SCUIO_DPLL_EXT_PARAMTO_REG(0x324)
+#define AST2700_SCUIO_DPLL_PARAM_READ   TO_REG(0x328)
+#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
+#define AST2700_SCUIO_UARTCLK_GEN   TO_REG(0x330)
+#define AST2700_SCUIO_HUARTCLK_GEN  TO_REG(0x334)
+#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+
 #define SCU_IO_REGION_SIZE 0x1000
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
@@ -244,6 +286,25 @@ static uint32_t 
aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
 / asc->apb_divider;
 }
 
+static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
+
+return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
+   / asc->apb_divider;
+}
+
+static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
+
+return hpll /
+(SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
+/ asc->apb_divider;
+}
+
 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 {
 AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr 
offset, unsigned size)
 
 switch (reg) {
 case RNG_DATA:
-/* On hardware, RNG_DATA works regardless of
+/*
+ * On hardware, RNG_DATA works regardless of
  * the state of the enable bit in RNG_CTRL
  */
 s->regs[RNG_DATA] = aspeed_scu_get_random();
@@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
 AST2600_A3_SILICON_REV,
 AST1030_A0_SILICON_REV,
 AST1030_A1_SILICON_REV,
+AST2700_A0_SILICON_REV,
+AST2720_A0_SILICON_REV,
+AST2750_A0_SILICON_REV,
 };
 
 bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
 .class_init = aspeed_2600_scu_class_init,
 };
 
+static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+AspeedSCUState *s = ASPEED_SCU(opaque);
+int reg = TO_REG(offset);
+
+if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+  

[PATCH v1 6/8] aspeed/intc: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _intc_ops, s,
+  TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+sysbus_init_mmio(sbd, >iomem);
+
+qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+sysbus_init_irq(sbd, >irq);
+sysbus_init_irq(sbd, >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 = 0x1F07FFF8ULL;
+s->dual_edge = 0xF80007ULL;
+s->event = 0x5F07FFF8ULL;
+}
+
+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(_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: 

[PATCH v1 2/8] aspeed/sli: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _sli_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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(>iomem, OBJECT(s), _sliio_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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);

[PATCH v1 7/8] aspeed/soc: Add AST2700 support

2024-02-28 Thread Jamin Lin via
Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35 CPU).

AST2700 SOC and its interrupt controller are too complex to handle
in the common Aspeed SoC framework. We introduce a new ast2700
class with instance_init and realize handlers.

AST2700 is a 64 bits quad core cpus and support 8 watchdog.
Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8.
In addition, update AspeedSocState to support scuio, sli, sliio and intc.

Update silicon_rev data type to 64bits from AspeedSoCClass and
add TYPE_ASPEED27X0_SOC machine type.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed_ast27x0.c | 462 
 hw/arm/meson.build  |   1 +
 include/hw/arm/aspeed_soc.h |  26 +-
 3 files changed, 486 insertions(+), 3 deletions(-)
 create mode 100644 hw/arm/aspeed_ast27x0.c

diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
new file mode 100644
index 00..c120994e5c
--- /dev/null
+++ b/hw/arm/aspeed_ast27x0.c
@@ -0,0 +1,462 @@
+/*
+ * ASPEED SoC 27x0 family
+ *
+ * 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.
+ *
+ * Implementation extracted from the AST2600 and adapted for AST27x0.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/misc/unimp.h"
+#include "hw/arm/aspeed_soc.h"
+#include "qemu/module.h"
+#include "qemu/error-report.h"
+#include "hw/i2c/aspeed_i2c.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/intc/arm_gicv3.h"
+#include "qapi/qmp/qlist.h"
+
+static const hwaddr aspeed_soc_ast2700_memmap[] = {
+[ASPEED_DEV_SPI_BOOT]  =  0x4,
+[ASPEED_DEV_SRAM]  =  0x1000,
+[ASPEED_DEV_SDMC]  =  0x12C0,
+[ASPEED_DEV_SCU]   =  0x12C02000,
+[ASPEED_DEV_SCUIO] =  0x14C02000,
+[ASPEED_DEV_UART0] =  0X14C33000,
+[ASPEED_DEV_UART1] =  0X14C33100,
+[ASPEED_DEV_UART2] =  0X14C33200,
+[ASPEED_DEV_UART3] =  0X14C33300,
+[ASPEED_DEV_UART4] =  0X12C1A000,
+[ASPEED_DEV_UART5] =  0X14C33400,
+[ASPEED_DEV_UART6] =  0X14C33500,
+[ASPEED_DEV_UART7] =  0X14C33600,
+[ASPEED_DEV_UART8] =  0X14C33700,
+[ASPEED_DEV_UART9] =  0X14C33800,
+[ASPEED_DEV_UART10]=  0X14C33900,
+[ASPEED_DEV_UART11]=  0X14C33A00,
+[ASPEED_DEV_UART12]=  0X14C33B00,
+[ASPEED_DEV_WDT]   =  0x14C37000,
+[ASPEED_DEV_VUART] =  0X14C3,
+[ASPEED_DEV_FMC]   =  0x1400,
+[ASPEED_DEV_SPI0]  =  0x1401,
+[ASPEED_DEV_SPI1]  =  0x1402,
+[ASPEED_DEV_SPI2]  =  0x1403,
+[ASPEED_DEV_SDRAM] =  0x4,
+[ASPEED_DEV_MII1]  =  0x1404,
+[ASPEED_DEV_MII2]  =  0x14040008,
+[ASPEED_DEV_MII3]  =  0x14040010,
+[ASPEED_DEV_ETH1]  =  0x1405,
+[ASPEED_DEV_ETH2]  =  0x1406,
+[ASPEED_DEV_ETH3]  =  0x1407,
+[ASPEED_DEV_EMMC]  =  0x1209,
+[ASPEED_DEV_VIC]   =  0x1210,
+[ASPEED_DEV_SLI]   =  0x12C17000,
+[ASPEED_DEV_SLIIO] =  0x14C1E000,
+[ASPEED_GIC_DIST]  =  0x1220,
+[ASPEED_GIC_REDIST]=  0x1228,
+};
+
+#define AST2700_MAX_IRQ 288
+
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
+static const int aspeed_soc_ast2700_irqmap[] = {
+[ASPEED_DEV_UART0] = 132,
+[ASPEED_DEV_UART1] = 132,
+[ASPEED_DEV_UART2] = 132,
+[ASPEED_DEV_UART3] = 132,
+[ASPEED_DEV_UART4] = 8,
+[ASPEED_DEV_UART5] = 132,
+[ASPEED_DEV_UART6] = 132,
+[ASPEED_DEV_UART7] = 132,
+[ASPEED_DEV_UART8] = 132,
+[ASPEED_DEV_UART9] = 132,
+[ASPEED_DEV_UART10]= 132,
+[ASPEED_DEV_UART11]= 132,
+[ASPEED_DEV_UART12]= 132,
+[ASPEED_DEV_FMC]   = 131,
+[ASPEED_DEV_SDMC]  = 0,
+[ASPEED_DEV_SCU]   = 12,
+[ASPEED_DEV_ADC]   = 130,
+[ASPEED_DEV_XDMA]  = 5,
+[ASPEED_DEV_EMMC]  = 15,
+[ASPEED_DEV_GPIO]  = 11,
+[ASPEED_DEV_GPIO_1_8V] = 130,
+[ASPEED_DEV_RTC]   = 13,
+[ASPEED_DEV_TIMER1]= 16,
+[ASPEED_DEV_TIMER2]= 17,
+[ASPEED_DEV_TIMER3]= 18,
+[ASPEED_DEV_TIMER4]= 19,
+[ASPEED_DEV_TIMER5]= 20,
+[ASPEED_DEV_TIMER6]= 21,
+[ASPEED_DEV_TIMER7]= 22,
+[ASPEED_DEV_TIMER8]= 23,
+[ASPEED_DEV_WDT]   = 131,
+[ASPEED_DEV_PWM]   = 131,
+[ASPEED_DEV_LPC]   = 128,
+[ASPEED_DEV_IBT]   = 128,
+[ASPEED_DEV_I2C]   = 130,
+[ASPEED_DEV_PECI]  = 133,
+[ASPEED_DEV_ETH1]  = 132,
+[ASPEED_DEV_ETH2]  = 132,
+[ASPEED_DEV_ETH3]  = 132,
+[ASPEED_DEV_HACE]  = 4,
+[ASPEED_DEV_KCS]   = 128,
+[ASPEED_DEV_DP]= 28,
+[ASPEED_DEV_I3C]   = 131,
+};
+
+static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int 

[PATCH v1 0/8] Add AST2700 support

2024-02-28 Thread Jamin Lin via
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=$((0x4 + ${UBOOT_SIZE}))

qemu-system-aarch64 -M ast2700-evb -nographic -m 8G\
 -device loader,addr=0x4,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=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\
 -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\
 -device loader,addr=0x43000,cpu-num=0\
 -device loader,addr=0x43000,cpu-num=1\
 -device loader,addr=0x43000,cpu-num=2\
 -device loader,addr=0x43000,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.

2. It is required to add "-m 8G" to set the dram size 8G.
AST2700 dram size calculation is not compatible AST2600.
According to the DDR hardware capacity behavior, if users write the
data at address which is over than the supported size, it would set
the data at address 0.
For example:
a. sdram base address "0x4 "
b. sdram size is 1GiB
The available address range is from "0x4 " to "0x4 4000".
If users write 0xdeadbeef at address "0x6 ", the value of
DRAM address 0 (base address 0x4 ) should be 0xdeadbeef.
Please see ast2700_sdrammc_calc_size in
https://github.com/AspeedTech-BMC/u-boot/blob/v00.05.00/drivers/ram/aspeed/
sdram_ast2700.c

It seems we should create a new function instead of aspeed_soc_dram_init
to support AST2700.
https://github.com/qemu/qemu/blob/master/hw/arm/aspeed_soc_common.c

Jamin Lin (8):
  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

 hw/arm/aspeed.c  |  32 +++
 hw/arm/aspeed_ast27x0.c  | 462 +++
 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  |  26 +-
 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, 1787 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




[PATCH v1 3/8] aspeed/sdmc: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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..a5bdda0f60 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -27,6 +27,7 @@
 #define   PROT_SOFTLOCKED0x00
 
 #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_32MB0x2
 #define ASPEED_SDMC_VGA_64MB0x3
 #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_RESERVED0x2082 /* 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   \
+ 

[PATCH v1 6/8] aspeed/intc: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _intc_ops, s,
+  TYPE_ASPEED_INTC, ASPEED_INTC_SIZE);
+
+sysbus_init_mmio(sbd, >iomem);
+
+qdev_init_gpio_in(dev, aspeed_intc_set_irq, ASPEED_INTC_NR_IRQS);
+sysbus_init_irq(sbd, >irq);
+sysbus_init_irq(sbd, >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 = 0x1F07FFF8ULL;
+s->dual_edge = 0xF80007ULL;
+s->event = 0x5F07FFF8ULL;
+}
+
+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(_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: 

[PATCH v1 5/8] aspeed/scu: Add AST2700 support

2024-02-28 Thread Jamin Lin via
AST2700 have two SCU controllers which are SCU and SCUIO.
Both SCU and SCUIO registers are not compatible previous SOCs
, introduces new registers and adds ast2700 scu, sucio class init handler.

The pclk divider selection of SCUIO is defined in SCUIO280[20:18] and
the pclk divider selection of SCU is defined in SCU280[25:23].
Both of them are not compatible AST2600 SOCs, adds a get_apb_freq function
and trace-event for AST2700 SCU and SCUIO.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/misc/aspeed_scu.c | 306 ++-
 hw/misc/trace-events |   4 +
 include/hw/misc/aspeed_scu.h |  47 +-
 3 files changed, 351 insertions(+), 6 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 1ac04b6cb0..eb38ea8e19 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -134,6 +134,48 @@
 
 #define AST2600_CLK TO_REG(0x40)
 
+#define AST2700_SILICON_REV   TO_REG(0x00)
+#define AST2700_HW_STRAP1 TO_REG(0x10)
+#define AST2700_HW_STRAP1_CLR TO_REG(0x14)
+#define AST2700_HW_STRAP1_LOCKTO_REG(0x20)
+#define AST2700_HW_STRAP1_SEC1TO_REG(0x24)
+#define AST2700_HW_STRAP1_SEC2TO_REG(0x28)
+#define AST2700_HW_STRAP1_SEC3TO_REG(0x2C)
+
+#define AST2700_SCU_CLK_SEL_1   TO_REG(0x280)
+#define AST2700_SCU_HPLL_PARAM  TO_REG(0x300)
+#define AST2700_SCU_HPLL_EXT_PARAM  TO_REG(0x304)
+#define AST2700_SCU_DPLL_PARAM  TO_REG(0x308)
+#define AST2700_SCU_DPLL_EXT_PARAM  TO_REG(0x30c)
+#define AST2700_SCU_MPLL_PARAM  TO_REG(0x310)
+#define AST2700_SCU_MPLL_EXT_PARAM  TO_REG(0x314)
+#define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
+#define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
+#define AST2700_SCU_CRT1CLK_PARAM   TO_REG(0x340)
+#define AST2700_SCU_CRT2CLK_PARAM   TO_REG(0x350)
+#define AST2700_SCU_MPHYCLK_PARAM   TO_REG(0x360)
+#define AST2700_SCU_FREQ_CNTR   TO_REG(0x3b0)
+#define AST2700_SCU_CPU_SCRATCH_0   TO_REG(0x780)
+#define AST2700_SCU_CPU_SCRATCH_1   TO_REG(0x784)
+
+#define AST2700_SCUIO_CLK_STOP_CTL_1TO_REG(0x240)
+#define AST2700_SCUIO_CLK_STOP_CLR_1TO_REG(0x244)
+#define AST2700_SCUIO_CLK_STOP_CTL_2TO_REG(0x260)
+#define AST2700_SCUIO_CLK_STOP_CLR_2TO_REG(0x264)
+#define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
+#define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
+#define AST2700_SCUIO_HPLL_PARAMTO_REG(0x300)
+#define AST2700_SCUIO_HPLL_EXT_PARAMTO_REG(0x304)
+#define AST2700_SCUIO_APLL_PARAMTO_REG(0x310)
+#define AST2700_SCUIO_APLL_EXT_PARAMTO_REG(0x314)
+#define AST2700_SCUIO_DPLL_PARAMTO_REG(0x320)
+#define AST2700_SCUIO_DPLL_EXT_PARAMTO_REG(0x324)
+#define AST2700_SCUIO_DPLL_PARAM_READ   TO_REG(0x328)
+#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
+#define AST2700_SCUIO_UARTCLK_GEN   TO_REG(0x330)
+#define AST2700_SCUIO_HUARTCLK_GEN  TO_REG(0x334)
+#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+
 #define SCU_IO_REGION_SIZE 0x1000
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
@@ -244,6 +286,25 @@ static uint32_t 
aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
 / asc->apb_divider;
 }
 
+static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
+
+return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
+   / asc->apb_divider;
+}
+
+static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
+{
+AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
+uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
+
+return hpll /
+(SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
+/ asc->apb_divider;
+}
+
 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 {
 AspeedSCUState *s = ASPEED_SCU(opaque);
@@ -258,7 +319,8 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr 
offset, unsigned size)
 
 switch (reg) {
 case RNG_DATA:
-/* On hardware, RNG_DATA works regardless of
+/*
+ * On hardware, RNG_DATA works regardless of
  * the state of the enable bit in RNG_CTRL
  */
 s->regs[RNG_DATA] = aspeed_scu_get_random();
@@ -494,6 +556,9 @@ static uint32_t aspeed_silicon_revs[] = {
 AST2600_A3_SILICON_REV,
 AST1030_A0_SILICON_REV,
 AST1030_A1_SILICON_REV,
+AST2700_A0_SILICON_REV,
+AST2720_A0_SILICON_REV,
+AST2750_A0_SILICON_REV,
 };
 
 bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -783,6 +848,243 @@ static const TypeInfo aspeed_2600_scu_info = {
 .class_init = aspeed_2600_scu_class_init,
 };
 
+static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+AspeedSCUState *s = ASPEED_SCU(opaque);
+int reg = TO_REG(offset);
+
+if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
+  

[PATCH v1 2/8] aspeed/sli: Add AST2700 support

2024-02-28 Thread Jamin Lin via
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 
Signed-off-by: Jamin Lin 
---
 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 00..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(>iomem, OBJECT(s), _sli_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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(>iomem, OBJECT(s), _sliio_ops, s,
+  TYPE_ASPEED_SLI, SLI_REGION_SIZE);
+sysbus_init_mmio(sbd, >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);

[PATCH v1 4/8] aspeed/smc: Add AST2700 support

2024-02-28 Thread Jamin Lin via
AST2700 fmc/spi controller's address decoding unit is 64KB
and only bits [31:16] are used for decoding. Introduce seg_to_reg
and reg_to_seg handlers for ast2700 fmc/spi controller.
In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler.

AST2700 support the maximum dram size is 8GiB.
Update dma_rw function and trace-event to support 64 bits dram
address. DMA length is from 1 byte to 32MB for AST2700, AST2600 and AST10x0
and DMA length is from 4 bytes to 32MB for AST2500.

In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
data for AST2700, AST2600 and AST10x0 and 4 bytes data for AST2500.
To support all ASPEED SOCs, adds dma_start_length parameter to store
the start length and update DMA_LENGTH mask to "1FF" to fix dma moving
incorrect data length issue.

Currently, dma_rw function only supports length 4 bytes aligned.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/ssi/aspeed_smc.c | 326 +---
 hw/ssi/trace-events |   2 +-
 include/hw/ssi/aspeed_smc.h |   1 +
 3 files changed, 309 insertions(+), 20 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 3c93936fd1..73121edf2b 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -131,6 +131,9 @@
 #define   FMC_WDT2_CTRL_BOOT_SOURCE  BIT(4) /* O: primary 1: alternate */
 #define   FMC_WDT2_CTRL_EN   BIT(0)
 
+/* DMA DRAM Side Address High Part (AST2700) */
+#define R_DMA_DRAM_ADDR_HIGH   (0x7c / 4)
+
 /* DMA Control/Status Register */
 #define R_DMA_CTRL(0x80 / 4)
 #define   DMA_CTRL_REQUEST  (1 << 31)
@@ -177,13 +180,18 @@
  * DMA flash addresses should be 4 bytes aligned and the valid address
  * range is 0x2000 - 0x2FFF.
  *
- * DMA length is from 4 bytes to 32MB
+ * DMA length is from 4 bytes to 32MB (AST2500)
  *   0: 4 bytes
  *   0x7F: 32M bytes
+ *
+ * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700)
+ *   0: 1 byte
+ *   0x1FF: 32M bytes
  */
 #define DMA_DRAM_ADDR(asc, val)   ((val) & (asc)->dma_dram_mask)
+#define DMA_DRAM_ADDR_HIGH(val)   ((val) & 0xf)
 #define DMA_FLASH_ADDR(asc, val)  ((val) & (asc)->dma_flash_mask)
-#define DMA_LENGTH(val) ((val) & 0x01FC)
+#define DMA_LENGTH(val) ((val) & 0x01FF)
 
 /* Flash opcodes. */
 #define SPI_OP_READ   0x03/* Read data bytes (low frequency) */
@@ -202,6 +210,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
 #define ASPEED_SMC_FEATURE_DMA   0x1
 #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
 #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
+#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
 
 static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
 {
@@ -213,6 +222,11 @@ static inline bool aspeed_smc_has_wdt_control(const 
AspeedSMCClass *asc)
 return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
 }
 
+static inline bool aspeed_smc_has_dma_dram_addr_high(const AspeedSMCClass *asc)
+{
+return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
+}
+
 #define aspeed_smc_error(fmt, ...)  \
 qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
 
@@ -655,7 +669,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 .valid = {
 .min_access_size = 1,
-.max_access_size = 4,
+.max_access_size = 8,
 },
 };
 
@@ -734,6 +748,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, 
unsigned int size)
 (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) ||
+(aspeed_smc_has_dma(asc) &&
+ aspeed_smc_has_dma_dram_addr_high(asc) &&
+ addr == R_DMA_DRAM_ADDR_HIGH) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
 (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
 (addr >= R_SEG_ADDR0 &&
@@ -840,8 +857,11 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState 
*s)
  */
 static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 {
+AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
 MemTxResult result;
+uint32_t dma_len;
 uint32_t data;
+uint32_t extra;
 
 if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
 aspeed_smc_error("invalid direction for DMA checksum");
@@ -852,7 +872,14 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
 aspeed_smc_dma_calibration(s);
 }
 
-while (s->regs[R_DMA_LEN]) {
+dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
+/* dma length 4 bytes aligned */
+extra = dma_len % 4;
+if (extra != 0) {
+dma_len += 4 - extra;
+}
+
+while (dma_len) {
 data = address_space_ldl_le(>flash_as, s->regs[R_DMA_FLASH_ADDR],
 MEMTXATTRS_UNSPECIFIED, );
 if (result != MEMTX_OK) {
@@ -868,7 +895,8 @@ 

[PATCH v3 2/2] aspeed: fix hardcode boot address 0

2024-02-15 Thread Jamin Lin via
In the previous design of ASPEED SOCs QEMU model, it set the boot
address at "0" which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has a bootmcu(riscv-32) which
is used for executing SPL and initialize DRAM and copy u-boot image
from SPI/Flash to DRAM at address 0x4 at SPL boot stage.
Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.

Currently, qemu not support emulate two CPU architectures
at the same machine. Therefore, qemu will only support
to emulate CPU(cortex-a35) side for ast2700 and the boot
address is "0x4 ".

Fixed hardcode boot address "0" for future models using
a different mapping address.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 hw/arm/aspeed_ast2400.c | 4 ++--
 hw/arm/aspeed_ast2600.c | 2 +-
 include/hw/arm/aspeed_soc.h | 2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index aa165d583b..9fec245e4e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 95da85fee0..d125886207 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -26,7 +26,7 @@
 #define ASPEED_SOC_IOMEM_SIZE   0x0020
 
 static const hwaddr aspeed_soc_ast2400_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  =  ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
@@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 };
 
 static const hwaddr aspeed_soc_ast2500_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index f74561ecdc..174be53770 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -22,7 +22,7 @@
 #define ASPEED_SOC_DPMCU_SIZE   0x0004
 
 static const hwaddr aspeed_soc_ast2600_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_SRAM]  = 0x1000,
 [ASPEED_DEV_DPMCU] = 0x1800,
 /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index e1a023be53..c60fac900a 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -224,8 +224,6 @@ enum {
 ASPEED_DEV_FSI2,
 };
 
-#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
-
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
 bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
-- 
2.25.1




[PATCH v3 0/2] UART0 device name and fix hardcode boot address 0

2024-02-15 Thread Jamin Lin via
v1:
1. support uart controller both 0 and 1 base
2. fix hardcode boot address 0

v2:
1. introduce a new UART0 device name
2. remove ASPEED_SOC_SPI_BOOT_ADDR marco

v3:
1. add uart helper functions to get the index, start and last.
2. add more description in commit log

Jamin Lin (2):
  aspeed: introduce a new UART0 device name
  aspeed: fix hardcode boot address 0

 hw/arm/aspeed.c | 17 +++--
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  6 --
 hw/arm/aspeed_ast2600.c |  3 ++-
 hw/arm/aspeed_soc_common.c  | 10 ++
 include/hw/arm/aspeed_soc.h | 19 +--
 6 files changed, 41 insertions(+), 15 deletions(-)

-- 
2.25.1




[PATCH v3 0/2] UART0 device name and fix hardcode boot address 0

2024-02-14 Thread Jamin Lin via
v1:
1. support uart controller both 0 and 1 base
2. fix hardcode boot address 0

v2:
1. introduce a new UART0 device name
2. remove ASPEED_SOC_SPI_BOOT_ADDR marco

v3:
1. add uart helper functions to get the index, start and last.
2. add more description in commit log

Jamin Lin (2):
  aspeed: introduce a new UART0 device name
  aspeed: fix hardcode boot address 0

 hw/arm/aspeed.c | 17 +++--
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  6 --
 hw/arm/aspeed_ast2600.c |  3 ++-
 hw/arm/aspeed_soc_common.c  | 10 ++
 include/hw/arm/aspeed_soc.h | 19 +--
 6 files changed, 41 insertions(+), 15 deletions(-)

-- 
2.25.1




[PATCH v3 2/2] aspeed: fix hardcode boot address 0

2024-02-14 Thread Jamin Lin via
In the previous design of ASPEED SOCs QEMU model, it set the boot
address at "0" which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has a bootmcu(riscv-32) which
is used for executing SPL and initialize DRAM and copy u-boot image
from SPI/Flash to DRAM at address 0x4 at SPL boot stage.
Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.

Currently, qemu not support emulate two CPU architectures
at the same machine. Therefore, qemu will only support
to emulate CPU(cortex-a35) side for ast2700 and the boot
address is "0x4 ".

Fixed hardcode boot address "0" for future models using
a different mapping address.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 hw/arm/aspeed_ast2400.c | 4 ++--
 hw/arm/aspeed_ast2600.c | 2 +-
 include/hw/arm/aspeed_soc.h | 2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index aa165d583b..9fec245e4e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 95da85fee0..d125886207 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -26,7 +26,7 @@
 #define ASPEED_SOC_IOMEM_SIZE   0x0020
 
 static const hwaddr aspeed_soc_ast2400_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  =  ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
@@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 };
 
 static const hwaddr aspeed_soc_ast2500_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index f74561ecdc..174be53770 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -22,7 +22,7 @@
 #define ASPEED_SOC_DPMCU_SIZE   0x0004
 
 static const hwaddr aspeed_soc_ast2600_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_SRAM]  = 0x1000,
 [ASPEED_DEV_DPMCU] = 0x1800,
 /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index e1a023be53..c60fac900a 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -224,8 +224,6 @@ enum {
 ASPEED_DEV_FSI2,
 };
 
-#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
-
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
 bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
-- 
2.25.1




[PATCH v3 1/2] aspeed: introduce a new UART0 device name

2024-02-14 Thread Jamin Lin via
The Aspeed datasheet refers to the UART controllers
as UART1 - UART13 for the ast10x0, ast2600, ast2500
and ast2400 SoCs and the Aspeed ast2700 introduces an UART0
and the UART controllers as UART0 - UART12.

To keep the naming in the QEMU models
in sync with the datasheet, let's introduce a new  UART0 device name
and do the required adjustements.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 13 -
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  2 ++
 hw/arm/aspeed_ast2600.c |  1 +
 hw/arm/aspeed_soc_common.c  | 10 ++
 include/hw/arm/aspeed_soc.h | 17 +
 6 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 09b1e823ba..aa165d583b 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState 
*bmc)
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
 aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
-for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
 if (uart == uart_chosen) {
 continue;
 }
@@ -1094,7 +1094,7 @@ static char *aspeed_get_bmc_console(Object *obj, Error 
**errp)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
-return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1);
+return g_strdup_printf("uart%d", aspeed_uart_index(uart_chosen));
 }
 
 static void aspeed_set_bmc_console(Object *obj, const char *value, Error 
**errp)
@@ -1103,6 +1103,8 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
 AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
 int val;
+int uart_first = aspeed_uart_first(sc);
+int uart_last = aspeed_uart_last(sc);
 
 if (sscanf(value, "uart%u", ) != 1) {
 error_setg(errp, "Bad value for \"uart\" property");
@@ -1110,11 +1112,12 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 }
 
 /* The number of UART depends on the SoC */
-if (val < 1 || val > sc->uarts_num) {
-error_setg(errp, "\"uart\" should be in range [1 - %d]", 
sc->uarts_num);
+if (val < uart_first || val > uart_last) {
+error_setg(errp, "\"uart\" should be in range [%d - %d]",
+   uart_first, uart_last);
 return;
 }
-bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1;
+bmc->uart_chosen = val + ASPEED_DEV_UART0;
 }
 
 static void aspeed_machine_class_props_init(ObjectClass *oc)
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index c3b5116a6a..2634e0f654 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass 
*klass, void *data)
 sc->wdts_num = 4;
 sc->macs_num = 1;
 sc->uarts_num = 13;
+sc->uarts_base = ASPEED_DEV_UART1;
 sc->irqmap = aspeed_soc_ast1030_irqmap;
 sc->memmap = aspeed_soc_ast1030_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 8829561bb6..95da85fee0 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 2;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2400_irqmap;
 sc->memmap   = aspeed_soc_ast2400_memmap;
 sc->num_cpus = 1;
@@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 3;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2500_irqmap;
 sc->memmap   = aspeed_soc_ast2500_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 4ee32ea99d..f74561ecdc 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 4;
 sc->macs_num = 4;
 sc->uarts_num= 13;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2600_irqmap;
 sc->memmap   = aspeed_soc_ast2600_memmap;
 sc->num_cpus = 2;
diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index 123a0c432c..95d0c0aba9 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -36,7 +36,7 @@ bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 

[PATCH v3 2/2] aspeed: fix hardcode boot address 0

2024-02-14 Thread Jamin Lin via
In the previous design of ASPEED SOCs QEMU model, it set the boot
address at "0" which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has a bootmcu(riscv-32) which
is used for executing SPL and initialize DRAM and copy u-boot image
from SPI/Flash to DRAM at address 0x4 at SPL boot stage.
Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.

Currently, qemu not support emulate two CPU architectures
at the same machine. Therefore, qemu will only support
to emulate CPU(cortex-a35) side for ast2700 and the boot
address is "0x4 ".

Fixed hardcode boot address "0" for future models using
a different mapping address.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 hw/arm/aspeed_ast2400.c | 4 ++--
 hw/arm/aspeed_ast2600.c | 2 +-
 include/hw/arm/aspeed_soc.h | 2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index aa165d583b..9fec245e4e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 95da85fee0..d125886207 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -26,7 +26,7 @@
 #define ASPEED_SOC_IOMEM_SIZE   0x0020
 
 static const hwaddr aspeed_soc_ast2400_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  =  ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
@@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 };
 
 static const hwaddr aspeed_soc_ast2500_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index f74561ecdc..174be53770 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -22,7 +22,7 @@
 #define ASPEED_SOC_DPMCU_SIZE   0x0004
 
 static const hwaddr aspeed_soc_ast2600_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_SRAM]  = 0x1000,
 [ASPEED_DEV_DPMCU] = 0x1800,
 /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index e1a023be53..c60fac900a 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -224,8 +224,6 @@ enum {
 ASPEED_DEV_FSI2,
 };
 
-#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
-
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
 bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
-- 
2.25.1




[PATCH v3 0/2] UART0 device name and fix hardcode boot address 0

2024-02-14 Thread Jamin Lin via
v1:
1. support uart controller both 0 and 1 base
2. fix hardcode boot address 0

v2:
1. introduce a new UART0 device name
2. remove ASPEED_SOC_SPI_BOOT_ADDR marco

v3:
1. add uart helper functions to get the index, start and last.
2. add more description in commit log

Jamin Lin (2):
  aspeed: introduce a new UART0 device name
  aspeed: fix hardcode boot address 0

 hw/arm/aspeed.c | 17 +++--
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  6 --
 hw/arm/aspeed_ast2600.c |  3 ++-
 hw/arm/aspeed_soc_common.c  | 10 ++
 include/hw/arm/aspeed_soc.h | 19 +--
 6 files changed, 41 insertions(+), 15 deletions(-)

-- 
2.25.1




[PATCH v3 2/2] aspeed: fix hardcode boot address 0

2024-02-14 Thread Jamin Lin via
In the previous design of ASPEED SOCs QEMU model, it set the boot
address at "0" which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has a bootmcu(riscv-32) which
is used for executing SPL and initialize DRAM and copy u-boot image
from SPI/Flash to DRAM at address 0x4 at SPL boot stage.
Then, CPUs(cortex-a35) execute u-boot, kernel and rofs.

Currently, qemu not support emulate two CPU architectures
at the same machine. Therefore, qemu will only support
to emulate CPU(cortex-a35) side for ast2700 and the boot
address is "0x4 ".

Fixed hardcode boot address "0" for future models using
a different mapping address.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 hw/arm/aspeed_ast2400.c | 4 ++--
 hw/arm/aspeed_ast2600.c | 2 +-
 include/hw/arm/aspeed_soc.h | 2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index aa165d583b..9fec245e4e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 95da85fee0..d125886207 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -26,7 +26,7 @@
 #define ASPEED_SOC_IOMEM_SIZE   0x0020
 
 static const hwaddr aspeed_soc_ast2400_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  =  ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
@@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 };
 
 static const hwaddr aspeed_soc_ast2500_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index f74561ecdc..174be53770 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -22,7 +22,7 @@
 #define ASPEED_SOC_DPMCU_SIZE   0x0004
 
 static const hwaddr aspeed_soc_ast2600_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_SRAM]  = 0x1000,
 [ASPEED_DEV_DPMCU] = 0x1800,
 /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index e1a023be53..c60fac900a 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -224,8 +224,6 @@ enum {
 ASPEED_DEV_FSI2,
 };
 
-#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
-
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
 bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
-- 
2.25.1




[PATCH v3 1/2] aspeed: introduce a new UART0 device name

2024-02-14 Thread Jamin Lin via
The Aspeed datasheet refers to the UART controllers
as UART1 - UART13 for the ast10x0, ast2600, ast2500
and ast2400 SoCs and the Aspeed ast2700 introduces an UART0
and the UART controllers as UART0 - UART12.

To keep the naming in the QEMU models
in sync with the datasheet, let's introduce a new  UART0 device name
and do the required adjustements.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 13 -
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  2 ++
 hw/arm/aspeed_ast2600.c |  1 +
 hw/arm/aspeed_soc_common.c  | 10 ++
 include/hw/arm/aspeed_soc.h | 17 +
 6 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 09b1e823ba..aa165d583b 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState 
*bmc)
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
 aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
-for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
 if (uart == uart_chosen) {
 continue;
 }
@@ -1094,7 +1094,7 @@ static char *aspeed_get_bmc_console(Object *obj, Error 
**errp)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
-return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1);
+return g_strdup_printf("uart%d", aspeed_uart_index(uart_chosen));
 }
 
 static void aspeed_set_bmc_console(Object *obj, const char *value, Error 
**errp)
@@ -1103,6 +1103,8 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
 AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
 int val;
+int uart_first = aspeed_uart_first(sc);
+int uart_last = aspeed_uart_last(sc);
 
 if (sscanf(value, "uart%u", ) != 1) {
 error_setg(errp, "Bad value for \"uart\" property");
@@ -1110,11 +1112,12 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 }
 
 /* The number of UART depends on the SoC */
-if (val < 1 || val > sc->uarts_num) {
-error_setg(errp, "\"uart\" should be in range [1 - %d]", 
sc->uarts_num);
+if (val < uart_first || val > uart_last) {
+error_setg(errp, "\"uart\" should be in range [%d - %d]",
+   uart_first, uart_last);
 return;
 }
-bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1;
+bmc->uart_chosen = val + ASPEED_DEV_UART0;
 }
 
 static void aspeed_machine_class_props_init(ObjectClass *oc)
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index c3b5116a6a..2634e0f654 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass 
*klass, void *data)
 sc->wdts_num = 4;
 sc->macs_num = 1;
 sc->uarts_num = 13;
+sc->uarts_base = ASPEED_DEV_UART1;
 sc->irqmap = aspeed_soc_ast1030_irqmap;
 sc->memmap = aspeed_soc_ast1030_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 8829561bb6..95da85fee0 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 2;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2400_irqmap;
 sc->memmap   = aspeed_soc_ast2400_memmap;
 sc->num_cpus = 1;
@@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 3;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2500_irqmap;
 sc->memmap   = aspeed_soc_ast2500_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 4ee32ea99d..f74561ecdc 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 4;
 sc->macs_num = 4;
 sc->uarts_num= 13;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2600_irqmap;
 sc->memmap   = aspeed_soc_ast2600_memmap;
 sc->num_cpus = 2;
diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index 123a0c432c..95d0c0aba9 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -36,7 +36,7 @@ bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 

[PATCH v3 0/2] UART0 device name and fix hardcode boot address 0

2024-02-14 Thread Jamin Lin via
v1:
1. support uart controller both 0 and 1 base
2. fix hardcode boot address 0

v2:
1. introduce a new UART0 device name
2. remove ASPEED_SOC_SPI_BOOT_ADDR marco

v3:
1. add uart helper functions to get the index, start and last.
2. add more description in commit log

Jamin Lin (2):
  aspeed: introduce a new UART0 device name
  aspeed: fix hardcode boot address 0

 hw/arm/aspeed.c | 17 +++--
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  6 --
 hw/arm/aspeed_ast2600.c |  3 ++-
 hw/arm/aspeed_soc_common.c  | 10 ++
 include/hw/arm/aspeed_soc.h | 19 +--
 6 files changed, 41 insertions(+), 15 deletions(-)

-- 
2.25.1




[PATCH v2 2/2] aspeed: fix hardcode boot address 0

2024-02-07 Thread Jamin Lin via
In the previous design of ASPEED SOCs QEMU model, it set the boot
address at "0" which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has bootmcu which is used for
executing SPL and initialize DRAM, then, CPUs(cortex-a35)
execute u-boot, kernel and rofs. QEMU will only support CPU(cortex-a35)
parts and the boot address is "0x4 " for ast2700.
Therefore, fixed hardcode boot address 0.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 hw/arm/aspeed_ast2400.c | 4 ++--
 hw/arm/aspeed_ast2600.c | 2 +-
 include/hw/arm/aspeed_soc.h | 2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 06d863958b..39758557be 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 95da85fee0..d125886207 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -26,7 +26,7 @@
 #define ASPEED_SOC_IOMEM_SIZE   0x0020
 
 static const hwaddr aspeed_soc_ast2400_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  =  ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
@@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 };
 
 static const hwaddr aspeed_soc_ast2500_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index f74561ecdc..174be53770 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -22,7 +22,7 @@
 #define ASPEED_SOC_DPMCU_SIZE   0x0004
 
 static const hwaddr aspeed_soc_ast2600_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_SRAM]  = 0x1000,
 [ASPEED_DEV_DPMCU] = 0x1800,
 /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 5ab0902da0..bf43ad8351 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -224,8 +224,6 @@ enum {
 ASPEED_DEV_FSI2,
 };
 
-#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
-
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
 bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
-- 
2.25.1




[PATCH v2 1/2] aspeed: introduce a new UART0 device name

2024-02-07 Thread Jamin Lin via
The Aspeed datasheet refers to the UART controllers
as UART1 - UART13 for the ast10x0, ast2600, ast2500
and ast2400 SoCs and the Aspeed ast2700 introduces an UART0
and the UART controllers as UART0 - UART12.

To keep the naming in the QEMU models
in sync with the datasheet, let's introduce a new  UART0 device name
and do the required adjustements, etc ...

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 13 -
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  2 ++
 hw/arm/aspeed_ast2600.c |  1 +
 hw/arm/aspeed_soc_common.c  | 14 +-
 include/hw/arm/aspeed_soc.h |  2 ++
 6 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 09b1e823ba..06d863958b 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState 
*bmc)
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
 aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
-for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
 if (uart == uart_chosen) {
 continue;
 }
@@ -1094,7 +1094,7 @@ static char *aspeed_get_bmc_console(Object *obj, Error 
**errp)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
-return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1);
+return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART0);
 }
 
 static void aspeed_set_bmc_console(Object *obj, const char *value, Error 
**errp)
@@ -1103,6 +1103,8 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
 AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
 int val;
+int start = sc->uarts_base - ASPEED_DEV_UART0;
+int end = start + sc->uarts_num;
 
 if (sscanf(value, "uart%u", ) != 1) {
 error_setg(errp, "Bad value for \"uart\" property");
@@ -1110,11 +1112,12 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 }
 
 /* The number of UART depends on the SoC */
-if (val < 1 || val > sc->uarts_num) {
-error_setg(errp, "\"uart\" should be in range [1 - %d]", 
sc->uarts_num);
+if (val < start || val >= end) {
+error_setg(errp, "\"uart\" should be in range [%d - %d]",
+   start, end - 1);
 return;
 }
-bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1;
+bmc->uart_chosen = val + ASPEED_DEV_UART0;
 }
 
 static void aspeed_machine_class_props_init(ObjectClass *oc)
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index c3b5116a6a..2634e0f654 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass 
*klass, void *data)
 sc->wdts_num = 4;
 sc->macs_num = 1;
 sc->uarts_num = 13;
+sc->uarts_base = ASPEED_DEV_UART1;
 sc->irqmap = aspeed_soc_ast1030_irqmap;
 sc->memmap = aspeed_soc_ast1030_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 8829561bb6..95da85fee0 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 2;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2400_irqmap;
 sc->memmap   = aspeed_soc_ast2400_memmap;
 sc->num_cpus = 1;
@@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 3;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2500_irqmap;
 sc->memmap   = aspeed_soc_ast2500_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 4ee32ea99d..f74561ecdc 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 4;
 sc->macs_num = 4;
 sc->uarts_num= 13;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2600_irqmap;
 sc->memmap   = aspeed_soc_ast2600_memmap;
 sc->num_cpus = 2;
diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index 123a0c432c..54c875c8d5 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -36,7 +36,7 @@ bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 SerialMM *smm;
 
-

[PATCH v2 2/2] aspeed: fix hardcode boot address 0

2024-02-07 Thread Jamin Lin via
In the previous design of ASPEED SOCs QEMU model, it set the boot
address at "0" which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has bootmcu which is used for
executing SPL and initialize DRAM, then, CPUs(cortex-a35)
execute u-boot, kernel and rofs. QEMU will only support CPU(cortex-a35)
parts and the boot address is "0x4 " for ast2700.
Therefore, fixed hardcode boot address 0.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 hw/arm/aspeed_ast2400.c | 4 ++--
 hw/arm/aspeed_ast2600.c | 2 +-
 include/hw/arm/aspeed_soc.h | 2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 06d863958b..39758557be 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 95da85fee0..d125886207 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -26,7 +26,7 @@
 #define ASPEED_SOC_IOMEM_SIZE   0x0020
 
 static const hwaddr aspeed_soc_ast2400_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  =  ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
@@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 };
 
 static const hwaddr aspeed_soc_ast2500_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_IOMEM]  = 0x1E60,
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index f74561ecdc..174be53770 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -22,7 +22,7 @@
 #define ASPEED_SOC_DPMCU_SIZE   0x0004
 
 static const hwaddr aspeed_soc_ast2600_memmap[] = {
-[ASPEED_DEV_SPI_BOOT]  = ASPEED_SOC_SPI_BOOT_ADDR,
+[ASPEED_DEV_SPI_BOOT]  = 0x,
 [ASPEED_DEV_SRAM]  = 0x1000,
 [ASPEED_DEV_DPMCU] = 0x1800,
 /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 5ab0902da0..bf43ad8351 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -224,8 +224,6 @@ enum {
 ASPEED_DEV_FSI2,
 };
 
-#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
-
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
 bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
-- 
2.25.1




[PATCH v0 1/2] aspeed: support uart controller both 0 and 1 base

2024-02-05 Thread Jamin Lin via
According to the design of ASPEED SOCS, the uart controller
is 1 base for ast10x0, ast2600, ast2500 and ast2400.

However, the uart controller is 0 base for ast2700.
To support uart controller both 0 and 1 base,
adds uasrt_bases parameter in AspeedSoCClass
and set the default uart controller 1 base
for ast10x0, astt2600, ast2500 and ast2400.

>From datasheet description
ast2700:
Base Address of UART0 = 0x14c33000
ast1030:
Base Address of UART1 = 0x7e783000
ast2600:
Base Address of UART1 = 0x1E78 3000
ast2500:
Base Address of UART1 = 0x1E78 3000

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 8 +---
 hw/arm/aspeed_ast10x0.c | 1 +
 hw/arm/aspeed_ast2400.c | 2 ++
 hw/arm/aspeed_ast2600.c | 1 +
 hw/arm/aspeed_soc_common.c  | 4 ++--
 include/hw/arm/aspeed_soc.h | 1 +
 6 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 09b1e823ba..218b81298e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState 
*bmc)
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
 aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
-for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
 if (uart == uart_chosen) {
 continue;
 }
@@ -1092,9 +1092,11 @@ static char *aspeed_get_bmc_console(Object *obj, Error 
**errp)
 {
 AspeedMachineState *bmc = ASPEED_MACHINE(obj);
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
+AspeedSoCClass *sc = ASPEED_SOC_CLASS(obj);
+
 int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
 
-return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1);
+return g_strdup_printf("uart%d", uart_chosen - sc->uarts_base + 1);
 }
 
 static void aspeed_set_bmc_console(Object *obj, const char *value, Error 
**errp)
@@ -1114,7 +1116,7 @@ static void aspeed_set_bmc_console(Object *obj, const 
char *value, Error **errp)
 error_setg(errp, "\"uart\" should be in range [1 - %d]", 
sc->uarts_num);
 return;
 }
-bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1;
+bmc->uart_chosen = sc->uarts_base + val - 1;
 }
 
 static void aspeed_machine_class_props_init(ObjectClass *oc)
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index c3b5116a6a..2634e0f654 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass 
*klass, void *data)
 sc->wdts_num = 4;
 sc->macs_num = 1;
 sc->uarts_num = 13;
+sc->uarts_base = ASPEED_DEV_UART1;
 sc->irqmap = aspeed_soc_ast1030_irqmap;
 sc->memmap = aspeed_soc_ast1030_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 8829561bb6..95da85fee0 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 2;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2400_irqmap;
 sc->memmap   = aspeed_soc_ast2400_memmap;
 sc->num_cpus = 1;
@@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 3;
 sc->macs_num = 2;
 sc->uarts_num= 5;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2500_irqmap;
 sc->memmap   = aspeed_soc_ast2500_memmap;
 sc->num_cpus = 1;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 4ee32ea99d..f74561ecdc 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, 
void *data)
 sc->wdts_num = 4;
 sc->macs_num = 4;
 sc->uarts_num= 13;
+sc->uarts_base   = ASPEED_DEV_UART1;
 sc->irqmap   = aspeed_soc_ast2600_irqmap;
 sc->memmap   = aspeed_soc_ast2600_memmap;
 sc->num_cpus = 2;
diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index 123a0c432c..3963436c3a 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -36,7 +36,7 @@ bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 SerialMM *smm;
 
-for (int i = 0, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
 smm = >uart[i];
 
 /* Chardev property is set by the machine. */
@@ -58,7 +58,7 @@ bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
 void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr)
 {
 AspeedSoCClass *sc = 

[PATCH v0 2/2] aspeed: fix hardcode boot address 0

2024-02-05 Thread Jamin Lin via
In the previous design of QEMU model for ASPEED SOCs, it set the boot
address at 0 which was the hardcode setting for ast10x0, ast2600,
ast2500 and ast2400.

According to the design of ast2700, it has bootmcu which is used for
executing SPL and initialize DRAM, then, CPUs(cortex-a35)
execute u-boot, kernel and rofs. QEMU will only support CPU(coretax-a35)
parts and the boot address is "0x4" for ast2700.
Therefore, fixed hardcode boot address 0.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
---
 hw/arm/aspeed.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 218b81298e..82a92e8142 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState 
*bmc, BlockBackend *blk,
 uint64_t rom_size)
 {
 AspeedSoCState *soc = bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
 
 memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
_abort);
 memory_region_add_subregion_overlap(>spi_boot_container, 0,
 >boot_rom, 1);
-write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
+write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT],
+   rom_size, _abort);
 }
 
 void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
-- 
2.34.1




[v0 0/2] uart base and hardcode boot address 0

2024-02-05 Thread Jamin Lin via
v0:
1. support uart controller both 0 and 1 base
2. fix hardcode boot address 0

Jamin Lin (2):
  aspeed: support uart controller both 0 and 1 base
  aspeed: fix hardcode boot address 0

 hw/arm/aspeed.c | 12 
 hw/arm/aspeed_ast10x0.c |  1 +
 hw/arm/aspeed_ast2400.c |  2 ++
 hw/arm/aspeed_ast2600.c |  1 +
 hw/arm/aspeed_soc_common.c  |  4 ++--
 include/hw/arm/aspeed_soc.h |  1 +
 6 files changed, 15 insertions(+), 6 deletions(-)

-- 
2.34.1