:p
atchew
Login
The following changes since commit c77283dd5d79149f4e7e9edd00f65416c648ee59: Merge tag 'pull-request-2025-07-02' of https://gitlab.com/thuth/qemu into staging (2025-07-03 06:01:41 -0400) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-aspeed-20250704 for you to fetch changes up to 3a34dad2c0d25cebafed40696bbbdeb7ff4b9c7d: tests/functional: Add gb200 tests (2025-07-03 17:36:45 +0200) ---------------------------------------------------------------- aspeed queue: * Improved AST2700 SoC modeling (SDMC, SCU) * Fixed hardware strapping of 'bletchley-bmc' machine * Added new Meta 'catalina-bmc' machine and functional test using OpenBMC * Improved AST2600 SCU protection key modeling * Introduced AST2600 SCU unit tests * Deprecated 'ast2700a0-evb' machine * Added new NVIDIA 'gb200-bmc' machine and functional test using OpenBMC ---------------------------------------------------------------- Ed Tanous (4): hw/arm/aspeed: Add second SPI chip to Aspeed model docs: add support for gb200-bmc hw/arm/aspeed: Add GB200 BMC target tests/functional: Add gb200 tests Jamin Lin (3): hw/misc/aspeed_sdmc: Skipping dram_init in u-boot for AST2700 hw/misc/aspeed_scu: Support the Frequency Counter Control register for AST2700 aspeed: Deprecate the ast2700a0-evb machine Patrick Williams (2): hw/arm/aspeed: bletchley: update hw strap values hw/arm/aspeed: add Catalina machine type Tan Siewert (2): hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly tests/qtest: Add test for ASPEED SCU docs/about/deprecated.rst | 8 + docs/system/arm/aspeed.rst | 4 +- hw/arm/aspeed_eeprom.h | 3 + include/hw/arm/aspeed.h | 2 + hw/arm/aspeed.c | 285 ++++++++++++++++++++++- hw/arm/aspeed_eeprom.c | 21 ++ hw/misc/aspeed_scu.c | 22 +- hw/misc/aspeed_sdmc.c | 3 + tests/qtest/aspeed_scu-test.c | 231 ++++++++++++++++++ hw/arm/Kconfig | 1 + tests/functional/aspeed.py | 9 +- tests/functional/meson.build | 4 + tests/functional/test_arm_aspeed_catalina.py | 25 ++ tests/functional/test_arm_aspeed_gb200nvl_bmc.py | 26 +++ tests/qtest/meson.build | 1 + 15 files changed, 636 insertions(+), 9 deletions(-) create mode 100644 tests/qtest/aspeed_scu-test.c create mode 100755 tests/functional/test_arm_aspeed_catalina.py create mode 100644 tests/functional/test_arm_aspeed_gb200nvl_bmc.py
From: Jamin Lin <jamin_lin@aspeedtech.com> On AST2700 SoC, QEMU now sets BIT6 in VGA0 SCRATCH register to indicate that DDR training has completed, thus skipping the dram_init(). To align with the recent U-Boot changes, where the Main Control Register's BIT16 is checked to skip the dram_init() process, this patch sets BIT16 in the SDMC Main Control Register at reset time. This allows both the main U-Boot stage to correctly detect and bypass DRAM initialization when running under QEMU. Reference: - QEMU: https://github.com/qemu/qemu/commit/2d082fea485ee455a70ed3e963cdf9a70f34858a - U-Boot: https://github.com/AspeedTech-BMC/u-boot/commit/94e5435504fb0d8888f5c1bfd3fa284cdd6aaf9b Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250618080006.846355-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/misc/aspeed_sdmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -XXX,XX +XXX,XX @@ static void aspeed_2700_sdmc_reset(DeviceState *dev) /* Set ram size bit and defaults values */ s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0); + /* Skipping dram init */ + s->regs[R_MAIN_CONTROL] = BIT(16); + if (s->unlocked) { s->regs[R_2700_PROT] = PROT_UNLOCKED; } -- 2.50.0
From: Jamin Lin <jamin_lin@aspeedtech.com> According to the datasheet: BIT[1] (SCU_FREQ_OSC_EN) enables the oscillator frequency measurement counter. BIT[6] (SCU_FREQ_DONE) indicates the measurement is finished. Firmware polls BIT[6] to determine when measurement is complete. The flag can be cleared by writing BIT[1] to 0. To simulate this hardware behavior in QEMU: If BIT[1] is set to 1, BIT[6] is immediately set to 1 to avoid firmware hanging during polling. If BIT[1] is cleared to 0, BIT[6] is also cleared to 0 to match hardware semantics. The initial value of this register is initialized to 0x80, reflecting the default value confirmed from an EVB register dump. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250618080006.846355-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/misc/aspeed_scu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -XXX,XX +XXX,XX @@ #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 AST2700_SCUIO_FREQ_CNT_CTL TO_REG(0x3A0) #define SCU_IO_REGION_SIZE 0x1000 @@ -XXX,XX +XXX,XX @@ static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset, s->regs[reg - 1] ^= data; updated = true; break; + case AST2700_SCUIO_FREQ_CNT_CTL: + s->regs[reg] = deposit32(s->regs[reg], 6, 1, !!(data & BIT(1))); + updated = true; + break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n", @@ -XXX,XX +XXX,XX @@ static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = { [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506, [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0, [AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2, + [AST2700_SCUIO_FREQ_CNT_CTL] = 0x00000080, }; static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data) -- 2.50.0
From: Patrick Williams <patrick@stwcx.xyz> Update the Bletchley hardware strap register values per actual hardware: ``` root@bmc:~# devmem 0x1e6e2500 0x00002000 root@bmc:~# devmem 0x1e6e2510 0x00000801 ``` Signed-off-by: Patrick Williams <patrick@stwcx.xyz> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250619035850.2682690-1-patrick@stwcx.xyz Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -XXX,XX +XXX,XX @@ struct AspeedMachineState { #define FUJI_BMC_HW_STRAP2 0x00000000 /* Bletchley hardware value */ -/* TODO: Leave same as EVB for now. */ -#define BLETCHLEY_BMC_HW_STRAP1 AST2600_EVB_HW_STRAP1 -#define BLETCHLEY_BMC_HW_STRAP2 AST2600_EVB_HW_STRAP2 +#define BLETCHLEY_BMC_HW_STRAP1 0x00002000 +#define BLETCHLEY_BMC_HW_STRAP2 0x00000801 /* Qualcomm DC-SCM hardware value */ #define QCOM_DC_SCM_V1_BMC_HW_STRAP1 0x00000000 -- 2.50.0
From: Patrick Williams <patrick@stwcx.xyz> Add the 'catalina-bmc' machine type based on the kernel DTS[1] as of 6.16-rc2. The i2c model is as complete as the current QEMU models support, but in some cases I substituted devices that are close enough for present functionality. Strap registers are were verified with hardware. This has been tested with an openbmc image built from [2]. Add a functional test in line with Bletchley, pointing at an image obtained from the OpenBMC Jenkins server. [1]: https://github.com/torvalds/linux/blob/v6.16-rc2/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts [2]: https://github.com/openbmc/openbmc/commit/5bc73ec261f981d5e586bda5ac78eb0cbd5f92b0 Signed-off-by: Patrick Williams <patrick@stwcx.xyz> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250619151458.2831859-1-patrick@stwcx.xyz Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed.c | 200 +++++++++++++++++++ hw/arm/Kconfig | 1 + tests/functional/meson.build | 2 + tests/functional/test_arm_aspeed_catalina.py | 25 +++ 4 files changed, 228 insertions(+) create mode 100755 tests/functional/test_arm_aspeed_catalina.py diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -XXX,XX +XXX,XX @@ #include "hw/i2c/i2c_mux_pca954x.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/gpio/pca9552.h" +#include "hw/gpio/pca9554.h" #include "hw/nvram/eeprom_at24c.h" #include "hw/sensor/tmp105.h" #include "hw/misc/led.h" @@ -XXX,XX +XXX,XX @@ static void fuji_bmc_i2c_init(AspeedMachineState *bmc) } #define TYPE_TMP421 "tmp421" +#define TYPE_DS1338 "ds1338" + +/* Catalina hardware value */ +#define CATALINA_BMC_HW_STRAP1 0x00002002 +#define CATALINA_BMC_HW_STRAP2 0x00000800 + +#define CATALINA_BMC_RAM_SIZE ASPEED_RAM_SIZE(2 * GiB) + +static void catalina_bmc_i2c_init(AspeedMachineState *bmc) +{ + /* Reference from v6.16-rc2 aspeed-bmc-facebook-catalina.dts */ + + AspeedSoCState *soc = bmc->soc; + I2CBus *i2c[16] = {}; + I2CSlave *i2c_mux; + + /* busses 0-15 are all used. */ + for (int i = 0; i < ARRAY_SIZE(i2c); i++) { + i2c[i] = aspeed_i2c_get_bus(&soc->i2c, i); + } + + /* &i2c0 */ + /* i2c-mux@71 (PCA9546) on i2c0 */ + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); + + /* i2c-mux@72 (PCA9546) on i2c0 */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); + + /* i2c0mux1ch1 */ + /* io_expander7 - pca9535@20 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), + TYPE_PCA9552, 0x20); + /* eeprom@50 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x50, 8 * KiB); + + /* i2c-mux@73 (PCA9546) on i2c0 */ + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); + + /* i2c-mux@75 (PCA9546) on i2c0 */ + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); + + /* i2c-mux@76 (PCA9546) on i2c0 */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); + + /* i2c0mux4ch1 */ + /* io_expander8 - pca9535@21 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), + TYPE_PCA9552, 0x21); + /* eeprom@50 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x50, 8 * KiB); + + /* i2c-mux@77 (PCA9546) on i2c0 */ + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); + + + /* &i2c1 */ + /* i2c-mux@70 (PCA9548) on i2c1 */ + i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); + /* i2c1mux0ch0 */ + /* ina238@41 - no model */ + /* ina238@42 - no model */ + /* ina238@44 - no model */ + /* i2c1mux0ch1 */ + /* ina238@41 - no model */ + /* ina238@43 - no model */ + /* i2c1mux0ch4 */ + /* ltc4287@42 - no model */ + /* ltc4287@43 - no model */ + + /* i2c1mux0ch5 */ + /* eeprom@54 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); + /* tpm75@4f */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); + + /* i2c1mux0ch6 */ + /* io_expander5 - pca9554@27 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), + TYPE_PCA9554, 0x27); + /* io_expander6 - pca9555@25 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), + TYPE_PCA9552, 0x25); + /* eeprom@51 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 6), 0x51, 8 * KiB); + + /* i2c1mux0ch7 */ + /* eeprom@53 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x53, 8 * KiB); + /* temperature-sensor@4b - tmp75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); + + /* &i2c2 */ + /* io_expander0 - pca9555@20 */ + i2c_slave_create_simple(i2c[2], TYPE_PCA9552, 0x20); + /* io_expander0 - pca9555@21 */ + i2c_slave_create_simple(i2c[2], TYPE_PCA9552, 0x21); + /* io_expander0 - pca9555@27 */ + i2c_slave_create_simple(i2c[2], TYPE_PCA9552, 0x27); + /* eeprom@50 */ + at24c_eeprom_init(i2c[2], 0x50, 8 * KiB); + /* eeprom@51 */ + at24c_eeprom_init(i2c[2], 0x51, 8 * KiB); + + /* &i2c5 */ + /* i2c-mux@70 (PCA9548) on i2c5 */ + i2c_mux = i2c_slave_create_simple(i2c[5], TYPE_PCA9548, 0x70); + /* i2c5mux0ch6 */ + /* eeprom@52 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 6), 0x52, 8 * KiB); + /* i2c5mux0ch7 */ + /* ina230@40 - no model */ + /* ina230@41 - no model */ + /* ina230@44 - no model */ + /* ina230@45 - no model */ + + /* &i2c6 */ + /* io_expander3 - pca9555@21 */ + i2c_slave_create_simple(i2c[6], TYPE_PCA9552, 0x21); + /* rtc@6f - nct3018y */ + i2c_slave_create_simple(i2c[6], TYPE_DS1338, 0x6f); + + /* &i2c9 */ + /* io_expander4 - pca9555@4f */ + i2c_slave_create_simple(i2c[9], TYPE_PCA9552, 0x4f); + /* temperature-sensor@4b - tpm75 */ + i2c_slave_create_simple(i2c[9], TYPE_TMP75, 0x4b); + /* eeprom@50 */ + at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); + /* eeprom@56 */ + at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); + + /* &i2c10 */ + /* temperature-sensor@1f - tpm421 */ + i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); + /* eeprom@50 */ + at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); + + /* &i2c11 */ + /* ssif-bmc@10 - no model */ + + /* &i2c12 */ + /* eeprom@50 */ + at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); + + /* &i2c13 */ + /* eeprom@50 */ + at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); + /* eeprom@54 */ + at24c_eeprom_init(i2c[13], 0x54, 256); + /* eeprom@55 */ + at24c_eeprom_init(i2c[13], 0x55, 256); + /* eeprom@57 */ + at24c_eeprom_init(i2c[13], 0x57, 256); + + /* &i2c14 */ + /* io_expander9 - pca9555@10 */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9552, 0x10); + /* io_expander10 - pca9555@11 */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9552, 0x11); + /* io_expander11 - pca9555@12 */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9552, 0x12); + /* io_expander12 - pca9555@13 */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9552, 0x13); + /* io_expander13 - pca9555@14 */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9552, 0x14); + /* io_expander14 - pca9555@15 */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9552, 0x15); + + /* &i2c15 */ + /* temperature-sensor@1f - tmp421 */ + i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); + /* eeprom@52 */ + at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); +} static void bletchley_bmc_i2c_init(AspeedMachineState *bmc) { @@ -XXX,XX +XXX,XX @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc, aspeed_machine_class_init_cpus_defaults(mc); } +static void aspeed_machine_catalina_class_init(ObjectClass *oc, + const void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook Catalina BMC (Cortex-A7)"; + amc->soc_name = "ast2600-a3"; + amc->hw_strap1 = CATALINA_BMC_HW_STRAP1; + amc->hw_strap2 = CATALINA_BMC_HW_STRAP2; + amc->fmc_model = "w25q01jvq"; + amc->spi_model = NULL; + amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC2_ON; + amc->i2c_init = catalina_bmc_i2c_init; + mc->auto_create_sdcard = true; + mc->default_ram_size = CATALINA_BMC_RAM_SIZE; + aspeed_machine_class_init_cpus_defaults(mc); + aspeed_machine_ast2600_class_emmc_init(oc); +} + static void fby35_reset(MachineState *state, ResetType type) { AspeedMachineState *bmc = ASPEED_MACHINE(state); @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = { .name = MACHINE_TYPE_NAME("bletchley-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_bletchley_class_init, + }, { + .name = MACHINE_TYPE_NAME("catalina-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_catalina_class_init, }, { .name = MACHINE_TYPE_NAME("fby35-bmc"), .parent = MACHINE_TYPE_NAME("ast2600-evb"), diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -XXX,XX +XXX,XX @@ config ASPEED_SOC select I2C select DPS310 select PCA9552 + select PCA9554 select SERIAL_MM select SMBUS_EEPROM select PCA954X diff --git a/tests/functional/meson.build b/tests/functional/meson.build index XXXXXXX..XXXXXXX 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -XXX,XX +XXX,XX @@ test_timeouts = { 'arm_aspeed_ast2500' : 720, 'arm_aspeed_ast2600' : 1200, 'arm_aspeed_bletchley' : 480, + 'arm_aspeed_catalina' : 480, 'arm_aspeed_rainier' : 480, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -XXX,XX +XXX,XX @@ tests_arm_system_thorough = [ 'arm_aspeed_ast2500', 'arm_aspeed_ast2600', 'arm_aspeed_bletchley', + 'arm_aspeed_catalina', 'arm_aspeed_rainier', 'arm_bpim2u', 'arm_canona1100', diff --git a/tests/functional/test_arm_aspeed_catalina.py b/tests/functional/test_arm_aspeed_catalina.py new file mode 100755 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_catalina.py @@ -XXX,XX +XXX,XX @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class CatalinaMachine(AspeedTest): + + ASSET_CATALINA_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz', + '287402e1ba021991e06be1d098f509444a02a3d81a73a932f66528b159e864f9') + + def test_arm_ast2600_catalina_openbmc(self): + image_path = self.uncompress(self.ASSET_CATALINA_FLASH) + + self.do_test_arm_aspeed_openbmc('catalina-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3') + +if __name__ == '__main__': + AspeedTest.main() -- 2.50.0
From: Tan Siewert <tan@siewert.io> The AST2600 SCU has two protection key registers (0x00 and 0x10) that both need to be unlocked. (Un-)locking 0x00 modifies both protection key registers, while modifying 0x10 only modifies itself. This commit updates the SCU write logic to reject writes unless both protection key registers are unlocked, matching the behaviour of real hardware. Signed-off-by: Tan Siewert <tan@siewert.io> Reviewed-by: Jamin Lin <jamin_lin@aspeedtech.com> Link: https://lore.kernel.org/qemu-devel/20250619085329.42125-1-tan@siewert.io Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/misc/aspeed_scu.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -XXX,XX +XXX,XX @@ #define BMC_DEV_ID TO_REG(0x1A4) #define AST2600_PROT_KEY TO_REG(0x00) +#define AST2600_PROT_KEY2 TO_REG(0x10) #define AST2600_SILICON_REV TO_REG(0x04) #define AST2600_SILICON_REV2 TO_REG(0x14) #define AST2600_SYS_RST_CTRL TO_REG(0x40) @@ -XXX,XX +XXX,XX @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, int reg = TO_REG(offset); /* Truncate here so bitwise operations below behave as expected */ uint32_t data = data64; + bool prot_data_state = data == ASPEED_SCU_PROT_KEY; + bool unlocked = s->regs[AST2600_PROT_KEY] && s->regs[AST2600_PROT_KEY2]; if (reg >= ASPEED_AST2600_SCU_NR_REGS) { qemu_log_mask(LOG_GUEST_ERROR, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, return; } - if (reg > PROT_KEY && !s->regs[PROT_KEY]) { + if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && !unlocked) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__); + return; } trace_aspeed_scu_write(offset, size, data); switch (reg) { case AST2600_PROT_KEY: - s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0; + /* + * Writing a value to SCU000 will modify both protection + * registers to each protection register individually. + */ + s->regs[AST2600_PROT_KEY] = prot_data_state; + s->regs[AST2600_PROT_KEY2] = prot_data_state; + return; + case AST2600_PROT_KEY2: + s->regs[AST2600_PROT_KEY2] = prot_data_state; return; case AST2600_HW_STRAP1: case AST2600_HW_STRAP2: -- 2.50.0
From: Tan Siewert <tan@siewert.io> This adds basic tests for the ASPEED System Control Unit (SCU) and its protection mechanism on the AST2500 and AST2600 platforms. The tests verify: - That SCU protection registers can be unlocked and locked again - That modifying the primary protection register on AST2600 also affects the secondary one - That writes to protected SCU registers are blocked unless protection registers are unlocked explicitly These tests ensure proper emulation of hardware locking behaviour and help catch regressions in SCU access logic. Signed-off-by: Tan Siewert <tan@siewert.io> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250630112646.74944-1-tan@siewert.io [ clg: Reordered file list in meson.build ] Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_scu-test.c | 231 ++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 1 + 2 files changed, 232 insertions(+) create mode 100644 tests/qtest/aspeed_scu-test.c diff --git a/tests/qtest/aspeed_scu-test.c b/tests/qtest/aspeed_scu-test.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/qtest/aspeed_scu-test.c @@ -XXX,XX +XXX,XX @@ +/* + * QTest testcase for the ASPEED AST2500 and AST2600 SCU. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2025 Tan Siewert + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* + * SCU base, as well as protection key are + * the same on AST2500 and 2600. + */ +#define AST_SCU_BASE 0x1E6E2000 +#define AST_SCU_PROT_LOCK_STATE 0x0 +#define AST_SCU_PROT_LOCK_VALUE 0x2 +#define AST_SCU_PROT_UNLOCK_STATE 0x1 +#define AST_SCU_PROT_UNLOCK_VALUE 0x1688A8A8 + +#define AST2500_MACHINE "-machine ast2500-evb" +#define AST2500_SCU_PROT_REG 0x00 +#define AST2500_SCU_MISC_2_CONTROL_REG 0x4C + +#define AST2600_MACHINE "-machine ast2600-evb" +/* AST2600 has two protection registers */ +#define AST2600_SCU_PROT_REG 0x000 +#define AST2600_SCU_PROT_REG2 0x010 +#define AST2600_SCU_MISC_2_CONTROL_REG 0x0C4 + +#define TEST_LOCK_ARBITRARY_VALUE 0xABCDEFAB + +/** + * Assert that a given register matches an expected value. + * + * Reads the register and checks if its value equals the expected value. + * + * @param *s - QTest machine state + * @param reg - Address of the register to be checked + * @param expected - Expected register value + */ +static inline void assert_register_eq(QTestState *s, + uint32_t reg, + uint32_t expected) +{ + uint32_t value = qtest_readl(s, reg); + g_assert_cmphex(value, ==, expected); +} + +/** + * Assert that a given register does not match a specific value. + * + * Reads the register and checks that its value is not equal to the + * provided value. + * + * @param *s - QTest machine state + * @param reg - Address of the register to be checked + * @param not_expected - Value the register must not contain + */ +static inline void assert_register_neq(QTestState *s, + uint32_t reg, + uint32_t not_expected) +{ + uint32_t value = qtest_readl(s, reg); + g_assert_cmphex(value, !=, not_expected); +} + +/** + * Test whether the SCU can be locked and unlocked correctly. + * + * When testing multiple registers, this function assumes that writing + * to the first register also affects the others. However, writing to + * any other register only affects itself. + * + * @param *machine - input machine configuration, passed directly + * to QTest + * @param regs[] - List of registers to be checked + * @param regc - amount of arguments for registers to be checked + */ +static void test_protection_register(const char *machine, + const uint32_t regs[], + const int regc) +{ + QTestState *s = qtest_init(machine); + + for (int i = 0; i < regc; i++) { + uint32_t reg = regs[i]; + + qtest_writel(s, reg, AST_SCU_PROT_UNLOCK_VALUE); + assert_register_eq(s, reg, AST_SCU_PROT_UNLOCK_STATE); + + /** + * Check that other registers are unlocked too, if more + * than one is available. + */ + if (regc > 1 && i == 0) { + /* Initialise at 1 instead of 0 to skip first */ + for (int j = 1; j < regc; j++) { + uint32_t add_reg = regs[j]; + assert_register_eq(s, add_reg, AST_SCU_PROT_UNLOCK_STATE); + } + } + + /* Lock the register again */ + qtest_writel(s, reg, AST_SCU_PROT_LOCK_VALUE); + assert_register_eq(s, reg, AST_SCU_PROT_LOCK_STATE); + + /* And the same for locked state */ + if (regc > 1 && i == 0) { + /* Initialise at 1 instead of 0 to skip first */ + for (int j = 1; j < regc; j++) { + uint32_t add_reg = regs[j]; + assert_register_eq(s, add_reg, AST_SCU_PROT_LOCK_STATE); + } + } + } + + qtest_quit(s); +} + +static void test_2500_protection_register(void) +{ + uint32_t regs[] = { AST_SCU_BASE + AST2500_SCU_PROT_REG }; + + test_protection_register(AST2500_MACHINE, + regs, + ARRAY_SIZE(regs)); +} + +static void test_2600_protection_register(void) +{ + /** + * The AST2600 has two protection registers, both + * being required to be unlocked to do any operation. + * + * Modifying SCU000 also modifies SCU010, but modifying + * SCU010 only will keep SCU000 untouched. + */ + uint32_t regs[] = { AST_SCU_BASE + AST2600_SCU_PROT_REG, + AST_SCU_BASE + AST2600_SCU_PROT_REG2 }; + + test_protection_register(AST2600_MACHINE, + regs, + ARRAY_SIZE(regs)); +} + +/** + * Test if SCU register writes are correctly allowed or blocked + * depending on the protection register state. + * + * The test first locks the protection register and verifies that + * writes to the target SCU register are rejected. It then unlocks + * the protection register and confirms that the written value is + * retained when unlocked. + * + * @param *machine - input machine configuration, passed directly + * to QTest + * @param protection_register - first SCU protection key register + * (only one for keeping it simple) + * @param test_register - Register to be used for writing arbitrary + * values + */ +static void test_write_permission_lock_state(const char *machine, + const uint32_t protection_register, + const uint32_t test_register) +{ + QTestState *s = qtest_init(machine); + + /* Arbitrary value to lock provided SCU protection register */ + qtest_writel(s, protection_register, AST_SCU_PROT_LOCK_VALUE); + + /* Ensure that the SCU is really locked */ + assert_register_eq(s, protection_register, AST_SCU_PROT_LOCK_STATE); + + /* Write a known arbitrary value to test that the write is blocked */ + qtest_writel(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + /* We do not want to have the written value to be saved */ + assert_register_neq(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + /** + * Unlock the SCU and verify that it can be written to. + * Assumes that the first SCU protection register is sufficient to + * unlock all protection registers, if multiple are present. + */ + qtest_writel(s, protection_register, AST_SCU_PROT_UNLOCK_VALUE); + assert_register_eq(s, protection_register, AST_SCU_PROT_UNLOCK_STATE); + + /* Write a known arbitrary value to test that the write works */ + qtest_writel(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + /* Ensure that the written value is retained */ + assert_register_eq(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + qtest_quit(s); +} + +static void test_2500_write_permission_lock_state(void) +{ + test_write_permission_lock_state( + AST2500_MACHINE, + AST_SCU_BASE + AST2500_SCU_PROT_REG, + AST_SCU_BASE + AST2500_SCU_MISC_2_CONTROL_REG + ); +} + +static void test_2600_write_permission_lock_state(void) +{ + test_write_permission_lock_state( + AST2600_MACHINE, + AST_SCU_BASE + AST2600_SCU_PROT_REG, + AST_SCU_BASE + AST2600_SCU_MISC_2_CONTROL_REG + ); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/ast2500/scu/protection_register", + test_2500_protection_register); + qtest_add_func("/ast2600/scu/protection_register", + test_2600_protection_register); + + qtest_add_func("/ast2500/scu/write_permission_lock_state", + test_2500_write_permission_lock_state); + qtest_add_func("/ast2600/scu/write_permission_lock_state", + test_2600_write_permission_lock_state); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -XXX,XX +XXX,XX @@ qtests_npcm8xx = \ qtests_aspeed = \ ['aspeed_gpio-test', 'aspeed_hace-test', + 'aspeed_scu-test', 'aspeed_smc-test'] qtests_aspeed64 = \ ['ast2700-gpio-test', -- 2.50.0
From: Jamin Lin <jamin_lin@aspeedtech.com> The ast2700a0-evb machine represents the first revision of the AST2700 and serves as the initial engineering sample rather than a production version. A newer revision, A1, is now supported, and the ast2700a1-evb should replace the older A0 version. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250703052400.2927831-1-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- docs/about/deprecated.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -XXX,XX +XXX,XX @@ deprecated; use the new name ``dtb-randomness`` instead. The new name better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. +Arm ``ast2700a0-evb`` machine (since 10.1) +'''''''''''''''''''''''''''''''''''''''''' + +The ``ast2700a0-evb`` machine represents the first revision of the AST2700 +and serves as the initial engineering sample rather than a production version. +A newer revision, A1, is now supported, and the ``ast2700a1-evb`` should +replace the older A0 version. + Mips ``mipssim`` machine (since 10.0) ''''''''''''''''''''''''''''''''''''' -- 2.50.0
From: Ed Tanous <etanous@nvidia.com> Aspeed2600 has two spi lanes; Add a new struct that can mount the second SPI. Signed-off-by: Ed Tanous <etanous@nvidia.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250703144249.3348879-2-etanous@nvidia.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed.h | 2 ++ hw/arm/aspeed.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed.h +++ b/include/hw/arm/aspeed.h @@ -XXX,XX +XXX,XX @@ struct AspeedMachineClass { uint32_t hw_strap2; const char *fmc_model; const char *spi_model; + const char *spi2_model; uint32_t num_cs; + uint32_t num_cs2; uint32_t macs_mask; void (*i2c_init)(AspeedMachineState *bmc); uint32_t uart_default; diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine) aspeed_board_init_flashes(&bmc->soc->spi[0], bmc->spi_model ? bmc->spi_model : amc->spi_model, 1, amc->num_cs); + aspeed_board_init_flashes(&bmc->soc->spi[1], + amc->spi2_model, 1, amc->num_cs2); } if (machine->kernel_filename && sc->num_cpus > 1) { -- 2.50.0
From: Ed Tanous <etanous@nvidia.com> This patch updates the docs for support of gb200-bmc. Signed-off-by: Ed Tanous <etanous@nvidia.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250703144249.3348879-3-etanous@nvidia.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- docs/system/arm/aspeed.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -XXX,XX +XXX,XX @@ -Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) -================================================================================================================================================================================================================================================================================================================================================================================================================================= +Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``gb200nvl-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) The QEMU Aspeed machines model BMCs of various OpenPOWER systems and Aspeed evaluation boards. They are based on different releases of the @@ -XXX,XX +XXX,XX @@ AST2600 SoC based machines : - ``fuji-bmc`` Facebook Fuji BMC - ``bletchley-bmc`` Facebook Bletchley BMC - ``fby35-bmc`` Facebook fby35 BMC +- ``gb200nvl-bmc`` Nvidia GB200nvl BMC - ``qcom-dc-scm-v1-bmc`` Qualcomm DC-SCM V1 BMC - ``qcom-firework-bmc`` Qualcomm Firework BMC -- 2.50.0
From: Ed Tanous <etanous@nvidia.com> GB200nvl72 is a system for for accelerated compute. This is a model for the BMC target within the system. This is based on the device tree aspeed-bmc-nvidia-gb200nvl-bmc.dts from: [1] https://github.com/openbmc/linux/blob/dev-6.6/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-gb200nvl-bmc.dts Signed-off-by: Ed Tanous <etanous@nvidia.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250703144249.3348879-4-etanous@nvidia.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_eeprom.h | 3 ++ hw/arm/aspeed.c | 78 ++++++++++++++++++++++++++++++++++++++++++ hw/arm/aspeed_eeprom.c | 21 ++++++++++++ 3 files changed, 102 insertions(+) diff --git a/hw/arm/aspeed_eeprom.h b/hw/arm/aspeed_eeprom.h index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_eeprom.h +++ b/hw/arm/aspeed_eeprom.h @@ -XXX,XX +XXX,XX @@ extern const size_t rainier_bb_fruid_len; extern const uint8_t rainier_bmc_fruid[]; extern const size_t rainier_bmc_fruid_len; +extern const uint8_t gb200nvl_bmc_fruid[]; +extern const size_t gb200nvl_bmc_fruid_len; + #endif diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -XXX,XX +XXX,XX @@ struct AspeedMachineState { #define BLETCHLEY_BMC_HW_STRAP1 0x00002000 #define BLETCHLEY_BMC_HW_STRAP2 0x00000801 +/* GB200NVL hardware value */ +#define GB200NVL_BMC_HW_STRAP1 AST2600_EVB_HW_STRAP1 +#define GB200NVL_BMC_HW_STRAP2 AST2600_EVB_HW_STRAP2 + /* Qualcomm DC-SCM hardware value */ #define QCOM_DC_SCM_V1_BMC_HW_STRAP1 0x00000000 #define QCOM_DC_SCM_V1_BMC_HW_STRAP2 0x00000041 @@ -XXX,XX +XXX,XX @@ static void create_pca9552(AspeedSoCState *soc, int bus_id, int addr) TYPE_PCA9552, addr); } +static I2CSlave *create_pca9554(AspeedSoCState *soc, int bus_id, int addr) +{ + return i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, bus_id), + TYPE_PCA9554, addr); +} + static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = bmc->soc; @@ -XXX,XX +XXX,XX @@ static void bletchley_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(i2c[12], TYPE_PCA9552, 0x67); } + +static void gb200nvl_bmc_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = bmc->soc; + I2CBus *i2c[15] = {}; + DeviceState *dev; + for (int i = 0; i < sizeof(i2c) / sizeof(i2c[0]); i++) { + if ((i == 11) || (i == 12) || (i == 13)) { + continue; + } + i2c[i] = aspeed_i2c_get_bus(&soc->i2c, i); + } + + /* Bus 5 Expander */ + create_pca9554(soc, 4, 0x21); + + /* Mux I2c Expanders */ + i2c_slave_create_simple(i2c[5], "pca9546", 0x71); + i2c_slave_create_simple(i2c[5], "pca9546", 0x72); + i2c_slave_create_simple(i2c[5], "pca9546", 0x73); + i2c_slave_create_simple(i2c[5], "pca9546", 0x75); + i2c_slave_create_simple(i2c[5], "pca9546", 0x76); + i2c_slave_create_simple(i2c[5], "pca9546", 0x77); + + /* Bus 10 */ + dev = DEVICE(create_pca9554(soc, 9, 0x20)); + + /* Set FPGA_READY */ + object_property_set_str(OBJECT(dev), "pin1", "high", &error_fatal); + + create_pca9554(soc, 9, 0x21); + at24c_eeprom_init(i2c[9], 0x50, 64 * KiB); + at24c_eeprom_init(i2c[9], 0x51, 64 * KiB); + + /* Bus 11 */ + at24c_eeprom_init_rom(i2c[10], 0x50, 256, gb200nvl_bmc_fruid, + gb200nvl_bmc_fruid_len); +} + static void fby35_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = bmc->soc; @@ -XXX,XX +XXX,XX @@ static void aspeed_machine_catalina_class_init(ObjectClass *oc, aspeed_machine_ast2600_class_emmc_init(oc); } +#define GB200NVL_BMC_RAM_SIZE ASPEED_RAM_SIZE(1 * GiB) + +static void aspeed_machine_gb200nvl_class_init(ObjectClass *oc, + const void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Nvidia GB200NVL BMC (Cortex-A7)"; + amc->soc_name = "ast2600-a3"; + amc->hw_strap1 = GB200NVL_BMC_HW_STRAP1; + amc->hw_strap2 = GB200NVL_BMC_HW_STRAP2; + amc->fmc_model = "mx66u51235f"; + amc->spi_model = "mx66u51235f"; + amc->num_cs = 2; + + amc->spi2_model = "mx66u51235f"; + amc->num_cs2 = 1; + amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON; + amc->i2c_init = gb200nvl_bmc_i2c_init; + mc->default_ram_size = GB200NVL_BMC_RAM_SIZE; + aspeed_machine_class_init_cpus_defaults(mc); + aspeed_machine_ast2600_class_emmc_init(oc); +} + static void fby35_reset(MachineState *state, ResetType type) { AspeedMachineState *bmc = ASPEED_MACHINE(state); @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = { .name = MACHINE_TYPE_NAME("bletchley-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_bletchley_class_init, + }, { + .name = MACHINE_TYPE_NAME("gb200nvl-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_gb200nvl_class_init, }, { .name = MACHINE_TYPE_NAME("catalina-bmc"), .parent = TYPE_ASPEED_MACHINE, diff --git a/hw/arm/aspeed_eeprom.c b/hw/arm/aspeed_eeprom.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_eeprom.c +++ b/hw/arm/aspeed_eeprom.c @@ -XXX,XX +XXX,XX @@ const uint8_t rainier_bmc_fruid[] = { 0x31, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, }; +const uint8_t gb200nvl_bmc_fruid[] = { + 0x01, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0xf3, 0x01, 0x0a, 0x19, 0x1f, + 0x0f, 0xe6, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x33, + 0x38, 0x30, 0x39, 0xcd, 0x31, 0x35, 0x38, 0x33, 0x33, 0x32, 0x34, 0x38, + 0x30, 0x30, 0x31, 0x35, 0x30, 0xd2, 0x36, 0x39, 0x39, 0x2d, 0x31, 0x33, + 0x38, 0x30, 0x39, 0x2d, 0x30, 0x34, 0x30, 0x34, 0x2d, 0x36, 0x30, 0x30, + 0xc0, 0x01, 0x01, 0xd6, 0x4d, 0x41, 0x43, 0x3a, 0x20, 0x33, 0x43, 0x3a, + 0x36, 0x44, 0x3a, 0x36, 0x36, 0x3a, 0x31, 0x34, 0x3a, 0x43, 0x38, 0x3a, + 0x37, 0x41, 0xc1, 0x3b, 0x01, 0x09, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, + 0x49, 0x41, 0xc9, 0x50, 0x33, 0x38, 0x30, 0x39, 0x2d, 0x42, 0x4d, 0x43, + 0xd2, 0x36, 0x39, 0x39, 0x2d, 0x31, 0x33, 0x38, 0x30, 0x39, 0x2d, 0x30, + 0x34, 0x30, 0x34, 0x2d, 0x36, 0x30, 0x30, 0xc4, 0x41, 0x45, 0x2e, 0x31, + 0xcd, 0x31, 0x35, 0x38, 0x33, 0x33, 0x32, 0x34, 0x38, 0x30, 0x30, 0x31, + 0x35, 0x30, 0xc0, 0xc4, 0x76, 0x30, 0x2e, 0x31, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + +}; + const size_t tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid); const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid); const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid); @@ -XXX,XX +XXX,XX @@ const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid); const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid); const size_t rainier_bb_fruid_len = sizeof(rainier_bb_fruid); const size_t rainier_bmc_fruid_len = sizeof(rainier_bmc_fruid); +const size_t gb200nvl_bmc_fruid_len = sizeof(gb200nvl_bmc_fruid); + -- 2.50.0
From: Ed Tanous <etanous@nvidia.com> To support the newly added gb200 machine, add appropriate tests and extend do_test_arm_aspeed_openbmc() to support the hostname of this new system: "gb200nvl-obmc". Signed-off-by: Ed Tanous <etanous@nvidia.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250703144249.3348879-5-etanous@nvidia.com [ clg: Adjust commit log to document do_test_arm_aspeed_openbmc() change ] Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/aspeed.py | 9 +++++-- tests/functional/meson.build | 2 ++ .../test_arm_aspeed_gb200nvl_bmc.py | 26 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/functional/test_arm_aspeed_gb200nvl_bmc.py diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py index XXXXXXX..XXXXXXX 100644 --- a/tests/functional/aspeed.py +++ b/tests/functional/aspeed.py @@ -XXX,XX +XXX,XX @@ class AspeedTest(LinuxKernelTest): def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04', - cpu_id='0x0', soc='AST2500 rev A1'): - hostname = machine.removesuffix('-bmc') + cpu_id='0x0', soc='AST2500 rev A1', + image_hostname=None): + # Allow for the image hostname to not end in "-bmc" + if image_hostname is not None: + hostname = image_hostname + else: + hostname = machine.removesuffix('-bmc') self.set_machine(machine) self.vm.set_console() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index XXXXXXX..XXXXXXX 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -XXX,XX +XXX,XX @@ test_timeouts = { 'arm_aspeed_ast2600' : 1200, 'arm_aspeed_bletchley' : 480, 'arm_aspeed_catalina' : 480, + 'arm_aspeed_gb200nvl_bmc' : 480, 'arm_aspeed_rainier' : 480, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -XXX,XX +XXX,XX @@ tests_arm_system_thorough = [ 'arm_aspeed_ast2600', 'arm_aspeed_bletchley', 'arm_aspeed_catalina', + 'arm_aspeed_gb200nvl_bmc', 'arm_aspeed_rainier', 'arm_bpim2u', 'arm_canona1100', diff --git a/tests/functional/test_arm_aspeed_gb200nvl_bmc.py b/tests/functional/test_arm_aspeed_gb200nvl_bmc.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_gb200nvl_bmc.py @@ -XXX,XX +XXX,XX @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class GB200Machine(AspeedTest): + + ASSET_GB200_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/gb200nvl-obmc/obmc-phosphor-image-gb200nvl-obmc-20250702182348.static.mtd.xz', + 'b84819317cb3dc762895ad507705978ef000bfc77c50c33a63bdd37921db0dbc') + + def test_arm_aspeed_gb200_openbmc(self): + image_path = self.uncompress(self.ASSET_GB200_FLASH) + + self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3', + image_hostname='gb200nvl-obmc') + +if __name__ == '__main__': + AspeedTest.main() -- 2.50.0
The following changes since commit 28a6ca268c2cd3718b5bf24c2d97e3d1e95fc604: Merge tag 'single-binary-20260203' of https://github.com/philmd/qemu into staging (2026-02-04 01:57:26 +1000) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-aspeed-20260204 for you to fetch changes up to e56e45d5bdc808ed52f943d1a785e4d885b6f18f: tests/functional/aarch64: Add I2C test for AST1700 IO expanders (2026-02-04 10:10:57 +0100) ---------------------------------------------------------------- aspeed queue: * Added support for the new AST1700 IO expander, including several device models (LTPI, PWM, I2C, GPIO, etc.). * Updated the AST2700 SoC with LTPI support, EHCI IRQ fixes, and other improvements. * Updated test images and test cases for various Aspeed platforms. * Fixed issues in the Aspeed I2C and ADC models. * Added support for pca9535 GPIO expander. * Updated documentation for Aspeed boards. ---------------------------------------------------------------- Cédric Le Goater (3): Merge tag 'pull-vbootrom-20260116-v3' into aspeed-next tests/functional/arm/aspeed: Update buildroot images to 2025.11 hw/adc: Fix out-of-bounds write in Aspeed ADC model Jamin Lin (17): pc-bios: Update vbootrom image to commit 1c8e9510b22c MAINTAINERS: Update ASPEED entry tests/functional/arm/test_aspeed_ast2500: Update test ASPEED SDK v10.00 hw/pci-host/aspeed_pcie: Drop AST2600 PCIe root device hw/pci-host/aspeed_pcie: Drop AST2600 RC_H root-bus remap and bus-nr property hw/arm/aspeed_ast2600: Expand RC_H PCIe MMIO window to 0x60000000 - 0x80000000 tests/functional/arm/test_aspeed_ast2600_sdk: Update test ASPEED SDK v11.00 tests/functional/arm/test_aspeed_ast1060: Update test aspeed-zephyr-project v03.04 tests/functional/arm/test_aspeed_ast1030: Update test ASPEED Zephyr SDK v03.05 hw/arm/aspeed_ast27x0: Fix EHCI3/4 IRQ routing to GIC hw/arm/aspeed_ast27x0: Sort SSP and TSP memmap tables by address hw/arm/aspeed_ast27x0: Sort SSP and TSP IRQ maps hw/i2c/aspeed_i2c: Fix DMA moving data into incorrect address tests/functional/aarch64/test_aspeed_ast2700: Enable PCIe2 DTS status for AST2700 tests tests/functional/aarch64/test_aspeed_ast2700: Update test ASPEED SDK v11.00 for A1 tests/functional/aarch64/test_aspeed_ast2700fc: Update test ASPEED SDK v11.00 for A1 docs/system/arm/aspeed: Load raw U-Boot image in AST2700 boot example Kane Chen (22): hw/misc: Add LTPI controller hw/arm/aspeed: Attach LTPI controller to AST27X0 platform hw/misc: Add basic Aspeed PWM model hw/arm/aspeed: Add AST1700 LTPI expander device model hw/arm/aspeed: Integrate AST1700 device into AST27X0 hw/arm/aspeed: Integrate interrupt controller for AST1700 hw/arm/aspeed: Attach LTPI controller to AST1700 model hw/arm/aspeed: Attach UART device to AST1700 model hw/arm/aspeed: Attach SRAM device to AST1700 model hw/arm/aspeed: Attach SPI device to AST1700 model hw/arm/aspeed: Attach ADC device to AST1700 model hw/arm/aspeed: Attach SCU device to AST1700 model hw/arm/aspeed: Attach GPIO device to AST1700 model hw/arm/aspeed: attach I2C device to AST1700 model hw/arm/aspeed: Attach WDT device to AST1700 model hw/arm/aspeed: Attach PWM device to AST1700 model hw/arm/aspeed: Attach SGPIOM device to AST1700 model hw/arm/aspeed: Model AST1700 I3C block as unimplemented device hw/arm/aspeed: Enable AST1700 IO expander support tests/functional/aarch64: Parameterize I2C bus ID in AST2700 test tests/functional/aarch64: Parameterize PCIe2 initialization in AST2700 tests/functional/aarch64: Add I2C test for AST1700 IO expanders Kane-Chen-AS (1): hw/i2c/aspeed: Introduce 'bus-label' to customize bus naming Nabih Estefan (1): hw/i2c/aspeed_i2c.c: Add a check for dma_read Patrick Williams (2): hw/gpio/pca9552: add pca9535 support hw/arm/aspeed: catalina: use pca9535 MAINTAINERS | 2 + docs/system/arm/aspeed.rst | 8 +- include/hw/arm/aspeed_ast1700.h | 54 ++++ include/hw/arm/aspeed_soc.h | 25 +- include/hw/gpio/pca9552.h | 1 + include/hw/gpio/pca9552_regs.h | 10 + include/hw/i2c/aspeed_i2c.h | 2 + include/hw/intc/aspeed_intc.h | 2 + include/hw/misc/aspeed_ltpi.h | 33 +++ include/hw/misc/aspeed_pwm.h | 30 +++ include/hw/pci-host/aspeed_pcie.h | 11 - hw/adc/aspeed_adc.c | 3 +- hw/arm/aspeed_ast1700.c | 276 +++++++++++++++++++++ hw/arm/aspeed_ast2600.c | 8 +- hw/arm/aspeed_ast2600_catalina.c | 4 +- hw/arm/aspeed_ast27x0-ssp.c | 14 +- hw/arm/aspeed_ast27x0-tsp.c | 14 +- hw/arm/aspeed_ast27x0.c | 169 ++++++++++++- hw/gpio/pca9552.c | 176 +++++++++---- hw/i2c/aspeed_i2c.c | 120 ++++++--- hw/intc/aspeed_intc.c | 60 +++++ hw/misc/aspeed_ltpi.c | 193 ++++++++++++++ hw/misc/aspeed_pwm.c | 120 +++++++++ hw/pci-host/aspeed_pcie.c | 76 +----- hw/arm/meson.build | 1 + hw/misc/meson.build | 2 + hw/misc/trace-events | 4 + pc-bios/ast27x0_bootrom.bin | Bin 16408 -> 28564 bytes pc-bios/npcm7xx_bootrom.bin | Bin 672 -> 736 bytes pc-bios/npcm8xx_bootrom.bin | Bin 672 -> 672 bytes roms/vbootrom | 2 +- tests/functional/aarch64/test_aspeed_ast2700.py | 137 ++++++---- tests/functional/aarch64/test_aspeed_ast2700fc.py | 54 ++-- tests/functional/arm/test_aspeed_ast1030.py | 12 +- tests/functional/arm/test_aspeed_ast1060.py | 14 +- tests/functional/arm/test_aspeed_ast2500.py | 16 +- .../arm/test_aspeed_ast2600_buildroot.py | 8 +- tests/functional/arm/test_aspeed_ast2600_sdk.py | 22 +- 38 files changed, 1352 insertions(+), 331 deletions(-) create mode 100644 include/hw/arm/aspeed_ast1700.h create mode 100644 include/hw/misc/aspeed_ltpi.h create mode 100644 include/hw/misc/aspeed_pwm.h create mode 100644 hw/arm/aspeed_ast1700.c create mode 100644 hw/misc/aspeed_ltpi.c create mode 100644 hw/misc/aspeed_pwm.c
From: Jamin Lin <jamin_lin@aspeedtech.com> Full changelog since last update (183c9ff8056b) : Joe Komlodi (1): npcm8xx: Fix u-boot copy size Jamin Lin (3): ast27x0: refactor FIT boot loader into fmc_image.c for future Caliptra Manifest support ast27x0: Add Caliptra Manifest boot support and MCU runtime loader framework ast27x0: Fix compilation issues on Ubuntu 22.04 Compiled with gcc version 13.3.0 Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> --- pc-bios/ast27x0_bootrom.bin | Bin 16408 -> 28564 bytes pc-bios/npcm7xx_bootrom.bin | Bin 672 -> 736 bytes pc-bios/npcm8xx_bootrom.bin | Bin 672 -> 672 bytes roms/vbootrom | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/ast27x0_bootrom.bin b/pc-bios/ast27x0_bootrom.bin index XXXXXXX..XXXXXXX 100644 GIT binary patch literal 28564 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 E14Sx{n*aa+ delta 4114 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 DBJm?y diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin index XXXXXXX..XXXXXXX 100644 GIT binary patch delta 287 zcmYL?Jxjw-7==%6(kd}S3J#75I4WN752V_mTZ<py;Nals=-?pq8XO#4s-3+T+?-q; zO7j=QrF2Sic|n`S$)%K6s-OoB&u|_%rk2;9Z=7BOs3dO{6Xq!}XMi~q%#kzyDWtJs zviad=Y3?RT4jfxIZ|0#Ij*&f(CwEI^*Yw3aU6IDl)_?sAnUZK4i)cWXQj?3l!U6nq zXc{qBUNoRHse6CJDKxz>S0_?aAm0esw{^f5v9YsNW0&JQLUcu~NRzv5ilfCr!`Q^> z6VSCD;J4yFiH)>;Wv)b^%1{m8*Pv;^?$Y7YtzbUrbaoyEGaM*{b@d4Wb>9~4AjW^b E0jKYKB>(^b delta 209 zcmaFBx`1^<2V*@C1H*5F|N0Ma{r~@pf#L6e28RFt8<_t8S77`L#tg~@TdznQlVZ?W z_?nrO;ZDI`oeUOhlY}qNxt0AtR67Z5ot*Cffx$&7L(F@Y6Y~X0j|!Ln-zU6J$`A(g z#lZZI_X6J1)!rNZKQK7?f2el6^n*i@D}l#rwj<-@RR0eQju(G8Fgk3!_`^k!=_^Cg z|L;fsGkj$z5ZKG=@#i_i{s8vSRU!WVP7I6;4GaPe9~hVz8nPG|7z!B}7$)~Hc}%{* GBme+2%vQGm diff --git a/pc-bios/npcm8xx_bootrom.bin b/pc-bios/npcm8xx_bootrom.bin index XXXXXXX..XXXXXXX 100644 GIT binary patch delta 99 zcmV-p0G$7z1)v46-~mCw0RU7a07AK+00V1b0RU9}d%vmu0|1dF_(8cM{6V?k0|hEV z00<G@|Noc$d%>un00<Gl17Fr500fag008U3lN|ydlRyGA4U7N)002}D5S;>^0Y{U8 F0v|xlB4+>q delta 98 zcmV-o0G<D!1)v46-~m0M0RU7a07AK+00V150RU9}d%vmu0|1dC{6V=T_(8eg0|hGI z|Noc$d%>un00<Gl17Fr500fag008UZlOX~hkzfRqKms%khyVZp08|bTodTW#Mw5X8 EA4gjv-2eap diff --git a/roms/vbootrom b/roms/vbootrom index XXXXXXX..XXXXXXX 160000 --- a/roms/vbootrom +++ b/roms/vbootrom @@ -1 +1 @@ -Subproject commit 183c9ff8056b7946db1ae49cc23e8980ac413174 +Subproject commit 1c8e9510b22c5b0fd7d7753f08042a4bcbd2939d -- 2.52.0
The main changes compared to upstream 2025.11 buildroot are - Linux v6.18 - latest OpenBMC U-Boot - extra packages (ssh, etc.) See https://github.com/legoater/buildroot/commits/aspeed-2025.11 Acked-by: Jamin Lin <jamin_lin@aspeedtech.com> Link: https://lore.kernel.org/qemu-devel/20260105160358.771511-1-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/arm/test_aspeed_ast2500.py | 8 ++++---- tests/functional/arm/test_aspeed_ast2600_buildroot.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/arm/test_aspeed_ast2500.py +++ b/tests/functional/arm/test_aspeed_ast2500.py @@ -XXX,XX +XXX,XX @@ class AST2500Machine(AspeedTest): - ASSET_BR2_202411_AST2500_FLASH = Asset( + ASSET_BR2_202511_AST2500_FLASH = Asset( ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2500-evb/buildroot-2024.11/flash.img'), - '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a') + 'images/ast2500-evb/buildroot-2025.11/flash.img'), + '31e5a8e280b982fb0e7c07eb71c94851002f99ac604dfe620e71a5d47cc87e78') def test_arm_ast2500_evb_buildroot(self): self.set_machine('ast2500-evb') - image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch() + image_path = self.ASSET_BR2_202511_AST2500_FLASH.fetch() self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test') diff --git a/tests/functional/arm/test_aspeed_ast2600_buildroot.py b/tests/functional/arm/test_aspeed_ast2600_buildroot.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/arm/test_aspeed_ast2600_buildroot.py +++ b/tests/functional/arm/test_aspeed_ast2600_buildroot.py @@ -XXX,XX +XXX,XX @@ class AST2600Machine(AspeedTest): - ASSET_BR2_202411_AST2600_FLASH = Asset( + ASSET_BR2_202511_AST2600_FLASH = Asset( ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2024.11/flash.img'), - '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609') + 'images/ast2600-evb/buildroot-2025.11/flash.img'), + 'c64a0755501393d570ca318e326e1e9f8372edc5a6452cdccc3649bc9fd2c138') def test_arm_ast2600_evb_buildroot(self): self.set_machine('ast2600-evb') - image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch() + image_path = self.ASSET_BR2_202511_AST2600_FLASH.fetch() self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test') -- 2.52.0
From: Kane-Chen-AS <kane_chen@aspeedtech.com> On some Aspeed-based machines, multiple I2C controllers may exist across different components, such as the primary SoC and an external IO expander or co-processor (e.g., AST1700). Using the current static naming convention results in object name conflicts when multiple controllers attempt to instantiate buses with the same ID. This patch introduces a 'bus-label' property for the Aspeed I2C controller. This allows higher-level layers, such as the SoC realize function, to provide a unique identifier for the buses. The I2C bus object name is then constructed using this label (e.g., "ioexp0.0" instead of the default "aspeed.i2c.bus.0"). This enhancement ensures unique bus identifiers across the system and resolves naming conflicts in multi-controller configurations. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260112083054.4151945-2-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/i2c/aspeed_i2c.h | 2 ++ hw/i2c/aspeed_i2c.c | 27 +++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -XXX,XX +XXX,XX @@ struct AspeedI2CBus { MemoryRegion mr_pool; I2CBus *bus; + char *name; uint8_t id; qemu_irq irq; @@ -XXX,XX +XXX,XX @@ struct AspeedI2CState { uint32_t intr_status; uint32_t ctrl_global; uint32_t new_clk_divider; + char *bus_label; MemoryRegion pool_iomem; uint8_t share_pool[ASPEED_I2C_SHARE_POOL_SIZE]; diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) "aspeed.i2c", aic->mem_size); sysbus_init_mmio(sbd, &s->iomem); + /* default value */ + if (!s->bus_label) { + s->bus_label = g_strdup(TYPE_ASPEED_I2C_BUS); + } + for (i = 0; i < aic->num_busses; i++) { Object *bus = OBJECT(&s->busses[i]); int offset = i < aic->gap ? 1 : 5; + g_autofree char *name = g_strdup_printf("%s.%d", + s->bus_label, i); if (!object_property_set_link(bus, "controller", OBJECT(s), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) return; } + if (!object_property_set_str(bus, "bus-name", name, errp)) { + return; + } + if (!sysbus_realize(SYS_BUS_DEVICE(bus), errp)) { return; } @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) static const Property aspeed_i2c_properties[] = { DEFINE_PROP_LINK("dram", AspeedI2CState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_STRING("bus-label", AspeedI2CState, bus_label), }; static void aspeed_i2c_class_init(ObjectClass *klass, const void *data) @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_realize(DeviceState *dev, Error **errp) { AspeedI2CBus *s = ASPEED_I2C_BUS(dev); AspeedI2CClass *aic; - g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I2C_BUS ".%d", s->id); - g_autofree char *pool_name = g_strdup_printf("%s.pool", name); + g_autofree char *pool_name = NULL; - if (!s->controller) { - error_setg(errp, TYPE_ASPEED_I2C_BUS ": 'controller' link not set"); + if (!s->controller || !s->name) { + error_setg(errp, TYPE_ASPEED_I2C_BUS + ": 'controller' or 'bus-name' not set"); return; } + pool_name = g_strdup_printf("%s.pool", s->name); + aic = ASPEED_I2C_GET_CLASS(s->controller); sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); - s->bus = i2c_init_bus(dev, name); + s->bus = i2c_init_bus(dev, s->name); s->slave = i2c_slave_create_simple(s->bus, TYPE_ASPEED_I2C_BUS_SLAVE, 0xff); memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i2c_bus_ops, - s, name, aic->reg_size); + s, s->name, aic->reg_size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr); memory_region_init_io(&s->mr_pool, OBJECT(s), &aspeed_i2c_bus_pool_ops, @@ -XXX,XX +XXX,XX @@ static const Property aspeed_i2c_bus_properties[] = { DEFINE_PROP_UINT8("bus-id", AspeedI2CBus, id, 0), DEFINE_PROP_LINK("controller", AspeedI2CBus, controller, TYPE_ASPEED_I2C, AspeedI2CState *), + DEFINE_PROP_STRING("bus-name", AspeedI2CBus, name), }; static void aspeed_i2c_bus_class_init(ObjectClass *klass, const void *data) -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260116082431.3689035-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index XXXXXXX..XXXXXXX 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -XXX,XX +XXX,XX @@ F: hw/net/ftgmac100.c F: include/hw/net/ftgmac100.h F: docs/system/arm/aspeed.rst F: docs/system/arm/fby35.rst +F: docs/specs/aspeed* F: tests/functional/*/*aspeed* F: tests/*/*aspeed* F: tests/*/*ast2700* F: hw/arm/fby35.c F: pc-bios/ast27x0_bootrom.bin +F: roms/vbootrom NRF51 M: Joel Stanley <joel@jms.id.au> -- 2.52.0
From: Nabih Estefan <nabihestefan@google.com> If aspeed_i2c_dma_read fails in aspeed_i2c_bus_send currently, we get stuck in an infinite retry loop. Add a check for the return value of aspeed_i2c_dma_read that will break us out of said loop. Signed-off-by: Nabih Estefan <nabihestefan@google.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Fixes: 545d6bef7097 ("aspeed/i2c: Add support for DMA transfers") Link: https://lore.kernel.org/qemu-devel/20260120211116.1367476-1-nabihestefan@google.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/i2c/aspeed_i2c.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus) } while (bus->regs[reg_dma_len]) { uint8_t data; - aspeed_i2c_dma_read(bus, &data); + ret = aspeed_i2c_dma_read(bus, &data); + /* Check that we were able to read the DMA */ + if (ret) { + break; + } trace_aspeed_i2c_bus_send("DMA", bus->regs[reg_dma_len], bus->regs[reg_dma_len], data); ret = i2c_send(bus->bus, data); -- 2.52.0
From: Patrick Williams <patrick@stwcx.xyz> Extend the 16-bit PCA9552 model to support non-LED devices such as the PCA9535[1]. [1]: https://www.ti.com/lit/ds/symlink/pca9535.pdf Signed-off-by: Patrick Williams <patrick@stwcx.xyz> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260121-pca9535-v1-1-164640e622ff@stwcx.xyz Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/gpio/pca9552.h | 1 + include/hw/gpio/pca9552_regs.h | 10 ++ hw/gpio/pca9552.c | 176 +++++++++++++++++++++++---------- 3 files changed, 133 insertions(+), 54 deletions(-) diff --git a/include/hw/gpio/pca9552.h b/include/hw/gpio/pca9552.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/gpio/pca9552.h +++ b/include/hw/gpio/pca9552.h @@ -XXX,XX +XXX,XX @@ #define TYPE_PCA9552 "pca9552" #define TYPE_PCA955X "pca955x" +#define TYPE_PCA9535 "pca9535" typedef struct PCA955xState PCA955xState; DECLARE_INSTANCE_CHECKER(PCA955xState, PCA955X, TYPE_PCA955X) diff --git a/include/hw/gpio/pca9552_regs.h b/include/hw/gpio/pca9552_regs.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/gpio/pca9552_regs.h +++ b/include/hw/gpio/pca9552_regs.h @@ -XXX,XX +XXX,XX @@ */ #define PCA9552_AUTOINC (1 << 4) +/* PCA9535 Registers (same addresses, different semantics) */ +#define PCA9535_INPUT0 0 /* read only input register 0 */ +#define PCA9535_INPUT1 1 /* read only input register 1 */ +#define PCA9535_OUTPUT0 2 /* read/write output register 0 */ +#define PCA9535_OUTPUT1 3 /* read/write output register 1 */ +#define PCA9535_POLARITY0 4 /* read/write polarity inversion register 0 */ +#define PCA9535_POLARITY1 5 /* read/write polarity inversion register 1 */ +#define PCA9535_CONFIG0 6 /* read/write configuration register 0 */ +#define PCA9535_CONFIG1 7 /* read/write configuration register 1 */ + #endif diff --git a/hw/gpio/pca9552.c b/hw/gpio/pca9552.c index XXXXXXX..XXXXXXX 100644 --- a/hw/gpio/pca9552.c +++ b/hw/gpio/pca9552.c @@ -XXX,XX +XXX,XX @@ struct PCA955xClass { uint8_t pin_count; uint8_t max_reg; + bool has_led_support; }; typedef struct PCA955xClass PCA955xClass; @@ -XXX,XX +XXX,XX @@ static void pca955x_update_pin_input(PCA955xState *s) for (i = 0; i < k->pin_count; i++) { uint8_t input_reg = PCA9552_INPUT0 + (i / 8); uint8_t bit_mask = 1 << (i % 8); - uint8_t config = pca955x_pin_get_config(s, i); uint8_t old_value = s->regs[input_reg] & bit_mask; uint8_t new_value; - switch (config) { - case PCA9552_LED_ON: - /* Pin is set to 0V to turn on LED */ - s->regs[input_reg] &= ~bit_mask; - break; - case PCA9552_LED_OFF: - /* - * Pin is set to Hi-Z to turn off LED and - * pullup sets it to a logical 1 unless - * external device drives it low. - */ - if (s->ext_state[i] == PCA9552_PIN_LOW) { + if (k->has_led_support) { + /* PCA9552: LED control behavior */ + uint8_t config = pca955x_pin_get_config(s, i); + + switch (config) { + case PCA9552_LED_ON: + /* Pin is set to 0V to turn on LED */ s->regs[input_reg] &= ~bit_mask; + break; + case PCA9552_LED_OFF: + /* + * Pin is set to Hi-Z to turn off LED and + * pullup sets it to a logical 1 unless + * external device drives it low. + */ + if (s->ext_state[i] == PCA9552_PIN_LOW) { + s->regs[input_reg] &= ~bit_mask; + } else { + s->regs[input_reg] |= bit_mask; + } + break; + case PCA9552_LED_PWM0: + case PCA9552_LED_PWM1: + /* TODO */ + default: + break; + } + } else { + /* PCA9535: Simple GPIO behavior */ + uint8_t config_reg = PCA9535_CONFIG0 + (i / 8); + uint8_t output_reg = PCA9535_OUTPUT0 + (i / 8); + uint8_t polarity_reg = PCA9535_POLARITY0 + (i / 8); + + /* Check if pin is configured as input */ + if (s->regs[config_reg] & bit_mask) { + /* Input mode - reflect external state */ + if (s->ext_state[i] == PCA9552_PIN_LOW) { + s->regs[input_reg] &= ~bit_mask; + } else { + s->regs[input_reg] |= bit_mask; + } } else { - s->regs[input_reg] |= bit_mask; + /* Output mode - reflect output register value */ + uint8_t output_bit = s->regs[output_reg] & bit_mask; + uint8_t polarity_bit = s->regs[polarity_reg] & bit_mask; + + /* Apply polarity inversion if set */ + s->regs[input_reg] = (s->regs[input_reg] & ~bit_mask) | + ((output_bit ^ polarity_bit) & bit_mask); } - break; - case PCA9552_LED_PWM0: - case PCA9552_LED_PWM1: - /* TODO */ - default: - break; } /* update irq state only if pin state changed */ @@ -XXX,XX +XXX,XX @@ static void pca955x_update_pin_input(PCA955xState *s) static uint8_t pca955x_read(PCA955xState *s, uint8_t reg) { - switch (reg) { - case PCA9552_INPUT0: - case PCA9552_INPUT1: - case PCA9552_PSC0: - case PCA9552_PWM0: - case PCA9552_PSC1: - case PCA9552_PWM1: - case PCA9552_LS0: - case PCA9552_LS1: - case PCA9552_LS2: - case PCA9552_LS3: - return s->regs[reg]; - default: + PCA955xClass *k = PCA955X_GET_CLASS(s); + + if (reg > k->max_reg) { qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected read to register %d\n", __func__, reg); return 0xFF; } + + return s->regs[reg]; } static void pca955x_write(PCA955xState *s, uint8_t reg, uint8_t data) { + PCA955xClass *k = PCA955X_GET_CLASS(s); uint16_t pins_status; - switch (reg) { - case PCA9552_PSC0: - case PCA9552_PWM0: - case PCA9552_PSC1: - case PCA9552_PWM1: - s->regs[reg] = data; - break; - - case PCA9552_LS0: - case PCA9552_LS1: - case PCA9552_LS2: - case PCA9552_LS3: - pins_status = pca955x_pins_get_status(s); - s->regs[reg] = data; - pca955x_update_pin_input(s); - pca955x_display_pins_status(s, pins_status); - break; - - case PCA9552_INPUT0: - case PCA9552_INPUT1: - default: + if (reg > k->max_reg) { qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected write to register %d\n", __func__, reg); + return; + } + + /* Handle read-only registers */ + if (reg == PCA9552_INPUT0 || reg == PCA9552_INPUT1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: unexpected write to read-only register %d\n", + __func__, reg); + return; + } + + pins_status = pca955x_pins_get_status(s); + s->regs[reg] = data; + + /* Update GPIO state if this register affects outputs */ + if (k->has_led_support) { + /* PCA9552: Update on LED selector register writes */ + if (reg >= PCA9552_LS0 && reg <= PCA9552_LS3) { + pca955x_update_pin_input(s); + pca955x_display_pins_status(s, pins_status); + } + } else { + /* PCA9535: Update on OUTPUT, POLARITY, or CONFIG register writes */ + if (reg >= PCA9535_OUTPUT0 && reg <= PCA9535_CONFIG1) { + pca955x_update_pin_input(s); + pca955x_display_pins_status(s, pins_status); + } } } @@ -XXX,XX +XXX,XX @@ static void pca9552_reset(DeviceState *dev) s->len = 0; } +static void pca9535_reset(DeviceState *dev) +{ + PCA955xState *s = PCA955X(dev); + + s->regs[PCA9535_INPUT0] = 0xFF; /* All inputs high (pull-ups) */ + s->regs[PCA9535_INPUT1] = 0xFF; /* All inputs high (pull-ups) */ + s->regs[PCA9535_OUTPUT0] = 0xFF; /* All outputs high */ + s->regs[PCA9535_OUTPUT1] = 0xFF; /* All outputs high */ + s->regs[PCA9535_POLARITY0] = 0x00; /* No polarity inversion */ + s->regs[PCA9535_POLARITY1] = 0x00; /* No polarity inversion */ + s->regs[PCA9535_CONFIG0] = 0xFF; /* All pins as inputs */ + s->regs[PCA9535_CONFIG1] = 0xFF; /* All pins as inputs */ + + memset(s->ext_state, PCA9552_PIN_HIZ, PCA955X_PIN_COUNT_MAX); + pca955x_update_pin_input(s); + + s->pointer = 0xFF; + s->len = 0; +} + static void pca955x_initfn(Object *obj) { PCA955xClass *k = PCA955X_GET_CLASS(obj); @@ -XXX,XX +XXX,XX @@ static void pca9552_class_init(ObjectClass *oc, const void *data) dc->vmsd = &pca9552_vmstate; pc->max_reg = PCA9552_LS3; pc->pin_count = 16; + pc->has_led_support = true; +} + +static void pca9535_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PCA955xClass *pc = PCA955X_CLASS(oc); + + device_class_set_legacy_reset(dc, pca9535_reset); + dc->vmsd = &pca9552_vmstate; + pc->max_reg = PCA9535_CONFIG1; + pc->pin_count = 16; + pc->has_led_support = false; } static const TypeInfo pca9552_info = { @@ -XXX,XX +XXX,XX @@ static const TypeInfo pca9552_info = { .class_init = pca9552_class_init, }; +static const TypeInfo pca9535_info = { + .name = TYPE_PCA9535, + .parent = TYPE_PCA955X, + .class_init = pca9535_class_init, +}; + static void pca955x_register_types(void) { type_register_static(&pca955x_info); type_register_static(&pca9552_info); + type_register_static(&pca9535_info); } type_init(pca955x_register_types) -- 2.52.0
From: Patrick Williams <patrick@stwcx.xyz> A few entries in the catalina model were using the PCA9552 chip because it was "close enough" in function. Since there is a PCA9535 model now, switch to use it. Signed-off-by: Patrick Williams <patrick@stwcx.xyz> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260121-pca9535-v1-2-164640e622ff@stwcx.xyz Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast2600_catalina.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/aspeed_ast2600_catalina.c b/hw/arm/aspeed_ast2600_catalina.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast2600_catalina.c +++ b/hw/arm/aspeed_ast2600_catalina.c @@ -XXX,XX +XXX,XX @@ static void catalina_bmc_i2c_init(AspeedMachineState *bmc) /* i2c0mux1ch1 */ /* io_expander7 - pca9535@20 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), - TYPE_PCA9552, 0x20); + TYPE_PCA9535, 0x20); /* eeprom@50 */ at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x50, 8 * KiB, gb200io_eeprom, gb200io_eeprom_len); @@ -XXX,XX +XXX,XX @@ static void catalina_bmc_i2c_init(AspeedMachineState *bmc) /* i2c0mux4ch1 */ /* io_expander8 - pca9535@21 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), - TYPE_PCA9552, 0x21); + TYPE_PCA9535, 0x21); /* eeprom@50 */ at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x50, 8 * KiB, gb200io_eeprom, gb200io_eeprom_len); -- 2.52.0
The 'regs' array has ASPEED_ADC_NR_REGS (52) elements, while the memory region covers offsets 0x00-0xFC. The aspeed_adc_engine_write() function has an out-of-bounds write vulnerability when accessing unimplemented registers. Fix this by using 'return' instead of 'break' in the default case, which prevents execution from reaching the s->regs[reg] assignment for unimplemented registers. Reported-by: Elhrj Saad <saadelhrj@gmail.com> Fixes: 5857974d5d11 ("hw/adc: Add basic Aspeed ADC model") Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Link: https://lore.kernel.org/qemu-devel/20260126141820.719492-1-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/adc/aspeed_adc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/adc/aspeed_adc.c b/hw/adc/aspeed_adc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/adc/aspeed_adc.c +++ b/hw/adc/aspeed_adc.c @@ -XXX,XX +XXX,XX @@ static void aspeed_adc_engine_write(void *opaque, hwaddr addr, uint64_t value, qemu_log_mask(LOG_UNIMP, "%s: engine[%u]: " "0x%" HWADDR_PRIx " 0x%" PRIx64 "\n", __func__, s->engine_id, addr, value); - break; + /* Do not update the regs[] array */ + return; } s->regs[reg] = value; -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/arm/test_aspeed_ast2500.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/arm/test_aspeed_ast2500.py +++ b/tests/functional/arm/test_aspeed_ast2500.py @@ -XXX,XX +XXX,XX @@ def test_arm_ast2500_evb_buildroot(self): self.do_test_arm_aspeed_buildroot_poweroff() - ASSET_SDK_V908_AST2500 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2500-default-obmc.tar.gz', - 'c0a2ba169efd19be5eb77c50ec2a6afd9d826e196a0be3432f969fc72d4b7c0e') + ASSET_SDK_V1000_AST2500 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v10.00/ast2500-default-obmc.tar.gz', + '7d71a3f71d5f4d9f3451f59a73bf9baf8fd9f6a24107eb504a3216151a8b2b5b') def test_arm_ast2500_evb_sdk(self): self.set_machine('ast2500-evb') - self.archive_extract(self.ASSET_SDK_V908_AST2500) + self.archive_extract(self.ASSET_SDK_V1000_AST2500) self.do_test_arm_aspeed_sdk_start( self.scratch_file("ast2500-default", "image-bmc")) -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> AST2600 PCIe previously exposed a root bus at 0x80 with both a root device at 80:00.0 and a root port at 80:08.0. Recent ASPEED SDK PCIe driver updates decided to remove the root device and keep only a single root port. This behavior has already been accepted by the upstream Linux kernel. Update the QEMU PCIe model accordingly by dropping the root device implementation and related properties. AST2600 now matches the AST2700 PCIe topology and no longer supports the legacy RC_L layout. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/pci-host/aspeed_pcie.h | 9 ----- hw/pci-host/aspeed_pcie.c | 57 ------------------------------- 2 files changed, 66 deletions(-) diff --git a/include/hw/pci-host/aspeed_pcie.h b/include/hw/pci-host/aspeed_pcie.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/pci-host/aspeed_pcie.h +++ b/include/hw/pci-host/aspeed_pcie.h @@ -XXX,XX +XXX,XX @@ typedef struct AspeedPCIERootPortState { PCIESlot parent_obj; } AspeedPCIERootPortState; -#define TYPE_ASPEED_PCIE_ROOT_DEVICE "aspeed.pcie-root-device" -OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERootDeviceState, ASPEED_PCIE_ROOT_DEVICE); - -struct AspeedPCIERootDeviceState { - PCIBridge parent_obj; -}; - #define TYPE_ASPEED_PCIE_RC "aspeed.pcie-rc" OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERcState, ASPEED_PCIE_RC); @@ -XXX,XX +XXX,XX @@ struct AspeedPCIERcState { uint32_t rp_addr; uint32_t bus_nr; char name[16]; - bool has_rd; qemu_irq irq; - AspeedPCIERootDeviceState root_device; AspeedPCIERootPortState root_port; }; diff --git a/hw/pci-host/aspeed_pcie.c b/hw/pci-host/aspeed_pcie.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/aspeed_pcie.c +++ b/hw/pci-host/aspeed_pcie.c @@ -XXX,XX +XXX,XX @@ #include "hw/pci/msi.h" #include "trace.h" -/* - * PCIe Root Device - * This device exists only on AST2600. - */ - -static void aspeed_pcie_root_device_class_init(ObjectClass *klass, - const void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->desc = "ASPEED PCIe Root Device"; - k->vendor_id = PCI_VENDOR_ID_ASPEED; - k->device_id = 0x2600; - k->class_id = PCI_CLASS_BRIDGE_HOST; - k->subsystem_vendor_id = k->vendor_id; - k->subsystem_id = k->device_id; - k->revision = 0; - - /* - * PCI-facing part of the host bridge, - * not usable without the host-facing part - */ - dc->user_creatable = false; -} - -static const TypeInfo aspeed_pcie_root_device_info = { - .name = TYPE_ASPEED_PCIE_ROOT_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(AspeedPCIERootDeviceState), - .class_init = aspeed_pcie_root_device_class_init, - .interfaces = (const InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - /* * PCIe Root Port */ @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_rc_realize(DeviceState *dev, Error **errp) &rc->dram_alias); pci_setup_iommu(pci->bus, &aspeed_pcie_rc_iommu_ops, rc); - /* setup root device */ - if (rc->has_rd) { - object_initialize_child(OBJECT(rc), "root_device", &rc->root_device, - TYPE_ASPEED_PCIE_ROOT_DEVICE); - qdev_prop_set_int32(DEVICE(&rc->root_device), "addr", - PCI_DEVFN(0, 0)); - qdev_prop_set_bit(DEVICE(&rc->root_device), "multifunction", false); - if (!qdev_realize(DEVICE(&rc->root_device), BUS(pci->bus), errp)) { - return; - } - } - /* setup root port */ qdev_prop_set_int32(DEVICE(&rc->root_port), "addr", rc->rp_addr); qdev_prop_set_uint16(DEVICE(&rc->root_port), "chassis", cfg->id); @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_rc_instance_init(Object *obj) static const Property aspeed_pcie_rc_props[] = { DEFINE_PROP_UINT32("bus-nr", AspeedPCIERcState, bus_nr, 0), - DEFINE_PROP_BOOL("has-rd", AspeedPCIERcState, has_rd, 0), DEFINE_PROP_UINT32("rp-addr", AspeedPCIERcState, rp_addr, 0), DEFINE_PROP_UINT32("msi-addr", AspeedPCIERcState, msi_addr, 0), DEFINE_PROP_UINT64("dram-base", AspeedPCIERcState, dram_base, 0), @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&s->rc), "bus-nr", apc->rc_bus_nr, &error_abort); - object_property_set_bool(OBJECT(&s->rc), "has-rd", - apc->rc_has_rd, - &error_abort); object_property_set_int(OBJECT(&s->rc), "rp-addr", apc->rc_rp_addr, &error_abort); @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_cfg_class_init(ObjectClass *klass, const void *data) apc->nr_regs = 0x100 >> 2; apc->rc_msi_addr = 0x1e77005C; apc->rc_bus_nr = 0x80; - apc->rc_has_rd = true; apc->rc_rp_addr = PCI_DEVFN(8, 0); } @@ -XXX,XX +XXX,XX @@ static void aspeed_2700_pcie_cfg_class_init(ObjectClass *klass, apc->nr_regs = 0x100 >> 2; apc->rc_msi_addr = 0x000000F0; apc->rc_bus_nr = 0; - apc->rc_has_rd = false; apc->rc_rp_addr = PCI_DEVFN(0, 0); } @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_2700_pcie_phy_info = { static void aspeed_pcie_register_types(void) { type_register_static(&aspeed_pcie_rc_info); - type_register_static(&aspeed_pcie_root_device_info); type_register_static(&aspeed_pcie_root_port_info); type_register_static(&aspeed_pcie_cfg_info); type_register_static(&aspeed_2700_pcie_cfg_info); -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> The original AST2600 PCIe design supported both RC_L and RC_H, using root bus number 0 for RC_L and 0x80 for RC_H. In that model, the root port appeared as 80:08.0 and QEMU carried a "bus-nr" property plus a config-space bus remap to translate bus 0x80 to bus 0x00 for PCI enumeration. Linux mainline has since dropped RC_L support and updated the RC_H root bus number to start at 0. The root port is now enumerated as 00:08.0, matching the default QEMU PCIe subsystem root bus numbering. Remove the bus number setting and the AST2600 bus remap logic, and drop the corresponding "bus-nr"/rc_bus_nr fields and property plumbing. QEMU now relies on the default root bus 0 behavior. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-4-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/pci-host/aspeed_pcie.h | 2 -- hw/pci-host/aspeed_pcie.c | 19 +------------------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/include/hw/pci-host/aspeed_pcie.h b/include/hw/pci-host/aspeed_pcie.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/pci-host/aspeed_pcie.h +++ b/include/hw/pci-host/aspeed_pcie.h @@ -XXX,XX +XXX,XX @@ struct AspeedPCIERcState { uint64_t dram_base; uint32_t msi_addr; uint32_t rp_addr; - uint32_t bus_nr; char name[16]; qemu_irq irq; @@ -XXX,XX +XXX,XX @@ struct AspeedPCIECfgClass { uint32_t rc_msi_addr; uint32_t rc_rp_addr; - uint64_t rc_bus_nr; uint64_t nr_regs; bool rc_has_rd; }; diff --git a/hw/pci-host/aspeed_pcie.c b/hw/pci-host/aspeed_pcie.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/aspeed_pcie.c +++ b/hw/pci-host/aspeed_pcie.c @@ -XXX,XX +XXX,XX @@ static const char *aspeed_pcie_rc_root_bus_path(PCIHostState *host_bridge, AspeedPCIECfgState *cfg = container_of(rc, AspeedPCIECfgState, rc); - snprintf(rc->name, sizeof(rc->name), "%04x:%02x", cfg->id, rc->bus_nr); + snprintf(rc->name, sizeof(rc->name), "%04x:00", cfg->id); return rc->name; } @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_rc_instance_init(Object *obj) } static const Property aspeed_pcie_rc_props[] = { - DEFINE_PROP_UINT32("bus-nr", AspeedPCIERcState, bus_nr, 0), DEFINE_PROP_UINT32("rp-addr", AspeedPCIERcState, rp_addr, 0), DEFINE_PROP_UINT32("msi-addr", AspeedPCIERcState, msi_addr, 0), DEFINE_PROP_UINT64("dram-base", AspeedPCIERcState, dram_base, 0), @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_cfg_readwrite(AspeedPCIECfgState *s, offset = cfg_addr & 0xffc; pci = PCI_HOST_BRIDGE(rc); - - /* - * On the AST2600, the RC_H bus number range from 0x80 to 0xFF, with the - * root device and root port assigned to bus 0x80 instead of the standard - * 0x00. To allow the PCI subsystem to correctly discover devices on the - * root bus, bus 0x80 is remapped to 0x00. - */ - if (bus == rc->bus_nr) { - bus = 0; - } - pdev = pci_find_device(pci->bus, bus, devfn); if (!pdev) { s->regs[desc->rdata_reg] = ~0; @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp) apc->nr_regs << 2); sysbus_init_mmio(sbd, &s->mmio); - object_property_set_int(OBJECT(&s->rc), "bus-nr", - apc->rc_bus_nr, - &error_abort); object_property_set_int(OBJECT(&s->rc), "rp-addr", apc->rc_rp_addr, &error_abort); @@ -XXX,XX +XXX,XX @@ static void aspeed_pcie_cfg_class_init(ObjectClass *klass, const void *data) apc->reg_map = &aspeed_regmap; apc->nr_regs = 0x100 >> 2; apc->rc_msi_addr = 0x1e77005C; - apc->rc_bus_nr = 0x80; apc->rc_rp_addr = PCI_DEVFN(8, 0); } @@ -XXX,XX +XXX,XX @@ static void aspeed_2700_pcie_cfg_class_init(ObjectClass *klass, apc->reg_map = &aspeed_2700_regmap; apc->nr_regs = 0x100 >> 2; apc->rc_msi_addr = 0x000000F0; - apc->rc_bus_nr = 0; apc->rc_rp_addr = PCI_DEVFN(0, 0); } -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Historically, the ASPEED PCIe driver supported both RC_L and RC_H, with RC_L using MMIO window 0x60000000 - 0x70000000 and RC_H using 0x70000000 - 0x80000000. Mainline Linux has dropped RC_L support and now supports RC_H only, updating RC_H to use a single combined MMIO window 0x60000000 - 0x80000000. Update the AST2600 QEMU model accordingly by moving PCIE_MMIO1 base to 0x60000000 and increasing the aliased MMIO size to 0x20000000. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-5-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast2600.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_FSI1] = 0x1E79B000, [ASPEED_DEV_FSI2] = 0x1E79B100, [ASPEED_DEV_I3C] = 0x1E7A0000, - [ASPEED_DEV_PCIE_MMIO1] = 0x70000000, + [ASPEED_DEV_PCIE_MMIO1] = 0x60000000, [ASPEED_DEV_SDRAM] = 0x80000000, }; @@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_calc_affinity(int cpu) * * Model scope / limitations: * - Firmware supports RC_H only; this QEMU model does not support RC_L. - * - RC_H uses PHY1 and the MMIO window [0x70000000, 0x80000000] + * - RC_H uses PHY1 and the MMIO window [0x60000000, 0x80000000] * (aka MMIO1). * * Indexing convention (this model): * - Expose a single logical instance at index 0. * - pcie[0] -> hardware RC_H (PCIe1) * - phy[0] -> hardware PHY1 - * - mmio.0 -> guest address range MMIO1: 0x70000000-0x80000000 + * - mmio.0 -> guest address range MMIO1: 0x60000000-0x80000000 * - RC_L / PCIe0 is not created and mapped. */ static bool aspeed_soc_ast2600_pcie_realize(DeviceState *dev, Error **errp) @@ -XXX,XX +XXX,XX @@ static bool aspeed_soc_ast2600_pcie_realize(DeviceState *dev, Error **errp) memory_region_init_alias(&s->pcie_mmio_alias[0], OBJECT(&s->pcie[0].rc), "aspeed.pcie-mmio", mmio_mr, sc->memmap[ASPEED_DEV_PCIE_MMIO1], - 0x10000000); + 0x20000000); memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_PCIE_MMIO1], &s->pcie_mmio_alias[0]); -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Drop root device and set root bus number to 0. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-6-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- .../functional/arm/test_aspeed_ast2600_sdk.py | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/tests/functional/arm/test_aspeed_ast2600_sdk.py b/tests/functional/arm/test_aspeed_ast2600_sdk.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/arm/test_aspeed_ast2600_sdk.py +++ b/tests/functional/arm/test_aspeed_ast2600_sdk.py @@ -XXX,XX +XXX,XX @@ class AST2600Machine(AspeedTest): - ASSET_SDK_V908_AST2600 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2600-default-obmc.tar.gz', - 'a0414f14ad696550efe083c2156dbeda855c08cc9ae7f40fe1b41bf292295f82') + ASSET_SDK_V1100_AST2600 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2600-default-obmc.tar.gz', + '64d8926a7d01b649168be96c986603b5690f06391286c438a3a772c8c7039e93') def do_ast2600_pcie_test(self): exec_command_and_wait_for_pattern(self, - 'lspci -s 80:00.0', - '80:00.0 Host bridge: ' - 'ASPEED Technology, Inc. Device 2600') - exec_command_and_wait_for_pattern(self, - 'lspci -s 80:08.0', - '80:08.0 PCI bridge: ' + 'lspci -s 00:08.0', + '00:08.0 PCI bridge: ' 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge') exec_command_and_wait_for_pattern(self, - 'lspci -s 81:00.0', - '81:00.0 Ethernet controller: ' + 'lspci -s 01:00.0', + '01:00.0 Ethernet controller: ' 'Intel Corporation 82574L Gigabit Network Connection') exec_command_and_wait_for_pattern(self, 'ip addr show dev eth4', @@ -XXX,XX +XXX,XX @@ def test_arm_ast2600_evb_sdk(self): self.set_machine('ast2600-evb') self.require_netdev('user') - self.archive_extract(self.ASSET_SDK_V908_AST2600) + self.archive_extract(self.ASSET_SDK_V1100_AST2600) self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test') @@ -XXX,XX +XXX,XX @@ def test_arm_ast2600_evb_sdk(self): def test_arm_ast2600_otp_blockdev_device(self): self.vm.set_machine("ast2600-evb") - image_path = self.archive_extract(self.ASSET_SDK_V908_AST2600) + image_path = self.archive_extract(self.ASSET_SDK_V1100_AST2600) otp_img = self.generate_otpmem_image() self.vm.set_console() -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-7-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/arm/test_aspeed_ast1060.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/functional/arm/test_aspeed_ast1060.py b/tests/functional/arm/test_aspeed_ast1060.py index XXXXXXX..XXXXXXX 100644 --- a/tests/functional/arm/test_aspeed_ast1060.py +++ b/tests/functional/arm/test_aspeed_ast1060.py @@ -XXX,XX +XXX,XX @@ class AST1060Machine(AspeedTest): - ASSET_ASPEED_AST1060_PROT_3_02 = Asset( + ASSET_ASPEED_AST1060_PROT_3_04 = Asset( ('https://github.com/AspeedTech-BMC' - '/aspeed-zephyr-project/releases/download/v03.02' - '/ast1060_prot_v03.02.tgz'), - 'dd5f1adc935316ddd1906506a02e15567bd7290657b52320f1a225564cc175bd') + '/aspeed-zephyr-project/releases/download/v03.04' + '/ast1060_prot_v03.04.tgz'), + 'c0319df55f5b7a547efefc5a6ba374b881223d5fe1a776bfdd36f97fd1f31d50') - def test_arm_ast1060_prot_3_02(self): + def test_arm_ast1060_prot_3_04(self): self.set_machine('ast1060-evb') kernel_name = "ast1060_prot/zephyr.bin" kernel_file = self.archive_extract( - self.ASSET_ASPEED_AST1060_PROT_3_02, member=kernel_name) + self.ASSET_ASPEED_AST1060_PROT_3_04, member=kernel_name) self.vm.set_console() self.vm.add_args('-kernel', kernel_file, '-nographic') @@ -XXX,XX +XXX,XX @@ def test_arm_ast1060_otp_blockdev_device(self): self.vm.set_machine("ast1060-evb") kernel_name = "ast1060_prot/zephyr.bin" - kernel_file = self.archive_extract(self.ASSET_ASPEED_AST1060_PROT_3_02, + kernel_file = self.archive_extract(self.ASSET_ASPEED_AST1060_PROT_3_04, member=kernel_name) otp_img = self.generate_otpmem_image() -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260127032348.2238527-8-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/arm/test_aspeed_ast1030.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/arm/test_aspeed_ast1030.py +++ b/tests/functional/arm/test_aspeed_ast1030.py @@ -XXX,XX +XXX,XX @@ class AST1030Machine(AspeedTest): - ASSET_ZEPHYR_3_03 = Asset( + ASSET_ZEPHYR_3_05 = Asset( ('https://github.com/AspeedTech-BMC' - '/zephyr/releases/download/v00.03.03/ast1030-evb-demo.zip'), - '27cd73cdee6374bceb4ee58b3ace87989fa3f0684f4e612510804b588b24d4e0') + '/zephyr/releases/download/v00.03.05/ast1030-evb-demo.zip'), + '057528d343490b1fbb5a721e91084b4f04fec60dc114bd65e724554f9c217f4b') - def test_arm_ast1030_zephyros_3_03(self): + def test_arm_ast1030_zephyros_3_05(self): self.set_machine('ast1030-evb') kernel_name = "ast1030-evb-demo/zephyr.elf" kernel_file = self.archive_extract( - self.ASSET_ZEPHYR_3_03, member=kernel_name) + self.ASSET_ZEPHYR_3_05, member=kernel_name) self.vm.set_console() self.vm.add_args('-kernel', kernel_file, '-nographic') @@ -XXX,XX +XXX,XX @@ def test_arm_ast1030_otp_blockdev_device(self): self.vm.set_machine("ast1030-evb") kernel_name = "ast1030-evb-demo/zephyr.elf" - kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_03, + kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_05, member=kernel_name) otp_img = self.generate_otpmem_image() -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> EHCI3 and EHCI4 were missing entries in aspeed_soc_ast2700a1_irqmap, so their source IRQs were never routed through the INTC OR-gates. As a result, EHCI3/4 interrupts were not propagated to the GIC, causing incorrect interrupt behavior for these controllers. Add EHCI3 and EHCI4 to the IRQ map and route them to the same INTC group as other shared peripherals, ensuring their interrupts are properly connected to the GIC. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Fixes: ba27ba302a264117c8b8427f944ced1bed17c438 ("hw/arm: ast27x0: Wire up EHCI controllers") Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast27x0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2700a1_irqmap[] = { [ASPEED_DEV_ETH1] = 196, [ASPEED_DEV_ETH2] = 196, [ASPEED_DEV_ETH3] = 196, + [ASPEED_DEV_EHCI3] = 196, + [ASPEED_DEV_EHCI4] = 196, [ASPEED_DEV_PECI] = 197, [ASPEED_DEV_SDHCI] = 197, }; -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Sort the SSP and TSP memmap tables to improve readability and make the definitions easier to maintain. No functional change. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast27x0-ssp.c | 10 +++++----- hw/arm/aspeed_ast27x0-tsp.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0-ssp.c +++ b/hw/arm/aspeed_ast27x0-ssp.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast27x0ssp_memmap[] = { [ASPEED_DEV_SRAM] = 0x70000000, [ASPEED_DEV_INTC] = 0x72100000, [ASPEED_DEV_SCU] = 0x72C02000, + [ASPEED_DEV_TIMER1] = 0x72C10000, + [ASPEED_DEV_UART4] = 0x72C1A000, + [ASPEED_DEV_IPC0] = 0x72C1C000, [ASPEED_DEV_SCUIO] = 0x74C02000, + [ASPEED_DEV_INTCIO] = 0x74C18000, [ASPEED_DEV_UART0] = 0x74C33000, [ASPEED_DEV_UART1] = 0x74C33100, [ASPEED_DEV_UART2] = 0x74C33200, [ASPEED_DEV_UART3] = 0x74C33300, - [ASPEED_DEV_UART4] = 0x72C1A000, - [ASPEED_DEV_INTCIO] = 0x74C18000, - [ASPEED_DEV_IPC0] = 0x72C1C000, - [ASPEED_DEV_IPC1] = 0x74C39000, [ASPEED_DEV_UART5] = 0x74C33400, [ASPEED_DEV_UART6] = 0x74C33500, [ASPEED_DEV_UART7] = 0x74C33600, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast27x0ssp_memmap[] = { [ASPEED_DEV_UART10] = 0x74C33900, [ASPEED_DEV_UART11] = 0x74C33A00, [ASPEED_DEV_UART12] = 0x74C33B00, - [ASPEED_DEV_TIMER1] = 0x72C10000, + [ASPEED_DEV_IPC1] = 0x74C39000, }; static const int aspeed_soc_ast27x0ssp_irqmap[] = { diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0-tsp.c +++ b/hw/arm/aspeed_ast27x0-tsp.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast27x0tsp_memmap[] = { [ASPEED_DEV_SRAM] = 0x70000000, [ASPEED_DEV_INTC] = 0x72100000, [ASPEED_DEV_SCU] = 0x72C02000, + [ASPEED_DEV_TIMER1] = 0x72C10000, + [ASPEED_DEV_UART4] = 0x72C1A000, + [ASPEED_DEV_IPC0] = 0x72C1C000, [ASPEED_DEV_SCUIO] = 0x74C02000, + [ASPEED_DEV_INTCIO] = 0x74C18000, [ASPEED_DEV_UART0] = 0x74C33000, [ASPEED_DEV_UART1] = 0x74C33100, [ASPEED_DEV_UART2] = 0x74C33200, [ASPEED_DEV_UART3] = 0x74C33300, - [ASPEED_DEV_UART4] = 0x72C1A000, - [ASPEED_DEV_INTCIO] = 0x74C18000, - [ASPEED_DEV_IPC0] = 0x72C1C000, - [ASPEED_DEV_IPC1] = 0x74C39000, [ASPEED_DEV_UART5] = 0x74C33400, [ASPEED_DEV_UART6] = 0x74C33500, [ASPEED_DEV_UART7] = 0x74C33600, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast27x0tsp_memmap[] = { [ASPEED_DEV_UART10] = 0x74C33900, [ASPEED_DEV_UART11] = 0x74C33A00, [ASPEED_DEV_UART12] = 0x74C33B00, - [ASPEED_DEV_TIMER1] = 0x72C10000, + [ASPEED_DEV_IPC1] = 0x74C39000, }; static const int aspeed_soc_ast27x0tsp_irqmap[] = { -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Sort the SSP and TSP IRQ map tables to improve readability and make the definitions easier to maintain. No functional change. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-4-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast27x0-ssp.c | 4 ++-- hw/arm/aspeed_ast27x0-tsp.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0-ssp.c +++ b/hw/arm/aspeed_ast27x0-ssp.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast27x0ssp_memmap[] = { }; static const int aspeed_soc_ast27x0ssp_irqmap[] = { + [ASPEED_DEV_UART4] = 8, [ASPEED_DEV_SCU] = 12, + [ASPEED_DEV_TIMER1] = 16, [ASPEED_DEV_UART0] = 164, [ASPEED_DEV_UART1] = 164, [ASPEED_DEV_UART2] = 164, [ASPEED_DEV_UART3] = 164, - [ASPEED_DEV_UART4] = 8, [ASPEED_DEV_UART5] = 164, [ASPEED_DEV_UART6] = 164, [ASPEED_DEV_UART7] = 164, @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast27x0ssp_irqmap[] = { [ASPEED_DEV_UART10] = 164, [ASPEED_DEV_UART11] = 164, [ASPEED_DEV_UART12] = 164, - [ASPEED_DEV_TIMER1] = 16, }; /* SSPINT 164 */ diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0-tsp.c +++ b/hw/arm/aspeed_ast27x0-tsp.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast27x0tsp_memmap[] = { }; static const int aspeed_soc_ast27x0tsp_irqmap[] = { + [ASPEED_DEV_UART4] = 8, [ASPEED_DEV_SCU] = 12, + [ASPEED_DEV_TIMER1] = 16, [ASPEED_DEV_UART0] = 164, [ASPEED_DEV_UART1] = 164, [ASPEED_DEV_UART2] = 164, [ASPEED_DEV_UART3] = 164, - [ASPEED_DEV_UART4] = 8, [ASPEED_DEV_UART5] = 164, [ASPEED_DEV_UART6] = 164, [ASPEED_DEV_UART7] = 164, @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast27x0tsp_irqmap[] = { [ASPEED_DEV_UART10] = 164, [ASPEED_DEV_UART11] = 164, [ASPEED_DEV_UART12] = 164, - [ASPEED_DEV_TIMER1] = 16, }; /* TSPINT 164 */ -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> In the previous design, the I2C model updated dma_dram_offset only when firmware programmed the RX/TX DMA buffer address registers. The firmware used to rewrite these registers before issuing each DMA command. The firmware driver behavior has changed to program the DMA address registers only once during I2C initialization. As a result, the I2C model no longer refreshes dma_dram_offset, causing DMA to move data into an incorrect DRAM address. Fix this by introducing helper functions to update dma_dram_offset from the DMA address registers, and invoke them right before handling TX/RX DMA operations. This guarantees DMA always uses the correct buffer address even if the registers are programmed only once. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Fixes: c400c38854017eeccda63115814eba4c3ef2b51f ("hw/i2c/aspeed: Introduce a new dma_dram_offset attribute in AspeedI2Cbus") Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-5-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/i2c/aspeed_i2c.c | 87 +++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_bus_old_read(AspeedI2CBus *bus, hwaddr offset, value = -1; break; } - - value = extract64(bus->dma_dram_offset, 0, 32); break; case A_I2CD_DMA_LEN: if (!aic->has_dma) { @@ -XXX,XX +XXX,XX @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus) return SHARED_ARRAY_FIELD_EX32(bus->regs, R_I2CD_CMD, TX_STATE); } +/* + * The AST2700 support the maximum DRAM size is 8 GB. + * The DRAM offset range is from 0x0_0000_0000 to + * 0x1_FFFF_FFFF and it is enough to use bits [33:0] + * saving the dram offset. + * Therefore, save the high part physical address bit[1:0] + * of Tx/Rx buffer address as dma_dram_offset bit[33:32]. + */ +static void aspeed_i2c_set_tx_dma_dram_offset(AspeedI2CBus *bus) +{ + AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller); + uint32_t value; + + assert(aic->has_dma); + + if (aspeed_i2c_is_new_mode(bus->controller)) { + value = bus->regs[R_I2CM_DMA_TX_ADDR]; + bus->dma_dram_offset = + deposit64(bus->dma_dram_offset, 0, 32, + FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR)); + if (!aic->has_dma64) { + value = bus->regs[R_I2CM_DMA_TX_ADDR_HI]; + bus->dma_dram_offset = + deposit64(bus->dma_dram_offset, 32, 32, + extract32(value, 0, 2)); + } + } else { + value = bus->regs[R_I2CD_DMA_ADDR]; + bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, + value & 0x3ffffffc); + } +} + +static void aspeed_i2c_set_rx_dma_dram_offset(AspeedI2CBus *bus) +{ + AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller); + uint32_t value; + + assert(aic->has_dma); + + if (aspeed_i2c_is_new_mode(bus->controller)) { + value = bus->regs[R_I2CM_DMA_RX_ADDR]; + bus->dma_dram_offset = + deposit64(bus->dma_dram_offset, 0, 32, + FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR)); + if (!aic->has_dma64) { + value = bus->regs[R_I2CM_DMA_RX_ADDR_HI]; + bus->dma_dram_offset = + deposit64(bus->dma_dram_offset, 32, 32, + extract32(value, 0, 2)); + } + } else { + value = bus->regs[R_I2CD_DMA_ADDR]; + bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, + value & 0x3ffffffc); + } +} + static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data) { MemTxResult result; @@ -XXX,XX +XXX,XX @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus) if (aspeed_i2c_is_new_mode(bus->controller)) { ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, TX_LEN, 0); } + aspeed_i2c_set_tx_dma_dram_offset(bus); while (bus->regs[reg_dma_len]) { uint8_t data; ret = aspeed_i2c_dma_read(bus, &data); @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus) ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, RX_LEN, 0); } + aspeed_i2c_set_rx_dma_dram_offset(bus); while (bus->regs[reg_dma_len]) { MemTxResult result; @@ -XXX,XX +XXX,XX @@ static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus) } else if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_DMA_EN)) { uint8_t data; + aspeed_i2c_set_tx_dma_dram_offset(bus); aspeed_i2c_dma_read(bus, &data); return data; } else { @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, case A_I2CM_DMA_TX_ADDR: bus->regs[R_I2CM_DMA_TX_ADDR] = FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR); - bus->dma_dram_offset = - deposit64(bus->dma_dram_offset, 0, 32, - FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR)); break; case A_I2CM_DMA_RX_ADDR: bus->regs[R_I2CM_DMA_RX_ADDR] = FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR); - bus->dma_dram_offset = - deposit64(bus->dma_dram_offset, 0, 32, - FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR)); break; case A_I2CM_DMA_LEN: w1t = FIELD_EX32(value, I2CM_DMA_LEN, RX_BUF_LEN_W1T) || @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, qemu_log_mask(LOG_UNIMP, "%s: Slave mode DMA TX is not implemented\n", __func__); break; - - /* - * The AST2700 support the maximum DRAM size is 8 GB. - * The DRAM offset range is from 0x0_0000_0000 to - * 0x1_FFFF_FFFF and it is enough to use bits [33:0] - * saving the dram offset. - * Therefore, save the high part physical address bit[1:0] - * of Tx/Rx buffer address as dma_dram_offset bit[33:32]. - */ case A_I2CM_DMA_TX_ADDR_HI: if (!aic->has_dma64) { qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA 64 bits support\n", @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CM_DMA_TX_ADDR_HI] = FIELD_EX32(value, I2CM_DMA_TX_ADDR_HI, ADDR_HI); - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32, - extract32(value, 0, 2)); break; case A_I2CM_DMA_RX_ADDR_HI: if (!aic->has_dma64) { @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CM_DMA_RX_ADDR_HI] = FIELD_EX32(value, I2CM_DMA_RX_ADDR_HI, ADDR_HI); - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32, - extract32(value, 0, 2)); break; case A_I2CS_DMA_TX_ADDR_HI: qemu_log_mask(LOG_UNIMP, @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_new_write(AspeedI2CBus *bus, hwaddr offset, bus->regs[R_I2CS_DMA_RX_ADDR_HI] = FIELD_EX32(value, I2CS_DMA_RX_ADDR_HI, ADDR_HI); - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32, - extract32(value, 0, 2)); break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", @@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_old_write(AspeedI2CBus *bus, hwaddr offset, qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__); break; } - - bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32, - value & 0x3ffffffc); break; case A_I2CD_DMA_LEN: -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> PCIe2 is disabled by default starting from SDK v10.00. Add a helper function to stop U-Boot autoboot and update the device tree at runtime, setting the PCIe2 node status to "okay" before booting Linux. This allows the AST2700 functional test to verify the PCIe2 root complex behavior correctly. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-6-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- .../functional/aarch64/test_aspeed_ast2700.py | 18 ++++++++++++++++-- .../aarch64/test_aspeed_ast2700fc.py | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700.py +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -XXX,XX +XXX,XX @@ import os from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern +from qemu_test import wait_for_console_pattern, exec_command from qemu_test import exec_command_and_wait_for_pattern @@ -XXX,XX +XXX,XX @@ def verify_vbootrom_firmware_flow(self): wait_for_console_pattern(self, 'done') wait_for_console_pattern(self, 'Jumping to BL31 (Trusted Firmware-A)') + def enable_ast2700_pcie2(self): + wait_for_console_pattern(self, 'Hit any key to stop autoboot') + exec_command_and_wait_for_pattern(self, '\012', '=>') + exec_command_and_wait_for_pattern(self, + 'cp 100420000 403000000 900000', '=>') + exec_command_and_wait_for_pattern(self, + 'bootm start 403000000', '=>') + exec_command_and_wait_for_pattern(self, 'bootm loados', '=>') + exec_command_and_wait_for_pattern(self, 'bootm ramdisk', '=>') + exec_command_and_wait_for_pattern(self, 'bootm prep', '=>') + exec_command_and_wait_for_pattern(self, + 'fdt set /soc@14000000/pcie@140d0000 status "okay"', '=>') + exec_command(self, 'bootm go') + def verify_openbmc_boot_start(self): wait_for_console_pattern(self, 'U-Boot 2023.10') - wait_for_console_pattern(self, '## Loading kernel from FIT Image') + self.enable_ast2700_pcie2() wait_for_console_pattern(self, 'Linux version ') def verify_openbmc_boot_and_login(self, name): diff --git a/tests/functional/aarch64/test_aspeed_ast2700fc.py b/tests/functional/aarch64/test_aspeed_ast2700fc.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700fc.py +++ b/tests/functional/aarch64/test_aspeed_ast2700fc.py @@ -XXX,XX +XXX,XX @@ import os from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern +from qemu_test import wait_for_console_pattern, exec_command from qemu_test import exec_command_and_wait_for_pattern @@ -XXX,XX +XXX,XX @@ def do_test_aarch64_aspeed_sdk_start(self, image): self.vm.launch() + def enable_ast2700_pcie2(self): + wait_for_console_pattern(self, 'Hit any key to stop autoboot') + exec_command_and_wait_for_pattern(self, '\012', '=>') + exec_command_and_wait_for_pattern(self, + 'cp 100420000 403000000 900000', '=>') + exec_command_and_wait_for_pattern(self, + 'bootm start 403000000', '=>') + exec_command_and_wait_for_pattern(self, 'bootm loados', '=>') + exec_command_and_wait_for_pattern(self, 'bootm ramdisk', '=>') + exec_command_and_wait_for_pattern(self, 'bootm prep', '=>') + exec_command_and_wait_for_pattern(self, + 'fdt set /soc@14000000/pcie@140d0000 status "okay"', '=>') + exec_command(self, 'bootm go') + def verify_openbmc_boot_and_login(self, name): wait_for_console_pattern(self, 'U-Boot 2023.10') - wait_for_console_pattern(self, '## Loading kernel from FIT Image') + self.enable_ast2700_pcie2() wait_for_console_pattern(self, 'Starting kernel ...') wait_for_console_pattern(self, f'{name} login:') -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-7-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- .../functional/aarch64/test_aspeed_ast2700.py | 60 +++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700.py +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -XXX,XX +XXX,XX @@ def do_test_aarch64_aspeed_sdk_start(self, image): self.vm.launch() def verify_vbootrom_firmware_flow(self): - wait_for_console_pattern(self, 'Found valid FIT image') - wait_for_console_pattern(self, '[uboot] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, '[fdt] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, '[tee] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, '[atf] loading') - wait_for_console_pattern(self, 'done') + wait_for_console_pattern(self, 'Found valid caliptra flash image') + wait_for_console_pattern(self, 'Check flash image checksum') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Read abb header') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Read soc manifest') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Load atf image') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Load optee image') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Load uboot image') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Load ssp image') + wait_for_console_pattern(self, 'pass') + wait_for_console_pattern(self, 'Load tsp image') + wait_for_console_pattern(self, 'pass') wait_for_console_pattern(self, 'Jumping to BL31 (Trusted Firmware-A)') def enable_ast2700_pcie2(self): @@ -XXX,XX +XXX,XX @@ def verify_openbmc_boot_and_login(self, name): exec_command_and_wait_for_pattern(self, 'root', 'Password:') exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#') - ASSET_SDK_V908_AST2700A1 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz', - 'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd') + ASSET_SDK_V1100_AST2700A1 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-obmc.tar.gz', + 'd5ceed511cd0dfefbb102fff2d731159e0472948a28066dc0d90bcd54be76525') def do_ast2700_i2c_test(self): exec_command_and_wait_for_pattern(self, @@ -XXX,XX +XXX,XX @@ def do_ast2700_pcie_test(self): def start_ast2700_test(self, name): num_cpu = 4 - uboot_size = os.path.getsize(self.scratch_file(name, - 'u-boot-nodtb.bin')) - uboot_dtb_load_addr = hex(0x400000000 + uboot_size) - load_images_list = [ { 'addr': '0x400000000', - 'file': self.scratch_file(name, - 'u-boot-nodtb.bin') - }, - { - 'addr': str(uboot_dtb_load_addr), - 'file': self.scratch_file(name, 'u-boot.dtb') + 'file': self.scratch_file(name, 'u-boot.bin') }, { 'addr': '0x430000000', @@ -XXX,XX +XXX,XX @@ def start_ast2700_test(self, name): }, { 'addr': '0x430080000', - 'file': self.scratch_file(name, 'optee', - 'tee-raw.bin') + 'file': self.scratch_file(name, 'optee', 'tee-raw.bin') } ] @@ -XXX,XX +XXX,XX @@ def start_ast2700_test_vbootrom(self, name): self.do_test_aarch64_aspeed_sdk_start( self.scratch_file(name, 'image-bmc')) - def test_aarch64_ast2700a1_evb_sdk_v09_08(self): + def test_aarch64_ast2700a1_evb_sdk_v11_00(self): self.set_machine('ast2700a1-evb') self.require_netdev('user') - self.archive_extract(self.ASSET_SDK_V908_AST2700A1) + self.archive_extract(self.ASSET_SDK_V1100_AST2700A1) self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2') self.vm.add_args('-netdev', 'user,id=net1') - self.start_ast2700_test('ast2700-default') - self.verify_openbmc_boot_and_login('ast2700-default') + self.start_ast2700_test('ast2700-a1') + self.verify_openbmc_boot_and_login('ast2700-a1') self.do_ast2700_i2c_test() self.do_ast2700_pcie_test() - def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_08(self): + def test_aarch64_ast2700a1_evb_sdk_vbootrom_v11_00(self): self.set_machine('ast2700a1-evb') self.require_netdev('user') - self.archive_extract(self.ASSET_SDK_V908_AST2700A1) + self.archive_extract(self.ASSET_SDK_V1100_AST2700A1) self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2') self.vm.add_args('-netdev', 'user,id=net1') - self.start_ast2700_test_vbootrom('ast2700-default') + self.start_ast2700_test_vbootrom('ast2700-a1') self.verify_vbootrom_firmware_flow() self.verify_openbmc_boot_start() -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-8-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- .../aarch64/test_aspeed_ast2700fc.py | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/tests/functional/aarch64/test_aspeed_ast2700fc.py b/tests/functional/aarch64/test_aspeed_ast2700fc.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700fc.py +++ b/tests/functional/aarch64/test_aspeed_ast2700fc.py @@ -XXX,XX +XXX,XX @@ def load_ast2700fc_coprocessor(self, name): self.vm.add_args('-device', f'loader,file={file},cpu-num={cpu_num}') - ASSET_SDK_V908_AST2700 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz', - 'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd') + ASSET_SDK_V1100_AST2700 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-obmc.tar.gz', + 'd5ceed511cd0dfefbb102fff2d731159e0472948a28066dc0d90bcd54be76525') def do_ast2700_i2c_test(self): exec_command_and_wait_for_pattern(self, @@ -XXX,XX +XXX,XX @@ def do_ast2700fc_tsp_test(self): def start_ast2700fc_test(self, name): ca35_core = 4 - uboot_size = os.path.getsize(self.scratch_file(name, - 'u-boot-nodtb.bin')) - uboot_dtb_load_addr = hex(0x400000000 + uboot_size) - load_images_list = [ { 'addr': '0x400000000', - 'file': self.scratch_file(name, - 'u-boot-nodtb.bin') - }, - { - 'addr': str(uboot_dtb_load_addr), - 'file': self.scratch_file(name, 'u-boot.dtb') + 'file': self.scratch_file(name, 'u-boot.bin') }, { 'addr': '0x430000000', @@ -XXX,XX +XXX,XX @@ def start_ast2700fc_test(self, name): }, { 'addr': '0x430080000', - 'file': self.scratch_file(name, 'optee', - 'tee-raw.bin') + 'file': self.scratch_file(name, 'optee', 'tee-raw.bin') } ] @@ -XXX,XX +XXX,XX @@ def start_ast2700fc_test_vbootrom(self, name): self.do_test_aarch64_aspeed_sdk_start( self.scratch_file(name, 'image-bmc')) - def test_aarch64_ast2700fc_sdk_v09_08(self): + def test_aarch64_ast2700fc_sdk_v11_00(self): self.set_machine('ast2700fc') self.require_netdev('user') - self.archive_extract(self.ASSET_SDK_V908_AST2700) - self.start_ast2700fc_test('ast2700-default') - self.verify_openbmc_boot_and_login('ast2700-default') + self.archive_extract(self.ASSET_SDK_V1100_AST2700) + self.start_ast2700fc_test('ast2700-a1') + self.verify_openbmc_boot_and_login('ast2700-a1') self.do_ast2700_i2c_test() self.do_ast2700_pcie_test() self.do_ast2700fc_ssp_test() self.do_ast2700fc_tsp_test() - def test_aarch64_ast2700fc_sdk_vbootrom_v09_08(self): + def test_aarch64_ast2700fc_sdk_vbootrom_v11_00(self): self.set_machine('ast2700fc') - self.archive_extract(self.ASSET_SDK_V908_AST2700) - self.start_ast2700fc_test_vbootrom('ast2700-default') - self.verify_openbmc_boot_and_login('ast2700-default') + self.archive_extract(self.ASSET_SDK_V1100_AST2700) + self.start_ast2700fc_test_vbootrom('ast2700-a1') + self.verify_openbmc_boot_and_login('ast2700-a1') self.do_ast2700fc_ssp_test() self.do_ast2700fc_tsp_test() -- 2.52.0
From: Jamin Lin <jamin_lin@aspeedtech.com> Recent SDK versions no longer provide a U-Boot FIT image, and U-Boot is now built as a single raw binary. Update the documentation to load the raw u-boot.bin image directly. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260203020855.1642884-9-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- docs/system/arm/aspeed.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -XXX,XX +XXX,XX @@ corresponds to the BL31 image load address. .. 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=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin \ - -device loader,force-raw=on,addr=$((0x400000000 + ${UBOOT_SIZE})),file=${IMGDIR}/u-boot.dtb \ + -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot.bin \ -device loader,force-raw=on,addr=0x430000000,file=${IMGDIR}/bl31.bin \ -device loader,force-raw=on,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin \ -device loader,cpu-num=0,addr=0x430000000 \ @@ -XXX,XX +XXX,XX @@ Steps to boot the AST2700fc machine: .. code-block:: bash IMGDIR=ast2700-default - UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin) $ qemu-system-aarch64 -M ast2700fc \ - -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin \ - -device loader,force-raw=on,addr=$((0x400000000 + ${UBOOT_SIZE})),file=${IMGDIR}/u-boot.dtb \ + -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot.bin \ -device loader,force-raw=on,addr=0x430000000,file=${IMGDIR}/bl31.bin \ -device loader,force-raw=on,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin \ -device loader,cpu-num=0,addr=0x430000000 \ -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> LTPI (LVDS Tunneling Protocol & Interface) is defined in the OCP DC-SCM 2.0 specification: https://www.opencompute.org/documents/ocp-dc-scm-2-0-ltpi-ver-1-0-pdf LTPI is a protocol and physical interface for tunneling various low-speed signals between the HPM and SCM. As shown in Figure 2, the AST27x0 (left) integrates two LTPI controllers, allowing it to connect to up to two extended boards. This commit introduces a simple device model for the ASPEED LTPI controller in QEMU. The model includes basic MMIO read/write operations and sets default register values during reset to emulate a link-up state. Implements register space with read/write callbacks. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-2-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/misc/aspeed_ltpi.h | 33 ++++++ hw/misc/aspeed_ltpi.c | 193 ++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + 3 files changed, 227 insertions(+) create mode 100644 include/hw/misc/aspeed_ltpi.h create mode 100644 hw/misc/aspeed_ltpi.c diff --git a/include/hw/misc/aspeed_ltpi.h b/include/hw/misc/aspeed_ltpi.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/include/hw/misc/aspeed_ltpi.h @@ -XXX,XX +XXX,XX @@ +/* + * ASPEED LTPI Controller + * + * Copyright (C) 2025 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef ASPEED_LTPI_H +#define ASPEED_LTPI_H + +#include "hw/core/sysbus.h" + +#define TYPE_ASPEED_LTPI "aspeed.ltpi-ctrl" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedLTPIState, ASPEED_LTPI) + +#define ASPEED_LTPI_TOTAL_SIZE 0x900 +#define ASPEED_LTPI_CTRL_SIZE 0x200 +#define ASPEED_LTPI_PHY_SIZE 0x100 +#define ASPEED_LTPI_TOP_SIZE 0x100 + +struct AspeedLTPIState { + SysBusDevice parent; + MemoryRegion mmio; + MemoryRegion mmio_ctrl; + MemoryRegion mmio_phy; + MemoryRegion mmio_top; + + uint32_t ctrl_regs[ASPEED_LTPI_CTRL_SIZE >> 2]; + uint32_t phy_regs[ASPEED_LTPI_PHY_SIZE >> 2]; + uint32_t top_regs[ASPEED_LTPI_TOP_SIZE >> 2]; +}; + +#endif /* ASPEED_LTPI_H */ diff --git a/hw/misc/aspeed_ltpi.c b/hw/misc/aspeed_ltpi.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/hw/misc/aspeed_ltpi.c @@ -XXX,XX +XXX,XX @@ +/* + * ASPEED LTPI Controller + * + * Copyright (C) 2025 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "migration/vmstate.h" +#include "hw/misc/aspeed_ltpi.h" + +#define ASPEED_LTPI_CTRL_BASE 0x000 +#define ASPEED_LTPI_PHY_BASE 0x200 +#define ASPEED_LTPI_TOP_BASE 0x800 + +#define LTPI_CTRL_LINK_MNG 0x42 +#define LTPI_PHY_MODE 0x0 + +static uint64_t aspeed_ltpi_top_read(void *opaque, hwaddr offset, unsigned size) +{ + AspeedLTPIState *s = opaque; + uint32_t idx = offset >> 2; + + return s->top_regs[idx]; +} + +static void aspeed_ltpi_top_write(void *opaque, hwaddr offset, + uint64_t val, unsigned size) +{ + AspeedLTPIState *s = opaque; + uint32_t idx = offset >> 2; + + switch (offset) { + default: + s->top_regs[idx] = (uint32_t)val; + break; + } +} + +static const MemoryRegionOps aspeed_ltpi_top_ops = { + .read = aspeed_ltpi_top_read, + .write = aspeed_ltpi_top_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static uint64_t aspeed_ltpi_phy_read(void *opaque, hwaddr offset, unsigned size) +{ + AspeedLTPIState *s = opaque; + uint32_t idx = offset >> 2; + + return s->phy_regs[idx]; +} + +static void aspeed_ltpi_phy_write(void *opaque, hwaddr offset, + uint64_t val, unsigned size) +{ + AspeedLTPIState *s = opaque; + uint32_t idx = offset >> 2; + + switch (offset) { + default: + s->phy_regs[idx] = (uint32_t)val; + break; + } +} + +static const MemoryRegionOps aspeed_ltpi_phy_ops = { + .read = aspeed_ltpi_phy_read, + .write = aspeed_ltpi_phy_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static uint64_t aspeed_ltpi_ctrl_read(void *opaque, + hwaddr offset, unsigned size) +{ + AspeedLTPIState *s = opaque; + uint32_t idx = offset >> 2; + + return s->ctrl_regs[idx]; +} + +static void aspeed_ltpi_ctrl_write(void *opaque, hwaddr offset, + uint64_t val, unsigned size) +{ + AspeedLTPIState *s = opaque; + uint32_t idx = offset >> 2; + + switch (offset) { + default: + s->ctrl_regs[idx] = (uint32_t)val; + break; + } +} + +static const MemoryRegionOps aspeed_ltpi_ctrl_ops = { + .read = aspeed_ltpi_ctrl_read, + .write = aspeed_ltpi_ctrl_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static void aspeed_ltpi_reset(DeviceState *dev) +{ + AspeedLTPIState *s = ASPEED_LTPI(dev); + + memset(s->ctrl_regs, 0, sizeof(s->ctrl_regs)); + memset(s->phy_regs, 0, sizeof(s->phy_regs)); + memset(s->top_regs, 0, sizeof(s->top_regs)); + /* set default values */ + s->ctrl_regs[LTPI_CTRL_LINK_MNG] = 0x11900007; + s->phy_regs[LTPI_PHY_MODE] = 0x2; +} + + +static const VMStateDescription vmstate_aspeed_ltpi = { + .name = TYPE_ASPEED_LTPI, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(ctrl_regs, AspeedLTPIState, + ASPEED_LTPI_CTRL_SIZE >> 2), + VMSTATE_UINT32_ARRAY(phy_regs, AspeedLTPIState, + ASPEED_LTPI_PHY_SIZE >> 2), + VMSTATE_UINT32_ARRAY(top_regs, AspeedLTPIState, + ASPEED_LTPI_TOP_SIZE >> 2), + + VMSTATE_END_OF_LIST() + } +}; + +static void aspeed_ltpi_realize(DeviceState *dev, Error **errp) +{ + AspeedLTPIState *s = ASPEED_LTPI(dev); + + memory_region_init(&s->mmio, OBJECT(s), TYPE_ASPEED_LTPI, + ASPEED_LTPI_TOTAL_SIZE); + + memory_region_init_io(&s->mmio_ctrl, OBJECT(s), + &aspeed_ltpi_ctrl_ops, s, + "aspeed-ltpi-ctrl", ASPEED_LTPI_CTRL_SIZE); + + memory_region_init_io(&s->mmio_phy, OBJECT(s), + &aspeed_ltpi_phy_ops, s, + "aspeed-ltpi-phy", ASPEED_LTPI_PHY_SIZE); + + memory_region_init_io(&s->mmio_top, OBJECT(s), + &aspeed_ltpi_top_ops, s, + "aspeed-ltpi-top", ASPEED_LTPI_TOP_SIZE); + + memory_region_add_subregion(&s->mmio, + ASPEED_LTPI_CTRL_BASE, &s->mmio_ctrl); + memory_region_add_subregion(&s->mmio, + ASPEED_LTPI_PHY_BASE, &s->mmio_phy); + memory_region_add_subregion(&s->mmio, + ASPEED_LTPI_TOP_BASE, &s->mmio_top); + + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); +} + +static void aspeed_ltpi_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + dc->realize = aspeed_ltpi_realize; + dc->vmsd = &vmstate_aspeed_ltpi; + device_class_set_legacy_reset(dc, aspeed_ltpi_reset); +} + +static const TypeInfo aspeed_ltpi_info = { + .name = TYPE_ASPEED_LTPI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedLTPIState), + .class_init = aspeed_ltpi_class_init, +}; + +static void aspeed_ltpi_register_types(void) +{ + type_register_static(&aspeed_ltpi_info); +} + +type_init(aspeed_ltpi_register_types); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_hace.c', 'aspeed_i3c.c', 'aspeed_lpc.c', + 'aspeed_ltpi.c', 'aspeed_scu.c', 'aspeed_sbc.c', 'aspeed_sdmc.c', -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the LTPI controller device (representing the AST1700 I/O expander) to the AST27X0 SoC model. This patch sets up the memory mapping and device registration according to the AST2700 SoC design, where the LTPI controller is exposed at fixed MMIO regions. This change only handles device instantiation and integration, without implementing the controller's internal logic. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-3-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_soc.h | 5 +++++ hw/arm/aspeed_ast27x0.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -XXX,XX +XXX,XX @@ #include "hw/fsi/aspeed_apb2opb.h" #include "hw/char/serial-mm.h" #include "hw/intc/arm_gicv3.h" +#include "hw/misc/aspeed_ltpi.h" #define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" @@ -XXX,XX +XXX,XX @@ #define ASPEED_UARTS_NUM 13 #define ASPEED_JTAG_NUM 2 #define ASPEED_PCIE_NUM 3 +#define ASPEED_IOEXP_NUM 2 struct AspeedSoCState { DeviceState parent; @@ -XXX,XX +XXX,XX @@ struct AspeedSoCState { UnimplementedDeviceState ltpi; UnimplementedDeviceState jtag[ASPEED_JTAG_NUM]; AspeedAPB2OPBState fsi[2]; + AspeedLTPIState ltpi_ctrl[ASPEED_IOEXP_NUM]; }; #define TYPE_ASPEED_SOC "aspeed-soc" @@ -XXX,XX +XXX,XX @@ enum { ASPEED_GIC_REDIST, ASPEED_DEV_IPC0, ASPEED_DEV_IPC1, + ASPEED_DEV_LTPI_CTRL1, + ASPEED_DEV_LTPI_CTRL2, }; const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types); diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_UART10] = 0x14C33900, [ASPEED_DEV_UART11] = 0x14C33A00, [ASPEED_DEV_UART12] = 0x14C33B00, + [ASPEED_DEV_LTPI_CTRL1] = 0x14C34000, + [ASPEED_DEV_LTPI_CTRL2] = 0x14C35000, [ASPEED_DEV_WDT] = 0x14C37000, [ASPEED_DEV_LTPI] = 0x30000000, [ASPEED_DEV_PCIE_MMIO0] = 0x60000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_init(Object *obj) object_property_set_int(OBJECT(&s->pcie[i]), "id", i, &error_abort); } + for (i = 0; i < ASPEED_IOEXP_NUM; i++) { + object_initialize_child(obj, "ltpi-ctrl[*]", + &s->ltpi_ctrl[i], TYPE_ASPEED_LTPI); + } + object_initialize_child(obj, "dpmcu", &s->dpmcu, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "ltpi", &s->ltpi, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) return; } + /* LTPI controller */ + for (i = 0; i < ASPEED_IOEXP_NUM; i++) { + AspeedLTPIState *ltpi_ctrl; + hwaddr ltpi_base; + + ltpi_ctrl = ASPEED_LTPI(&s->ltpi_ctrl[i]); + ltpi_base = sc->memmap[ASPEED_DEV_LTPI_CTRL1 + i]; + + if (!sysbus_realize(SYS_BUS_DEVICE(ltpi_ctrl), errp)) { + return; + } + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(ltpi_ctrl), 0, ltpi_base); + } + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu), "aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU], -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Add an initial PWM model for Aspeed SoCs, including device state, register definitions, and basic initialization as a sysbus device. Signed-off-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-4-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_soc.h | 3 +- include/hw/misc/aspeed_pwm.h | 30 +++++++++ hw/misc/aspeed_pwm.c | 120 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + hw/misc/trace-events | 4 ++ 5 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 include/hw/misc/aspeed_pwm.h create mode 100644 hw/misc/aspeed_pwm.c diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -XXX,XX +XXX,XX @@ #include "hw/misc/aspeed_hace.h" #include "hw/misc/aspeed_sbc.h" #include "hw/misc/aspeed_sli.h" +#include "hw/misc/aspeed_pwm.h" #include "hw/watchdog/wdt_aspeed.h" #include "hw/net/ftgmac100.h" #include "target/arm/cpu.h" @@ -XXX,XX +XXX,XX @@ struct AspeedSoCState { MemoryRegion secsram; UnimplementedDeviceState sbc_unimplemented; AspeedSDMCState sdmc; + AspeedPWMState pwm; AspeedWDTState wdt[ASPEED_WDTS_NUM]; FTGMAC100State ftgmac100[ASPEED_MACS_NUM]; AspeedMiiState mii[ASPEED_MACS_NUM]; @@ -XXX,XX +XXX,XX @@ struct AspeedSoCState { UnimplementedDeviceState video; UnimplementedDeviceState emmc_boot_controller; UnimplementedDeviceState dpmcu; - UnimplementedDeviceState pwm; UnimplementedDeviceState espi; UnimplementedDeviceState udc; UnimplementedDeviceState ltpi; diff --git a/include/hw/misc/aspeed_pwm.h b/include/hw/misc/aspeed_pwm.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/include/hw/misc/aspeed_pwm.h @@ -XXX,XX +XXX,XX @@ +/* + * ASPEED PWM Controller + * + * Copyright (C) 2017-2021 IBM Corp. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ASPEED_PWM_H +#define ASPEED_PWM_H + +#include "hw/core/sysbus.h" + +#define TYPE_ASPEED_PWM "aspeed.pwm" +#define ASPEED_PWM(obj) OBJECT_CHECK(AspeedPWMState, (obj), TYPE_ASPEED_PWM) + +#define ASPEED_PWM_NR_REGS (0x10C >> 2) + +typedef struct AspeedPWMState { + /* <private> */ + SysBusDevice parent; + + /*< public >*/ + MemoryRegion iomem; + qemu_irq irq; + + uint32_t regs[ASPEED_PWM_NR_REGS]; +} AspeedPWMState; + +#endif /* _ASPEED_PWM_H_ */ diff --git a/hw/misc/aspeed_pwm.c b/hw/misc/aspeed_pwm.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/hw/misc/aspeed_pwm.c @@ -XXX,XX +XXX,XX @@ +/* + * ASPEED PWM Controller + * + * Copyright (C) 2017-2021 IBM Corp. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_pwm.h" +#include "qapi/error.h" +#include "migration/vmstate.h" + +#include "trace.h" + +static uint64_t aspeed_pwm_read(void *opaque, hwaddr addr, + unsigned int size) +{ + AspeedPWMState *s = ASPEED_PWM(opaque); + uint64_t val = 0; + + addr >>= 2; + + if (addr >= ASPEED_PWM_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + } else { + val = s->regs[addr]; + } + + trace_aspeed_pwm_read(addr << 2, val); + + return val; +} + +static void aspeed_pwm_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + AspeedPWMState *s = ASPEED_PWM(opaque); + + trace_aspeed_pwm_write(addr, data); + + addr >>= 2; + + if (addr >= ASPEED_PWM_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return; + } + + s->regs[addr] = data; +} + +static const MemoryRegionOps aspeed_pwm_ops = { + .read = aspeed_pwm_read, + .write = aspeed_pwm_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static void aspeed_pwm_reset(DeviceState *dev) +{ + struct AspeedPWMState *s = ASPEED_PWM(dev); + + memset(s->regs, 0, sizeof(s->regs)); +} + +static void aspeed_pwm_realize(DeviceState *dev, Error **errp) +{ + AspeedPWMState *s = ASPEED_PWM(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_pwm_ops, s, + TYPE_ASPEED_PWM, 0x1000); + + sysbus_init_mmio(sbd, &s->iomem); +} + +static const VMStateDescription vmstate_aspeed_pwm = { + .name = TYPE_ASPEED_PWM, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, AspeedPWMState, ASPEED_PWM_NR_REGS), + VMSTATE_END_OF_LIST(), + } +}; + +static void aspeed_pwm_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aspeed_pwm_realize; + device_class_set_legacy_reset(dc, aspeed_pwm_reset); + dc->desc = "Aspeed PWM Controller"; + dc->vmsd = &vmstate_aspeed_pwm; +} + +static const TypeInfo aspeed_pwm_info = { + .name = TYPE_ASPEED_PWM, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedPWMState), + .class_init = aspeed_pwm_class_init, +}; + +static void aspeed_pwm_register_types(void) +{ + type_register_static(&aspeed_pwm_info); +} + +type_init(aspeed_pwm_register_types); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_i3c.c', 'aspeed_lpc.c', 'aspeed_ltpi.c', + 'aspeed_pwm.c', 'aspeed_scu.c', 'aspeed_sbc.c', 'aspeed_sdmc.c', diff --git a/hw/misc/trace-events b/hw/misc/trace-events index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -XXX,XX +XXX,XX @@ aspeed_i3c_write(uint64_t offset, uint64_t data) "I3C write: offset 0x%" PRIx64 aspeed_i3c_device_read(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] read: offset 0x%" PRIx64 " data 0x%" PRIx64 aspeed_i3c_device_write(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] write: offset 0x%" PRIx64 " data 0x%" PRIx64 +# aspeed_pwm.c +aspeed_pwm_read(uint64_t offset, uint64_t data) "read: offset 0x%" PRIx64 " data 0x%" PRIx64 +aspeed_pwm_write(uint64_t offset, uint64_t data) "write: offset 0x%" PRIx64 " data 0x%" PRIx64 + # aspeed_sdmc.c aspeed_sdmc_write(uint64_t reg, uint64_t data) "reg @0x%" PRIx64 " data: 0x%" PRIx64 aspeed_sdmc_read(uint64_t reg, uint64_t data) "reg @0x%" PRIx64 " data: 0x%" PRIx64 -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Introduce a minimal QEMU device model for the ASPEED AST1700, an MCU-less I/O expander used in the LTPI topology defined by the DC-SCM 2.0 specification (see figure 2): https://www.opencompute.org/documents/ocp-dc-scm-2-0-ltpi-ver-1-0-pdf This initial implementation includes: * Definition of aspeed.ast1700 as a SysBusDevice * Setup of a basic memory region to reserve I/O space for future peripheral modeling This stub establishes the foundation for LTPI-related device emulation, without implementing any functional peripherals at this stage. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-5-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 23 +++++++++++++++++ hw/arm/aspeed_ast1700.c | 46 +++++++++++++++++++++++++++++++++ hw/arm/meson.build | 1 + 3 files changed, 70 insertions(+) create mode 100644 include/hw/arm/aspeed_ast1700.h create mode 100644 hw/arm/aspeed_ast1700.c diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ +/* + * ASPEED AST1700 IO Expander + * + * Copyright (C) 2025 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef ASPEED_AST1700_H +#define ASPEED_AST1700_H + +#include "hw/core/sysbus.h" + +#define TYPE_ASPEED_AST1700 "aspeed.ast1700" + +OBJECT_DECLARE_SIMPLE_TYPE(AspeedAST1700SoCState, ASPEED_AST1700) + +struct AspeedAST1700SoCState { + SysBusDevice parent_obj; + + MemoryRegion iomem; +}; + +#endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ +/* + * ASPEED AST1700 IO Expander + * + * Copyright (C) 2025 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/core/boards.h" +#include "qom/object.h" +#include "hw/arm/aspeed_ast1700.h" + +#define AST2700_SOC_LTPI_SIZE 0x01000000 + +static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) +{ + AspeedAST1700SoCState *s = ASPEED_AST1700(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + /* Occupy memory space for all controllers in AST1700 */ + memory_region_init(&s->iomem, OBJECT(s), TYPE_ASPEED_AST1700, + AST2700_SOC_LTPI_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void aspeed_ast1700_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aspeed_ast1700_realize; +} + +static const TypeInfo aspeed_ast1700_info = { + .name = TYPE_ASPEED_AST1700, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedAST1700SoCState), + .class_init = aspeed_ast1700_class_init, +}; + +static void aspeed_ast1700_register_types(void) +{ + type_register_static(&aspeed_ast1700_info); +} + +type_init(aspeed_ast1700_register_types); diff --git a/hw/arm/meson.build b/hw/arm/meson.build index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_ast10x0_evb.c', 'fby35.c')) arm_common_ss.add(when: ['CONFIG_ASPEED_SOC', 'TARGET_AARCH64'], if_true: files( + 'aspeed_ast1700.c', 'aspeed_ast27x0.c', 'aspeed_ast27x0_evb.c', 'aspeed_ast27x0-fc.c', -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the AST1700 device as a child of the AST27X0 model to reflect its role in DC-SCM 2.0 LTPI-based architectures. This patch wires the AST1700 device into the platform without introducing functional peripherals. This forms the base for LTPI expander emulation in QEMU using AST27X0 as the host controller. Note: ioexp_num is set to 0 at this stage. Once all related devices and interrupts are fully implemented, ioexp_num will be updated to its expected value. This ensures the machine remains functional at every commit and avoids potential compiler or build issues. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-6-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_soc.h | 7 +++++-- hw/arm/aspeed_ast27x0.c | 26 ++++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -XXX,XX +XXX,XX @@ #include "hw/char/serial-mm.h" #include "hw/intc/arm_gicv3.h" #include "hw/misc/aspeed_ltpi.h" +#include "hw/arm/aspeed_ast1700.h" #define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" @@ -XXX,XX +XXX,XX @@ struct AspeedSoCState { UnimplementedDeviceState dpmcu; UnimplementedDeviceState espi; UnimplementedDeviceState udc; - UnimplementedDeviceState ltpi; UnimplementedDeviceState jtag[ASPEED_JTAG_NUM]; AspeedAPB2OPBState fsi[2]; AspeedLTPIState ltpi_ctrl[ASPEED_IOEXP_NUM]; + AspeedAST1700SoCState ioexp[ASPEED_IOEXP_NUM]; }; #define TYPE_ASPEED_SOC "aspeed-soc" @@ -XXX,XX +XXX,XX @@ struct AspeedSoCClass { int macs_num; int uarts_num; int uarts_base; + int ioexp_num; const int *irqmap; const hwaddr *memmap; uint32_t num_cpus; @@ -XXX,XX +XXX,XX @@ enum { ASPEED_DEV_IOMEM, ASPEED_DEV_IOMEM0, ASPEED_DEV_IOMEM1, - ASPEED_DEV_LTPI, ASPEED_DEV_UART0, ASPEED_DEV_UART1, ASPEED_DEV_UART2, @@ -XXX,XX +XXX,XX @@ enum { ASPEED_DEV_IPC1, ASPEED_DEV_LTPI_CTRL1, ASPEED_DEV_LTPI_CTRL2, + ASPEED_DEV_LTPI_IO0, + ASPEED_DEV_LTPI_IO1, }; const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types); diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ #define AST2700_SOC_IO_SIZE 0x00FE0000 #define AST2700_SOC_IOMEM_SIZE 0x01000000 #define AST2700_SOC_DPMCU_SIZE 0x00040000 -#define AST2700_SOC_LTPI_SIZE 0x01000000 static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_VBOOTROM] = 0x00000000, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_LTPI_CTRL1] = 0x14C34000, [ASPEED_DEV_LTPI_CTRL2] = 0x14C35000, [ASPEED_DEV_WDT] = 0x14C37000, - [ASPEED_DEV_LTPI] = 0x30000000, + [ASPEED_DEV_LTPI_IO0] = 0x30000000, + [ASPEED_DEV_LTPI_IO1] = 0x50000000, [ASPEED_DEV_PCIE_MMIO0] = 0x60000000, [ASPEED_DEV_PCIE_MMIO1] = 0x80000000, [ASPEED_DEV_PCIE_MMIO2] = 0xA0000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_init(Object *obj) &s->ltpi_ctrl[i], TYPE_ASPEED_LTPI); } + for (i = 0; i < sc->ioexp_num; i++) { + /* AST1700 IOEXP */ + object_initialize_child(obj, "ioexp[*]", &s->ioexp[i], + TYPE_ASPEED_AST1700); + } + object_initialize_child(obj, "dpmcu", &s->dpmcu, TYPE_UNIMPLEMENTED_DEVICE); - object_initialize_child(obj, "ltpi", &s->ltpi, - TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "iomem", &s->iomem, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "iomem0", &s->iomem0, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(ltpi_ctrl), 0, ltpi_base); } + /* IO Expander */ + for (i = 0; i < sc->ioexp_num; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ioexp[i]), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioexp[i]), 0, + sc->memmap[ASPEED_DEV_LTPI_IO0 + i]); + } + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu), "aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU], AST2700_SOC_DPMCU_SIZE); - aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->ltpi), - "aspeed.ltpi", - sc->memmap[ASPEED_DEV_LTPI], - AST2700_SOC_LTPI_SIZE); aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem), "aspeed.io", sc->memmap[ASPEED_DEV_IOMEM], @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700a1_class_init(ObjectClass *oc, const void *data) sc->macs_num = 3; sc->uarts_num = 13; sc->num_cpus = 4; + sc->ioexp_num = 0; sc->uarts_base = ASPEED_DEV_UART0; sc->irqmap = aspeed_soc_ast2700a1_irqmap; sc->memmap = aspeed_soc_ast2700_memmap; -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the AST1700 interrupt lines to the GIC in AST27X0, enabling the propagation of AST1700-originated interrupts to the host SoC. This patch does not implement interrupt sources in AST1700 itself, only the wiring into AST27X0. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-7-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_soc.h | 6 +++- include/hw/intc/aspeed_intc.h | 2 ++ hw/arm/aspeed_ast27x0.c | 37 +++++++++++++++++++++ hw/intc/aspeed_intc.c | 60 +++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -XXX,XX +XXX,XX @@ #define ASPEED_UARTS_NUM 13 #define ASPEED_JTAG_NUM 2 #define ASPEED_PCIE_NUM 3 +#define ASPEED_INTC_NUM 2 #define ASPEED_IOEXP_NUM 2 struct AspeedSoCState { @@ -XXX,XX +XXX,XX @@ struct Aspeed27x0SoCState { AspeedSoCState parent; ARMCPU cpu[ASPEED_CPUS_NUM]; - AspeedINTCState intc[2]; + AspeedINTCState intc[ASPEED_INTC_NUM]; + AspeedINTCState intcioexp[ASPEED_IOEXP_NUM]; GICv3State gic; MemoryRegion dram_empty; }; @@ -XXX,XX +XXX,XX @@ enum { ASPEED_DEV_LTPI_CTRL2, ASPEED_DEV_LTPI_IO0, ASPEED_DEV_LTPI_IO1, + ASPEED_DEV_IOEXP0_INTCIO, + ASPEED_DEV_IOEXP1_INTCIO, }; const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types); diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/intc/aspeed_intc.h +++ b/include/hw/intc/aspeed_intc.h @@ -XXX,XX +XXX,XX @@ #define TYPE_ASPEED_INTC "aspeed.intc" #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700" #define TYPE_ASPEED_2700_INTCIO TYPE_ASPEED_INTC "io-ast2700" +#define TYPE_ASPEED_2700_INTCIOEXP1 TYPE_ASPEED_INTC "-ast2700-ioexp1" +#define TYPE_ASPEED_2700_INTCIOEXP2 TYPE_ASPEED_INTC "-ast2700-ioexp2" #define TYPE_ASPEED_2700SSP_INTC TYPE_ASPEED_INTC "-ast2700ssp" #define TYPE_ASPEED_2700SSP_INTCIO TYPE_ASPEED_INTC "io-ast2700ssp" #define TYPE_ASPEED_2700TSP_INTC TYPE_ASPEED_INTC "-ast2700tsp" diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_LTPI_CTRL2] = 0x14C35000, [ASPEED_DEV_WDT] = 0x14C37000, [ASPEED_DEV_LTPI_IO0] = 0x30000000, + [ASPEED_DEV_IOEXP0_INTCIO] = 0x30C18000, [ASPEED_DEV_LTPI_IO1] = 0x50000000, + [ASPEED_DEV_IOEXP1_INTCIO] = 0x50C18000, [ASPEED_DEV_PCIE_MMIO0] = 0x60000000, [ASPEED_DEV_PCIE_MMIO1] = 0x80000000, [ASPEED_DEV_PCIE_MMIO2] = 0xA0000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_init(Object *obj) object_initialize_child(obj, "intc", &a->intc[0], TYPE_ASPEED_2700_INTC); object_initialize_child(obj, "intcio", &a->intc[1], TYPE_ASPEED_2700_INTCIO); + object_initialize_child(obj, "intc-ioexp0", &a->intcioexp[0], + TYPE_ASPEED_2700_INTCIOEXP1); + object_initialize_child(obj, "intc-ioexp1", &a->intcioexp[1], + TYPE_ASPEED_2700_INTCIOEXP2); snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname); object_initialize_child(obj, "adc", &s->adc, typename); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[1]), 0, sc->memmap[ASPEED_DEV_INTCIO]); + /* INTCIOEXP0 */ + if (!sysbus_realize(SYS_BUS_DEVICE(&a->intcioexp[0]), errp)) { + return; + } + + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intcioexp[0]), 0, + sc->memmap[ASPEED_DEV_IOEXP0_INTCIO]); + + /* INTCIOEXP1 */ + if (!sysbus_realize(SYS_BUS_DEVICE(&a->intcioexp[1]), errp)) { + return; + } + + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intcioexp[1]), 0, + sc->memmap[ASPEED_DEV_IOEXP1_INTCIO]); + /* irq sources -> orgates -> INTC */ for (i = 0; i < ic->num_inpins; i++) { qdev_connect_gpio_out(DEVICE(&a->intc[0].orgates[i]), 0, @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioexp[i]), 0, sc->memmap[ASPEED_DEV_LTPI_IO0 + i]); + + icio = ASPEED_INTC_GET_CLASS(&a->intcioexp[i]); + /* INTC_IOEXP internal: orgate[i] -> input[i] */ + for (int j = 0; j < icio->num_inpins; j++) { + irq = qdev_get_gpio_in(DEVICE(&a->intcioexp[i]), j); + qdev_connect_gpio_out(DEVICE(&a->intcioexp[i].orgates[j]), 0, + irq); + } + + /* INTC_IOEXP output[i] -> INTC0.orgate[0].input[i] */ + for (int j = 0; j < icio->num_outpins; j++) { + irq = qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), j); + sysbus_connect_irq(SYS_BUS_DEVICE(&a->intcioexp[i]), j, + irq); + } } aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu), diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/aspeed_intc.c +++ b/hw/intc/aspeed_intc.c @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_2700_intc_info = { .class_init = aspeed_2700_intc_class_init, }; +static AspeedINTCIRQ aspeed_2700_intcioexp2_irqs[ASPEED_INTC_MAX_INPINS] = { + {0, 8, 1, R_GICINT192_EN, R_GICINT192_STATUS}, + {1, 9, 1, R_GICINT193_EN, R_GICINT193_STATUS}, +}; + +static void aspeed_2700_intcioexp2_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + + dc->desc = "ASPEED 2700 IOEXP2 INTC Controller"; + aic->num_lines = 32; + aic->num_inpins = 2; + aic->num_outpins = 10; + aic->mem_size = 0x400; + aic->nr_regs = 0x58 >> 2; + aic->reg_offset = 0x100; + aic->reg_ops = &aspeed_intcio_ops; + aic->irq_table = aspeed_2700_intcioexp2_irqs; + aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcioexp2_irqs); +} + +static const TypeInfo aspeed_2700_intcioexp2_info = { + .name = TYPE_ASPEED_2700_INTCIOEXP2, + .parent = TYPE_ASPEED_INTC, + .class_init = aspeed_2700_intcioexp2_class_init, +}; + +static AspeedINTCIRQ aspeed_2700_intcioexp1_irqs[ASPEED_INTC_MAX_INPINS] = { + {0, 6, 1, R_GICINT192_EN, R_GICINT192_STATUS}, + {1, 7, 1, R_GICINT193_EN, R_GICINT193_STATUS}, +}; + +static void aspeed_2700_intcioexp1_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + + dc->desc = "ASPEED 2700 IOEXP1 INTC Controller"; + aic->num_lines = 32; + aic->num_inpins = 2; + aic->num_outpins = 10; + aic->mem_size = 0x400; + aic->nr_regs = 0x58 >> 2; + aic->reg_offset = 0x100; + aic->reg_ops = &aspeed_intcio_ops; + aic->irq_table = aspeed_2700_intcioexp1_irqs; + aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcioexp1_irqs); +} + +static const TypeInfo aspeed_2700_intcioexp1_info = { + .name = TYPE_ASPEED_2700_INTCIOEXP1, + .parent = TYPE_ASPEED_INTC, + .class_init = aspeed_2700_intcioexp1_class_init, +}; + static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS}, {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS}, @@ -XXX,XX +XXX,XX @@ static void aspeed_intc_register_types(void) type_register_static(&aspeed_intc_info); type_register_static(&aspeed_2700_intc_info); type_register_static(&aspeed_2700_intcio_info); + type_register_static(&aspeed_2700_intcioexp1_info); + type_register_static(&aspeed_2700_intcioexp2_info); type_register_static(&aspeed_2700ssp_intc_info); type_register_static(&aspeed_2700ssp_intcio_info); type_register_static(&aspeed_2700tsp_intc_info); -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the LTPI controller to the AST1700 model by mapping its MMIO region. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-8-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 3 +++ hw/arm/aspeed_ast1700.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #define ASPEED_AST1700_H #include "hw/core/sysbus.h" +#include "hw/misc/aspeed_ltpi.h" #define TYPE_ASPEED_AST1700 "aspeed.ast1700" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { SysBusDevice parent_obj; MemoryRegion iomem; + + AspeedLTPIState ltpi; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ #define AST2700_SOC_LTPI_SIZE 0x01000000 +enum { + ASPEED_AST1700_DEV_LTPI_CTRL, +}; + +static const hwaddr aspeed_ast1700_io_memmap[] = { + [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, +}; + static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) { AspeedAST1700SoCState *s = ASPEED_AST1700(dev); @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) memory_region_init(&s->iomem, OBJECT(s), TYPE_ASPEED_AST1700, AST2700_SOC_LTPI_SIZE); sysbus_init_mmio(sbd, &s->iomem); + + /* LTPI controller */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_LTPI_CTRL], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ltpi), 0)); +} + +static void aspeed_ast1700_instance_init(Object *obj) +{ + AspeedAST1700SoCState *s = ASPEED_AST1700(obj); + + /* LTPI controller */ + object_initialize_child(obj, "ltpi-ctrl", + &s->ltpi, TYPE_ASPEED_LTPI); + + return; } static void aspeed_ast1700_class_init(ObjectClass *klass, const void *data) @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_ast1700_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AspeedAST1700SoCState), .class_init = aspeed_ast1700_class_init, + .instance_init = aspeed_ast1700_instance_init, }; static void aspeed_ast1700_register_types(void) -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the UART controller to the AST1700 model by mapping its MMIO region. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-9-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 2 ++ hw/arm/aspeed_ast1700.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/core/sysbus.h" #include "hw/misc/aspeed_ltpi.h" +#include "hw/char/serial-mm.h" #define TYPE_ASPEED_AST1700 "aspeed.ast1700" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { MemoryRegion iomem; AspeedLTPIState ltpi; + SerialMM uart; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "hw/core/boards.h" #include "qom/object.h" +#include "hw/core/qdev-properties.h" #include "hw/arm/aspeed_ast1700.h" #define AST2700_SOC_LTPI_SIZE 0x01000000 enum { + ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, }; static const hwaddr aspeed_ast1700_io_memmap[] = { + [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, }; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) AST2700_SOC_LTPI_SIZE); sysbus_init_mmio(sbd, &s->iomem); + /* UART */ + qdev_prop_set_uint8(DEVICE(&s->uart), "regshift", 2); + qdev_prop_set_uint32(DEVICE(&s->uart), "baudbase", 38400); + qdev_prop_set_uint8(DEVICE(&s->uart), "endianness", DEVICE_LITTLE_ENDIAN); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_UART12], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) { AspeedAST1700SoCState *s = ASPEED_AST1700(obj); + /* UART */ + object_initialize_child(obj, "uart", &s->uart, + TYPE_SERIAL_MM); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Map the SRAM device to AST1700 model Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-10-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 2 ++ hw/arm/aspeed_ast1700.c | 17 +++++++++++++++++ hw/arm/aspeed_ast27x0.c | 1 + 3 files changed, 20 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { SysBusDevice parent_obj; MemoryRegion iomem; + uint8_t board_idx; AspeedLTPIState ltpi; SerialMM uart; + MemoryRegion sram; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ #include "hw/arm/aspeed_ast1700.h" #define AST2700_SOC_LTPI_SIZE 0x01000000 +#define AST1700_SOC_SRAM_SIZE 0x00040000 enum { + ASPEED_AST1700_DEV_SRAM, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, }; static const hwaddr aspeed_ast1700_io_memmap[] = { + [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, }; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) { AspeedAST1700SoCState *s = ASPEED_AST1700(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + char dev_name[32]; /* Occupy memory space for all controllers in AST1700 */ memory_region_init(&s->iomem, OBJECT(s), TYPE_ASPEED_AST1700, AST2700_SOC_LTPI_SIZE); sysbus_init_mmio(sbd, &s->iomem); + /* SRAM */ + snprintf(dev_name, sizeof(dev_name), "aspeed.ioexp-sram.%d", s->board_idx); + memory_region_init_ram(&s->sram, OBJECT(s), dev_name, + AST1700_SOC_SRAM_SIZE, errp); + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SRAM], + &s->sram); + /* UART */ qdev_prop_set_uint8(DEVICE(&s->uart), "regshift", 2); qdev_prop_set_uint32(DEVICE(&s->uart), "baudbase", 38400); @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) return; } +static const Property aspeed_ast1700_props[] = { + DEFINE_PROP_UINT8("board-idx", AspeedAST1700SoCState, board_idx, 0), +}; + static void aspeed_ast1700_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = aspeed_ast1700_realize; + device_class_set_props(dc, aspeed_ast1700_props); } static const TypeInfo aspeed_ast1700_info = { diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) /* IO Expander */ for (i = 0; i < sc->ioexp_num; i++) { + qdev_prop_set_uint8(DEVICE(&s->ioexp[i]), "board-idx", i); if (!sysbus_realize(SYS_BUS_DEVICE(&s->ioexp[i]), errp)) { return; } -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the SPI device to AST1700 model. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-11-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 3 +++ hw/arm/aspeed_ast1700.c | 30 ++++++++++++++++++++++++++++++ hw/arm/aspeed_ast27x0.c | 2 ++ 3 files changed, 35 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/core/sysbus.h" #include "hw/misc/aspeed_ltpi.h" +#include "hw/ssi/aspeed_smc.h" #include "hw/char/serial-mm.h" #define TYPE_ASPEED_AST1700 "aspeed.ast1700" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { SysBusDevice parent_obj; MemoryRegion iomem; + MemoryRegion *dram_mr; uint8_t board_idx; AspeedLTPIState ltpi; SerialMM uart; MemoryRegion sram; + AspeedSMCState spi; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "hw/core/boards.h" #include "qom/object.h" +#include "qapi/error.h" #include "hw/core/qdev-properties.h" #include "hw/arm/aspeed_ast1700.h" @@ -XXX,XX +XXX,XX @@ #define AST1700_SOC_SRAM_SIZE 0x00040000 enum { + ASPEED_AST1700_DEV_SPI0, ASPEED_AST1700_DEV_SRAM, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, + ASPEED_AST1700_DEV_SPI0_MEM, }; static const hwaddr aspeed_ast1700_io_memmap[] = { + [ASPEED_AST1700_DEV_SPI0] = 0x00030000, [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, + [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000, }; static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) SysBusDevice *sbd = SYS_BUS_DEVICE(dev); char dev_name[32]; + if (!s->dram_mr) { + error_setg(errp, TYPE_ASPEED_AST1700 ": 'dram' link not set"); + return; + } + /* Occupy memory space for all controllers in AST1700 */ memory_region_init(&s->iomem, OBJECT(s), TYPE_ASPEED_AST1700, AST2700_SOC_LTPI_SIZE); @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_UART12], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0)); + /* SPI */ + object_property_set_link(OBJECT(&s->spi), "dram", + OBJECT(s->dram_mr), errp); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 0)); + + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0_MEM], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 1)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "uart", &s->uart, TYPE_SERIAL_MM); + /* SPI */ + object_initialize_child(obj, "ioexp-spi", &s->spi, + "aspeed.spi0-ast2700"); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) static const Property aspeed_ast1700_props[] = { DEFINE_PROP_UINT8("board-idx", AspeedAST1700SoCState, board_idx, 0), + DEFINE_PROP_LINK("dram", AspeedAST1700SoCState, dram_mr, + TYPE_MEMORY_REGION, MemoryRegion *), }; static void aspeed_ast1700_class_init(ObjectClass *klass, const void *data) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) /* IO Expander */ for (i = 0; i < sc->ioexp_num; i++) { qdev_prop_set_uint8(DEVICE(&s->ioexp[i]), "board-idx", i); + object_property_set_link(OBJECT(&s->ioexp[i]), "dram", + OBJECT(s->dram_mr), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->ioexp[i]), errp)) { return; } -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the ADC device to AST1700 model. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-12-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 2 ++ hw/arm/aspeed_ast1700.c | 14 ++++++++++++++ hw/arm/aspeed_ast27x0.c | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #define ASPEED_AST1700_H #include "hw/core/sysbus.h" +#include "hw/adc/aspeed_adc.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/ssi/aspeed_smc.h" #include "hw/char/serial-mm.h" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { SerialMM uart; MemoryRegion sram; AspeedSMCState spi; + AspeedADCState adc; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_SPI0, ASPEED_AST1700_DEV_SRAM, + ASPEED_AST1700_DEV_ADC, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, ASPEED_AST1700_DEV_SPI0_MEM, @@ -XXX,XX +XXX,XX @@ enum { static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_SPI0] = 0x00030000, [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000, + [ASPEED_AST1700_DEV_ADC] = 0x00C00000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0_MEM], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 1)); + /* ADC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_ADC], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->adc), 0)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ioexp-spi", &s->spi, "aspeed.spi0-ast2700"); + /* ADC */ + object_initialize_child(obj, "ioexp-adc", &s->adc, + "aspeed.adc-ast2700"); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&a->intcioexp[i]), j, irq); } + + /* ADC */ + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].adc), 0, + aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_ADC)); + } aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu), -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the SCU device to AST1700 model. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-13-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 3 +++ hw/arm/aspeed_ast1700.c | 17 +++++++++++++++++ hw/arm/aspeed_ast27x0.c | 2 ++ 3 files changed, 22 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #define ASPEED_AST1700_H #include "hw/core/sysbus.h" +#include "hw/misc/aspeed_scu.h" #include "hw/adc/aspeed_adc.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/ssi/aspeed_smc.h" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { MemoryRegion iomem; MemoryRegion *dram_mr; uint8_t board_idx; + uint32_t silicon_rev; AspeedLTPIState ltpi; SerialMM uart; MemoryRegion sram; AspeedSMCState spi; AspeedADCState adc; + AspeedSCUState scu; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_SPI0, ASPEED_AST1700_DEV_SRAM, ASPEED_AST1700_DEV_ADC, + ASPEED_AST1700_DEV_SCU, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, ASPEED_AST1700_DEV_SPI0_MEM, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_SPI0] = 0x00030000, [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000, [ASPEED_AST1700_DEV_ADC] = 0x00C00000, + [ASPEED_AST1700_DEV_SCU] = 0x00C02000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_ADC], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->adc), 0)); + /* SCU */ + qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", + s->silicon_rev); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SCU], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->scu), 0)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ioexp-adc", &s->adc, "aspeed.adc-ast2700"); + /* SCU */ + object_initialize_child(obj, "ioexp-scu", &s->scu, + TYPE_ASPEED_2700_SCU); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) static const Property aspeed_ast1700_props[] = { DEFINE_PROP_UINT8("board-idx", AspeedAST1700SoCState, board_idx, 0), + DEFINE_PROP_UINT32("silicon-rev", AspeedAST1700SoCState, silicon_rev, 0), DEFINE_PROP_LINK("dram", AspeedAST1700SoCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), }; diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_init(Object *obj) /* AST1700 IOEXP */ object_initialize_child(obj, "ioexp[*]", &s->ioexp[i], TYPE_ASPEED_AST1700); + qdev_prop_set_uint32(DEVICE(&s->ioexp[i]), "silicon-rev", + sc->silicon_rev); } object_initialize_child(obj, "dpmcu", &s->dpmcu, -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the GPIO controller to the AST1700 model by mapping its MMIO region and wiring its interrupt line. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-14-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 2 ++ hw/arm/aspeed_ast1700.c | 14 ++++++++++++++ hw/arm/aspeed_ast27x0.c | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/core/sysbus.h" #include "hw/misc/aspeed_scu.h" #include "hw/adc/aspeed_adc.h" +#include "hw/gpio/aspeed_gpio.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/ssi/aspeed_smc.h" #include "hw/char/serial-mm.h" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { AspeedSMCState spi; AspeedADCState adc; AspeedSCUState scu; + AspeedGPIOState gpio; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_SRAM, ASPEED_AST1700_DEV_ADC, ASPEED_AST1700_DEV_SCU, + ASPEED_AST1700_DEV_GPIO, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, ASPEED_AST1700_DEV_SPI0_MEM, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000, [ASPEED_AST1700_DEV_ADC] = 0x00C00000, [ASPEED_AST1700_DEV_SCU] = 0x00C02000, + [ASPEED_AST1700_DEV_GPIO] = 0x00C0B000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SCU], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->scu), 0)); + /* GPIO */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_GPIO], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ioexp-scu", &s->scu, TYPE_ASPEED_2700_SCU); + /* GPIO */ + object_initialize_child(obj, "ioexp-gpio", &s->gpio, + "aspeed.gpio-ast2700"); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].adc), 0, aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_ADC)); + /* GPIO */ + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].gpio), 0, + aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_GPIO)); + } aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu), -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the I2C controller to the AST1700 model by mapping its MMIO region and wiring its interrupt line. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-15-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 2 ++ include/hw/arm/aspeed_soc.h | 2 ++ hw/arm/aspeed_ast1700.c | 19 ++++++++++++ hw/arm/aspeed_ast27x0.c | 51 +++++++++++++++++++++++++++++++-- 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/misc/aspeed_scu.h" #include "hw/adc/aspeed_adc.h" #include "hw/gpio/aspeed_gpio.h" +#include "hw/i2c/aspeed_i2c.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/ssi/aspeed_smc.h" #include "hw/char/serial-mm.h" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { AspeedADCState adc; AspeedSCUState scu; AspeedGPIOState gpio; + AspeedI2CState i2c; }; #endif /* ASPEED_AST1700_H */ diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -XXX,XX +XXX,XX @@ enum { ASPEED_DEV_LTPI_CTRL2, ASPEED_DEV_LTPI_IO0, ASPEED_DEV_LTPI_IO1, + ASPEED_DEV_IOEXP0_I2C, + ASPEED_DEV_IOEXP1_I2C, ASPEED_DEV_IOEXP0_INTCIO, ASPEED_DEV_IOEXP1_INTCIO, }; diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_ADC, ASPEED_AST1700_DEV_SCU, ASPEED_AST1700_DEV_GPIO, + ASPEED_AST1700_DEV_I2C, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, ASPEED_AST1700_DEV_SPI0_MEM, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_ADC] = 0x00C00000, [ASPEED_AST1700_DEV_SCU] = 0x00C02000, [ASPEED_AST1700_DEV_GPIO] = 0x00C0B000, + [ASPEED_AST1700_DEV_I2C] = 0x00C0F000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_GPIO], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); + /* I2C */ + snprintf(dev_name, sizeof(dev_name), "ioexp%d", s->board_idx); + qdev_prop_set_string(DEVICE(&s->i2c), "bus-label", dev_name); + + object_property_set_link(OBJECT(&s->i2c), "dram", + OBJECT(s->dram_mr), errp); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I2C], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c), 0)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ioexp-gpio", &s->gpio, "aspeed.gpio-ast2700"); + /* I2C */ + object_initialize_child(obj, "ioexp-i2c", &s->i2c, + "aspeed.i2c-ast2700"); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2700a1_irqmap[] = { [ASPEED_DEV_EHCI4] = 196, [ASPEED_DEV_PECI] = 197, [ASPEED_DEV_SDHCI] = 197, + [ASPEED_DEV_IOEXP0_I2C] = 198, + [ASPEED_DEV_IOEXP1_I2C] = 200, }; /* GICINT 192 */ @@ -XXX,XX +XXX,XX @@ static const int ast2700_gic197_intcmap[] = { [ASPEED_DEV_PECI] = 4, }; +/* Primary AST1700 Interrupts */ +/* A1: GICINT 198 */ +static const int ast2700_gic198_intcmap[] = { + [ASPEED_DEV_IOEXP0_I2C] = 0, /* 0 - 15 */ +}; + +/* Secondary AST1700 Interrupts */ +/* A1: GINTC 200 */ +static const int ast2700_gic200_intcmap[] = { + [ASPEED_DEV_IOEXP1_I2C] = 0, /* 0 - 15 */ +}; + /* GICINT 192 ~ 201 */ struct gic_intc_irq_info { int irq; @@ -XXX,XX +XXX,XX @@ static const struct gic_intc_irq_info ast2700_gic_intcmap[] = { {195, 1, 3, ast2700_gic195_intcmap}, {196, 1, 4, ast2700_gic196_intcmap}, {197, 1, 5, ast2700_gic197_intcmap}, - {198, 1, 6, NULL}, + {198, 2, 0, ast2700_gic198_intcmap}, {199, 1, 7, NULL}, - {200, 1, 8, NULL}, + {200, 3, 0, ast2700_gic200_intcmap}, {201, 1, 9, NULL}, }; @@ -XXX,XX +XXX,XX @@ static qemu_irq aspeed_soc_ast2700_get_irq_index(AspeedSoCState *s, int dev, int or_idx; int idx; int i; + OrIRQState *porgates; for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) { if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) { assert(ast2700_gic_intcmap[i].ptr); or_idx = ast2700_gic_intcmap[i].orgate_idx; idx = ast2700_gic_intcmap[i].intc_idx; - return qdev_get_gpio_in(DEVICE(&a->intc[idx].orgates[or_idx]), + if (idx < ASPEED_INTC_NUM) { + porgates = &a->intc[idx].orgates[or_idx]; + return qdev_get_gpio_in(DEVICE(porgates), + ast2700_gic_intcmap[i].ptr[dev] + index); + } else { + idx -= ASPEED_INTC_NUM; + porgates = &a->intcioexp[idx].orgates[or_idx]; + return qdev_get_gpio_in(DEVICE(porgates), ast2700_gic_intcmap[i].ptr[dev] + index); + } } } @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) /* IO Expander */ for (i = 0; i < sc->ioexp_num; i++) { + AspeedI2CClass *i2c_ctl; + qdev_prop_set_uint8(DEVICE(&s->ioexp[i]), "board-idx", i); object_property_set_link(OBJECT(&s->ioexp[i]), "dram", OBJECT(s->dram_mr), &error_abort); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].gpio), 0, aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_GPIO)); + /* I2C */ + i2c_ctl = ASPEED_I2C_GET_CLASS(&s->ioexp[i].i2c); + for (int j = 0; j < i2c_ctl->num_busses; j++) { + /* + * For I2C on AST1700: + * I2C bus interrupts are connected to the OR gate from bit 0 to bit + * 15, and the OR gate output pin is connected to the input pin of + * GICINT192 of IO expander Interrupt controller (INTC2/3). Then, + * the output pin is connected to the INTC (CPU Die) input pin, and + * its output pin is connected to the GIC. + * + * I2C bus 0 is connected to the OR gate at bit 0. + * I2C bus 15 is connected to the OR gate at bit 15. + */ + irq = aspeed_soc_ast2700_get_irq_index(s, + ASPEED_DEV_IOEXP0_I2C + i, + j); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].i2c.busses[j]), + 0, irq); + } } aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu), -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the WDT device to AST1700 model. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-16-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 4 ++++ hw/arm/aspeed_ast1700.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/i2c/aspeed_i2c.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/ssi/aspeed_smc.h" +#include "hw/watchdog/wdt_aspeed.h" #include "hw/char/serial-mm.h" +#define AST1700_WDT_NUM 9 + #define TYPE_ASPEED_AST1700 "aspeed.ast1700" OBJECT_DECLARE_SIMPLE_TYPE(AspeedAST1700SoCState, ASPEED_AST1700) @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { AspeedSCUState scu; AspeedGPIOState gpio; AspeedI2CState i2c; + AspeedWDTState wdt[AST1700_WDT_NUM]; }; #endif /* ASPEED_AST1700_H */ diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_I2C, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, + ASPEED_AST1700_DEV_WDT, ASPEED_AST1700_DEV_SPI0_MEM, }; @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_I2C] = 0x00C0F000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, + [ASPEED_AST1700_DEV_WDT] = 0x00C37000, [ASPEED_AST1700_DEV_SPI0_MEM] = 0x04000000, }; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->iomem, aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_LTPI_CTRL], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ltpi), 0)); + /* WDT */ + for (int i = 0; i < AST1700_WDT_NUM; i++) { + AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]); + hwaddr wdt_offset = aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_WDT] + + i * awc->iosize; + + object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu), + errp); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + wdt_offset, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->wdt[i]), 0)); + } + } static void aspeed_ast1700_instance_init(Object *obj) @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); + /* WDT */ + for (int i = 0; i < AST1700_WDT_NUM; i++) { + object_initialize_child(obj, "ioexp-wdt[*]", + &s->wdt[i], "aspeed.wdt-ast2700"); + } + return; } -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the PWM device to AST1700 model. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-17-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 2 ++ hw/arm/aspeed_ast1700.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/gpio/aspeed_gpio.h" #include "hw/i2c/aspeed_i2c.h" #include "hw/misc/aspeed_ltpi.h" +#include "hw/misc/aspeed_pwm.h" #include "hw/ssi/aspeed_smc.h" #include "hw/watchdog/wdt_aspeed.h" #include "hw/char/serial-mm.h" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { AspeedSCUState scu; AspeedGPIOState gpio; AspeedI2CState i2c; + AspeedPWMState pwm; AspeedWDTState wdt[AST1700_WDT_NUM]; }; diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_SPI0, + ASPEED_AST1700_DEV_PWM, ASPEED_AST1700_DEV_SRAM, ASPEED_AST1700_DEV_ADC, ASPEED_AST1700_DEV_SCU, @@ -XXX,XX +XXX,XX @@ enum { static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_SPI0] = 0x00030000, + [ASPEED_AST1700_DEV_PWM] = 0x000C0000, [ASPEED_AST1700_DEV_SRAM] = 0x00BC0000, [ASPEED_AST1700_DEV_ADC] = 0x00C00000, [ASPEED_AST1700_DEV_SCU] = 0x00C02000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I2C], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c), 0)); + /* PWM */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->pwm), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_PWM], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pwm), 0)); + /* LTPI controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) { return; @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ioexp-i2c", &s->i2c, "aspeed.i2c-ast2700"); + /* PWM */ + object_initialize_child(obj, "pwm", &s->pwm, TYPE_ASPEED_PWM); + /* LTPI controller */ object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Connect the SGPIOM device to AST1700 model. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-18-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 3 +++ hw/arm/aspeed_ast1700.c | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/misc/aspeed_scu.h" #include "hw/adc/aspeed_adc.h" #include "hw/gpio/aspeed_gpio.h" +#include "hw/gpio/aspeed_sgpio.h" #include "hw/i2c/aspeed_i2c.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/misc/aspeed_pwm.h" @@ -XXX,XX +XXX,XX @@ #include "hw/watchdog/wdt_aspeed.h" #include "hw/char/serial-mm.h" +#define AST1700_SGPIO_NUM 2 #define AST1700_WDT_NUM 9 #define TYPE_ASPEED_AST1700 "aspeed.ast1700" @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { AspeedADCState adc; AspeedSCUState scu; AspeedGPIOState gpio; + AspeedSGPIOState sgpiom[AST1700_SGPIO_NUM]; AspeedI2CState i2c; AspeedPWMState pwm; AspeedWDTState wdt[AST1700_WDT_NUM]; diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_ADC, ASPEED_AST1700_DEV_SCU, ASPEED_AST1700_DEV_GPIO, + ASPEED_AST1700_DEV_SGPIOM0, + ASPEED_AST1700_DEV_SGPIOM1, ASPEED_AST1700_DEV_I2C, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_ADC] = 0x00C00000, [ASPEED_AST1700_DEV_SCU] = 0x00C02000, [ASPEED_AST1700_DEV_GPIO] = 0x00C0B000, + [ASPEED_AST1700_DEV_SGPIOM0] = 0x00C0C000, + [ASPEED_AST1700_DEV_SGPIOM1] = 0x00C0D000, [ASPEED_AST1700_DEV_I2C] = 0x00C0F000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->iomem, aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_LTPI_CTRL], sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ltpi), 0)); + + /* SGPIOM */ + for (int i = 0; i < AST1700_SGPIO_NUM; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sgpiom[i]), errp)) { + return; + } + memory_region_add_subregion(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SGPIOM0 + i], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sgpiom[i]), 0)); + } + /* WDT */ for (int i = 0; i < AST1700_WDT_NUM; i++) { AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]); @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) object_initialize_child(obj, "ltpi-ctrl", &s->ltpi, TYPE_ASPEED_LTPI); + /* SGPIOM */ + for (int i = 0; i < AST1700_SGPIO_NUM; i++) { + object_initialize_child(obj, "ioexp-sgpiom[*]", &s->sgpiom[i], + "aspeed.sgpio-ast2700"); + } + /* WDT */ for (int i = 0; i < AST1700_WDT_NUM; i++) { object_initialize_child(obj, "ioexp-wdt[*]", -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> AST1700 exposes more I3C buses than the current dummy I3C model provides. When Linux probes the I3C devices on AST1700 this mismatch can trigger a kernel panic. Model the I3C block as an unimplemented device to make the missing functionality explicit and avoid unexpected side effects. This wires up the I3C interrupt lines for the IO expanders and adds the corresponding device entries for the AST1700 model. No functional I3C emulation is provided yet; this only prevents crashes and documents the missing piece. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-19-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/arm/aspeed_ast1700.h | 3 +++ include/hw/arm/aspeed_soc.h | 2 ++ hw/arm/aspeed_ast1700.c | 15 +++++++++++++++ hw/arm/aspeed_ast27x0.c | 18 ++++++++++++++++-- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_ast1700.h +++ b/include/hw/arm/aspeed_ast1700.h @@ -XXX,XX +XXX,XX @@ #include "hw/ssi/aspeed_smc.h" #include "hw/watchdog/wdt_aspeed.h" #include "hw/char/serial-mm.h" +#include "hw/misc/unimp.h" #define AST1700_SGPIO_NUM 2 #define AST1700_WDT_NUM 9 @@ -XXX,XX +XXX,XX @@ struct AspeedAST1700SoCState { AspeedI2CState i2c; AspeedPWMState pwm; AspeedWDTState wdt[AST1700_WDT_NUM]; + + UnimplementedDeviceState i3c; }; #endif /* ASPEED_AST1700_H */ diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -XXX,XX +XXX,XX @@ enum { ASPEED_DEV_IOEXP1_I2C, ASPEED_DEV_IOEXP0_INTCIO, ASPEED_DEV_IOEXP1_INTCIO, + ASPEED_DEV_IOEXP0_I3C, + ASPEED_DEV_IOEXP1_I3C, }; const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types); diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast1700.c +++ b/hw/arm/aspeed_ast1700.c @@ -XXX,XX +XXX,XX @@ #define AST2700_SOC_LTPI_SIZE 0x01000000 #define AST1700_SOC_SRAM_SIZE 0x00040000 +#define AST1700_SOC_I3C_SIZE 0x00010000 enum { ASPEED_AST1700_DEV_SPI0, @@ -XXX,XX +XXX,XX @@ enum { ASPEED_AST1700_DEV_SGPIOM0, ASPEED_AST1700_DEV_SGPIOM1, ASPEED_AST1700_DEV_I2C, + ASPEED_AST1700_DEV_I3C, ASPEED_AST1700_DEV_UART12, ASPEED_AST1700_DEV_LTPI_CTRL, ASPEED_AST1700_DEV_WDT, @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_ast1700_io_memmap[] = { [ASPEED_AST1700_DEV_SGPIOM0] = 0x00C0C000, [ASPEED_AST1700_DEV_SGPIOM1] = 0x00C0D000, [ASPEED_AST1700_DEV_I2C] = 0x00C0F000, + [ASPEED_AST1700_DEV_I3C] = 0x00C20000, [ASPEED_AST1700_DEV_UART12] = 0x00C33B00, [ASPEED_AST1700_DEV_LTPI_CTRL] = 0x00C34000, [ASPEED_AST1700_DEV_WDT] = 0x00C37000, @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_realize(DeviceState *dev, Error **errp) sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->wdt[i]), 0)); } + /* I3C */ + qdev_prop_set_string(DEVICE(&s->i3c), "name", "ioexp-i3c"); + qdev_prop_set_uint64(DEVICE(&s->i3c), "size", AST1700_SOC_I3C_SIZE); + sysbus_realize(SYS_BUS_DEVICE(&s->i3c), errp); + memory_region_add_subregion_overlap(&s->iomem, + aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I3C], + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i3c), 0), + -1000); } static void aspeed_ast1700_instance_init(Object *obj) @@ -XXX,XX +XXX,XX @@ static void aspeed_ast1700_instance_init(Object *obj) &s->wdt[i], "aspeed.wdt-ast2700"); } + /* I3C */ + object_initialize_child(obj, "ioexp-i3c", &s->i3c, + TYPE_UNIMPLEMENTED_DEVICE); + return; } diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2700a1_irqmap[] = { [ASPEED_DEV_PECI] = 197, [ASPEED_DEV_SDHCI] = 197, [ASPEED_DEV_IOEXP0_I2C] = 198, + [ASPEED_DEV_IOEXP0_I3C] = 199, [ASPEED_DEV_IOEXP1_I2C] = 200, + [ASPEED_DEV_IOEXP1_I3C] = 201, }; /* GICINT 192 */ @@ -XXX,XX +XXX,XX @@ static const int ast2700_gic198_intcmap[] = { [ASPEED_DEV_IOEXP0_I2C] = 0, /* 0 - 15 */ }; +/* Primary AST1700 Interrupts */ +/* A1: GINTC 199 */ +static const int ast2700_gic199_intcmap[] = { + [ASPEED_DEV_IOEXP0_I3C] = 0, /* 0 - 15 */ +}; + /* Secondary AST1700 Interrupts */ /* A1: GINTC 200 */ static const int ast2700_gic200_intcmap[] = { [ASPEED_DEV_IOEXP1_I2C] = 0, /* 0 - 15 */ }; +/* Secondary AST1700 Interrupts */ +/* A1: GINTC 201 */ +static const int ast2700_gic201_intcmap[] = { + [ASPEED_DEV_IOEXP1_I3C] = 0, /* 0 - 15 */ +}; + /* GICINT 192 ~ 201 */ struct gic_intc_irq_info { int irq; @@ -XXX,XX +XXX,XX @@ static const struct gic_intc_irq_info ast2700_gic_intcmap[] = { {196, 1, 4, ast2700_gic196_intcmap}, {197, 1, 5, ast2700_gic197_intcmap}, {198, 2, 0, ast2700_gic198_intcmap}, - {199, 1, 7, NULL}, + {199, 2, 1, ast2700_gic199_intcmap}, {200, 3, 0, ast2700_gic200_intcmap}, - {201, 1, 9, NULL}, + {201, 3, 1, ast2700_gic201_intcmap}, }; static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev) -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Set ioexp_num to 2 to enable AST1700 IO expander support. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Nabih Estefan <nabihestefan@google.com> Tested-by: Nabih Estefan <nabihestefan@google.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-20-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast27x0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700a1_class_init(ObjectClass *oc, const void *data) sc->macs_num = 3; sc->uarts_num = 13; sc->num_cpus = 4; - sc->ioexp_num = 0; + sc->ioexp_num = 2; sc->uarts_base = ASPEED_DEV_UART0; sc->irqmap = aspeed_soc_ast2700a1_irqmap; sc->memmap = aspeed_soc_ast2700_memmap; -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> The current Aspeed AST2700 functional test case strictly uses I2C bus 1 for its sensor tests. This hard-coded approach prevents the test logic from being reused for other machine types or configurations where I2C bus 1 might be disabled or where a different bus needs to be verified (e.g., I2C expanders). This refactoring allows the same I2C verification logic to be shared across different test scenarios by simply passing the target bus number. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-21-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- .../functional/aarch64/test_aspeed_ast2700.py | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700.py +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -XXX,XX +XXX,XX @@ class AST2x00MachineSDK(QemuSystemTest): - def do_test_aarch64_aspeed_sdk_start(self, image): + def do_test_aarch64_aspeed_sdk_start(self, image, bus_id): + bus_str = str(bus_id) self.require_netdev('user') self.vm.set_console() - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test') + self.vm.add_args( + '-device', + f'tmp105,' + f'bus=aspeed.i2c.bus.{bus_str},' + f'address=0x4d,' + f'id=tmp-test-{bus_str}' + ) self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', '-net', 'nic', '-net', 'user', '-snapshot') @@ -XXX,XX +XXX,XX @@ def verify_openbmc_boot_and_login(self, name): 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-obmc.tar.gz', 'd5ceed511cd0dfefbb102fff2d731159e0472948a28066dc0d90bcd54be76525') - def do_ast2700_i2c_test(self): + def do_ast2700_i2c_test(self, bus_id): + bus_str = str(bus_id) exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ', - 'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d') + f'echo lm75 0x4d > /sys/class/i2c-dev/i2c-{bus_str}/device/new_device ', + f'i2c i2c-{bus_str}: new_device: Instantiated device lm75 at 0x4d') exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + f'cat /sys/bus/i2c/devices/{bus_str}-004d/hwmon/hwmon*/temp1_input', '0') + self.vm.cmd('qom-set', path=f'/machine/peripheral/tmp-test-{bus_str}', property='temperature', value=18000) exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000') + f'cat /sys/bus/i2c/devices/{bus_str}-004d/hwmon/hwmon*/temp1_input', '18000') def do_ast2700_pcie_test(self): exec_command_and_wait_for_pattern(self, @@ -XXX,XX +XXX,XX @@ def do_ast2700_pcie_test(self): 'ip addr show dev eth2', 'inet 10.0.2.15/24') - def start_ast2700_test(self, name): + def start_ast2700_test(self, name, bus_id): num_cpu = 4 load_images_list = [ { @@ -XXX,XX +XXX,XX @@ def start_ast2700_test(self, name): self.vm.add_args('-smp', str(num_cpu)) self.do_test_aarch64_aspeed_sdk_start( - self.scratch_file(name, 'image-bmc')) + self.scratch_file(name, 'image-bmc'), bus_id) - def start_ast2700_test_vbootrom(self, name): + def start_ast2700_test_vbootrom(self, name, bus_id): self.vm.add_args('-bios', 'ast27x0_bootrom.bin') self.do_test_aarch64_aspeed_sdk_start( - self.scratch_file(name, 'image-bmc')) + self.scratch_file(name, 'image-bmc'), bus_id) def test_aarch64_ast2700a1_evb_sdk_v11_00(self): self.set_machine('ast2700a1-evb') @@ -XXX,XX +XXX,XX @@ def test_aarch64_ast2700a1_evb_sdk_v11_00(self): self.archive_extract(self.ASSET_SDK_V1100_AST2700A1) self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2') self.vm.add_args('-netdev', 'user,id=net1') - self.start_ast2700_test('ast2700-a1') + self.start_ast2700_test('ast2700-a1', 1) self.verify_openbmc_boot_and_login('ast2700-a1') - self.do_ast2700_i2c_test() + self.do_ast2700_i2c_test(1) self.do_ast2700_pcie_test() def test_aarch64_ast2700a1_evb_sdk_vbootrom_v11_00(self): @@ -XXX,XX +XXX,XX @@ def test_aarch64_ast2700a1_evb_sdk_vbootrom_v11_00(self): self.archive_extract(self.ASSET_SDK_V1100_AST2700A1) self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2') self.vm.add_args('-netdev', 'user,id=net1') - self.start_ast2700_test_vbootrom('ast2700-a1') + self.start_ast2700_test_vbootrom('ast2700-a1', 1) self.verify_vbootrom_firmware_flow() self.verify_openbmc_boot_start() -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> The current AST2700 functional test forces PCIe2 enablement by manually manipulating U-Boot env and FDT via the console. This sequence interferes with test cases that rely on the default boot flow of the image. Introduce a 'enable_pcie' parameter (defaulting to True) to both 'verify_openbmc_boot_start' and 'verify_openbmc_boot_and_login' methods. This allow test cases to toggle the PCIe2 initialization sequence based on their specific requirements without breaking standard boot tests. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-22-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/aarch64/test_aspeed_ast2700.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700.py +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -XXX,XX +XXX,XX @@ def enable_ast2700_pcie2(self): 'fdt set /soc@14000000/pcie@140d0000 status "okay"', '=>') exec_command(self, 'bootm go') - def verify_openbmc_boot_start(self): + def verify_openbmc_boot_start(self, enable_pcie=True): wait_for_console_pattern(self, 'U-Boot 2023.10') - self.enable_ast2700_pcie2() + if enable_pcie: + self.enable_ast2700_pcie2() wait_for_console_pattern(self, 'Linux version ') - def verify_openbmc_boot_and_login(self, name): - self.verify_openbmc_boot_start() + def verify_openbmc_boot_and_login(self, name, enable_pcie=True): + self.verify_openbmc_boot_start(enable_pcie) wait_for_console_pattern(self, f'{name} login:') exec_command_and_wait_for_pattern(self, 'root', 'Password:') -- 2.52.0
From: Kane Chen <kane_chen@aspeedtech.com> Extend the AST2700 test suite to verify I2C connectivity on AST1700 IO expanders using the DCSCM image. This validates the new bus-label naming scheme by testing communication on both primary and expander-attached I2C buses. Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260204082113.3955407-23-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/aarch64/test_aspeed_ast2700.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700.py +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -XXX,XX +XXX,XX @@ def verify_openbmc_boot_and_login(self, name, enable_pcie=True): 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-obmc.tar.gz', 'd5ceed511cd0dfefbb102fff2d731159e0472948a28066dc0d90bcd54be76525') + ASSET_SDK_V1100_AST2700A1_DCSCM = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-dcscm-obmc.tar.gz', + '4f8778be176ece1b57d33c4aee13bb989be114c3e4703150eaeb6f996bd5587f') + def do_ast2700_i2c_test(self, bus_id): bus_str = str(bus_id) exec_command_and_wait_for_pattern(self, @@ -XXX,XX +XXX,XX @@ def test_aarch64_ast2700a1_evb_sdk_vbootrom_v11_00(self): self.verify_vbootrom_firmware_flow() self.verify_openbmc_boot_start() + def test_aarch64_ast2700a1_evb_ioexp_v11_00(self): + self.set_machine('ast2700a1-evb') + self.require_netdev('user') + + self.archive_extract(self.ASSET_SDK_V1100_AST2700A1_DCSCM) + self.vm.set_machine('ast2700a1-evb,fmc-model=w25q512jv') + self.vm.add_args('-device', + 'tmp105,bus=ioexp0.0,address=0x4d,id=tmp-test-16') + self.start_ast2700_test('ast2700-a1-dcscm', 8) + self.verify_openbmc_boot_and_login('ast2700-a1-dcscm', False) + self.do_ast2700_i2c_test(8) + self.do_ast2700_i2c_test(16) + if __name__ == '__main__': QemuSystemTest.main() -- 2.52.0