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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmhnknUACgkQUaNDx8/7
 7KFPDBAAiHW7cu64JszAPk3SBHR8b021JpOrnF9Xp/UHMjNt0Kuazm6jkc/FeOJf
 yOKGfvuZUiLLcTrN8iCrVjjxIMKlzQP4KQEFaAPyxvKZo6j4czFZQ7AHS3G28w8l
 qrF4UsOhgQ6TL6fXMyqzDSLDEf5o/1ZCn1t+wkuDeVR7YVoAFj/si/A+qmIGQODJ
 egVmBopUzGrnGCcZREcKfJKmx1JOfVGFpm5HHPlazCaNTyKynd4rm2qP2St1eDEQ
 vOvSBZXKUHmpV9ckdY+Hp0VHvO2oIifDTN+Zbd2XT9RxO36VMnQxiSxOZOj/aRWa
 dc87OprPKjjS7Tbg7SZF7ySgfOShXWtNOwLuyrlw6BFsaHtwU2VP/mYR/Tfz/1Lw
 57ufAj04nh8bWp7LApXyui53/1X431oBFji6agWnonMut+e5Xv0JKdBeCu2y8Fj4
 wPpiNcaa8AgHUuJ8T/WXrogeAYXYPI7z1iCY5tX9xffvcL6B3cVLGlI+mXoCIK7O
 MTuS5d8CB0gQondLS0Y86ls5pM3RkW6izragH38ukuubKIRq1hjxFDBnF8AQJl7A
 pUWTTxhxNZaJie0F5grD7aCVPCSSr1ck1V3zbW/ffVX+7kEtCBW/Zk4qfw9/SGxd
 2QKbstRPNgTl78EKquYwipFVNyHTP/W8iXfxwpFALKBJFkmzAjQ=
 =i7wx
 -----END PGP SIGNATURE-----

Merge tag 'pull-aspeed-20250704' of https://github.com/legoater/qemu into staging

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

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmhnknUACgkQUaNDx8/7
# 7KFPDBAAiHW7cu64JszAPk3SBHR8b021JpOrnF9Xp/UHMjNt0Kuazm6jkc/FeOJf
# yOKGfvuZUiLLcTrN8iCrVjjxIMKlzQP4KQEFaAPyxvKZo6j4czFZQ7AHS3G28w8l
# qrF4UsOhgQ6TL6fXMyqzDSLDEf5o/1ZCn1t+wkuDeVR7YVoAFj/si/A+qmIGQODJ
# egVmBopUzGrnGCcZREcKfJKmx1JOfVGFpm5HHPlazCaNTyKynd4rm2qP2St1eDEQ
# vOvSBZXKUHmpV9ckdY+Hp0VHvO2oIifDTN+Zbd2XT9RxO36VMnQxiSxOZOj/aRWa
# dc87OprPKjjS7Tbg7SZF7ySgfOShXWtNOwLuyrlw6BFsaHtwU2VP/mYR/Tfz/1Lw
# 57ufAj04nh8bWp7LApXyui53/1X431oBFji6agWnonMut+e5Xv0JKdBeCu2y8Fj4
# wPpiNcaa8AgHUuJ8T/WXrogeAYXYPI7z1iCY5tX9xffvcL6B3cVLGlI+mXoCIK7O
# MTuS5d8CB0gQondLS0Y86ls5pM3RkW6izragH38ukuubKIRq1hjxFDBnF8AQJl7A
# pUWTTxhxNZaJie0F5grD7aCVPCSSr1ck1V3zbW/ffVX+7kEtCBW/Zk4qfw9/SGxd
# 2QKbstRPNgTl78EKquYwipFVNyHTP/W8iXfxwpFALKBJFkmzAjQ=
# =i7wx
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 04 Jul 2025 04:36:05 EDT
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full]
# gpg:                 aka "Cédric Le Goater <clg@kaod.org>" [full]
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* tag 'pull-aspeed-20250704' of https://github.com/legoater/qemu:
  tests/functional: Add gb200 tests
  hw/arm/aspeed: Add GB200 BMC target
  docs: add support for gb200-bmc
  hw/arm/aspeed: Add second SPI chip to Aspeed model
  aspeed: Deprecate the ast2700a0-evb machine
  tests/qtest: Add test for ASPEED SCU
  hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly
  hw/arm/aspeed: add Catalina machine type
  hw/arm/aspeed: bletchley: update hw strap values
  hw/misc/aspeed_scu: Support the Frequency Counter Control register for AST2700
  hw/misc/aspeed_sdmc: Skipping dram_init in u-boot for AST2700

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-07-04 08:58:27 -04:00
commit a876b05d38
15 changed files with 636 additions and 9 deletions

View file

@ -315,6 +315,14 @@ deprecated; use the new name ``dtb-randomness`` instead. The new name
better reflects the way this property affects all random data within better reflects the way this property affects all random data within
the device tree blob, not just the ``kaslr-seed`` node. 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) Mips ``mipssim`` machine (since 10.0)
''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''

View file

@ -1,5 +1,4 @@
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 The QEMU Aspeed machines model BMCs of various OpenPOWER systems and
Aspeed evaluation boards. They are based on different releases of the Aspeed evaluation boards. They are based on different releases of the
@ -35,6 +34,7 @@ AST2600 SoC based machines :
- ``fuji-bmc`` Facebook Fuji BMC - ``fuji-bmc`` Facebook Fuji BMC
- ``bletchley-bmc`` Facebook Bletchley BMC - ``bletchley-bmc`` Facebook Bletchley BMC
- ``fby35-bmc`` Facebook fby35 BMC - ``fby35-bmc`` Facebook fby35 BMC
- ``gb200nvl-bmc`` Nvidia GB200nvl BMC
- ``qcom-dc-scm-v1-bmc`` Qualcomm DC-SCM V1 BMC - ``qcom-dc-scm-v1-bmc`` Qualcomm DC-SCM V1 BMC
- ``qcom-firework-bmc`` Qualcomm Firework BMC - ``qcom-firework-bmc`` Qualcomm Firework BMC

View file

@ -532,6 +532,7 @@ config ASPEED_SOC
select I2C select I2C
select DPS310 select DPS310
select PCA9552 select PCA9552
select PCA9554
select SERIAL_MM select SERIAL_MM
select SMBUS_EEPROM select SMBUS_EEPROM
select PCA954X select PCA954X

View file

@ -19,6 +19,7 @@
#include "hw/i2c/i2c_mux_pca954x.h" #include "hw/i2c/i2c_mux_pca954x.h"
#include "hw/i2c/smbus_eeprom.h" #include "hw/i2c/smbus_eeprom.h"
#include "hw/gpio/pca9552.h" #include "hw/gpio/pca9552.h"
#include "hw/gpio/pca9554.h"
#include "hw/nvram/eeprom_at24c.h" #include "hw/nvram/eeprom_at24c.h"
#include "hw/sensor/tmp105.h" #include "hw/sensor/tmp105.h"
#include "hw/misc/led.h" #include "hw/misc/led.h"
@ -197,9 +198,12 @@ struct AspeedMachineState {
#define FUJI_BMC_HW_STRAP2 0x00000000 #define FUJI_BMC_HW_STRAP2 0x00000000
/* Bletchley hardware value */ /* Bletchley hardware value */
/* TODO: Leave same as EVB for now. */ #define BLETCHLEY_BMC_HW_STRAP1 0x00002000
#define BLETCHLEY_BMC_HW_STRAP1 AST2600_EVB_HW_STRAP1 #define BLETCHLEY_BMC_HW_STRAP2 0x00000801
#define BLETCHLEY_BMC_HW_STRAP2 AST2600_EVB_HW_STRAP2
/* 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 */ /* Qualcomm DC-SCM hardware value */
#define QCOM_DC_SCM_V1_BMC_HW_STRAP1 0x00000000 #define QCOM_DC_SCM_V1_BMC_HW_STRAP1 0x00000000
@ -465,6 +469,8 @@ static void aspeed_machine_init(MachineState *machine)
aspeed_board_init_flashes(&bmc->soc->spi[0], aspeed_board_init_flashes(&bmc->soc->spi[0],
bmc->spi_model ? bmc->spi_model : amc->spi_model, bmc->spi_model ? bmc->spi_model : amc->spi_model,
1, amc->num_cs); 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) { if (machine->kernel_filename && sc->num_cpus > 1) {
@ -645,6 +651,12 @@ static void create_pca9552(AspeedSoCState *soc, int bus_id, int addr)
TYPE_PCA9552, 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) static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc)
{ {
AspeedSoCState *soc = bmc->soc; AspeedSoCState *soc = bmc->soc;
@ -1003,6 +1015,180 @@ static void fuji_bmc_i2c_init(AspeedMachineState *bmc)
} }
#define TYPE_TMP421 "tmp421" #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) static void bletchley_bmc_i2c_init(AspeedMachineState *bmc)
{ {
@ -1050,6 +1236,45 @@ static void bletchley_bmc_i2c_init(AspeedMachineState *bmc)
i2c_slave_create_simple(i2c[12], TYPE_PCA9552, 0x67); 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) static void fby35_i2c_init(AspeedMachineState *bmc)
{ {
AspeedSoCState *soc = bmc->soc; AspeedSoCState *soc = bmc->soc;
@ -1585,6 +1810,52 @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc,
aspeed_machine_class_init_cpus_defaults(mc); 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);
}
#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) static void fby35_reset(MachineState *state, ResetType type)
{ {
AspeedMachineState *bmc = ASPEED_MACHINE(state); AspeedMachineState *bmc = ASPEED_MACHINE(state);
@ -1877,6 +2148,14 @@ static const TypeInfo aspeed_machine_types[] = {
.name = MACHINE_TYPE_NAME("bletchley-bmc"), .name = MACHINE_TYPE_NAME("bletchley-bmc"),
.parent = TYPE_ASPEED_MACHINE, .parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_bletchley_class_init, .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,
.class_init = aspeed_machine_catalina_class_init,
}, { }, {
.name = MACHINE_TYPE_NAME("fby35-bmc"), .name = MACHINE_TYPE_NAME("fby35-bmc"),
.parent = MACHINE_TYPE_NAME("ast2600-evb"), .parent = MACHINE_TYPE_NAME("ast2600-evb"),

View file

@ -162,6 +162,25 @@ const uint8_t rainier_bmc_fruid[] = {
0x31, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 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 tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid);
const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid); const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid);
const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid); const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid);
@ -169,3 +188,5 @@ 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 yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid);
const size_t rainier_bb_fruid_len = sizeof(rainier_bb_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 rainier_bmc_fruid_len = sizeof(rainier_bmc_fruid);
const size_t gb200nvl_bmc_fruid_len = sizeof(gb200nvl_bmc_fruid);

View file

@ -26,4 +26,7 @@ extern const size_t rainier_bb_fruid_len;
extern const uint8_t rainier_bmc_fruid[]; extern const uint8_t rainier_bmc_fruid[];
extern const size_t rainier_bmc_fruid_len; extern const size_t rainier_bmc_fruid_len;
extern const uint8_t gb200nvl_bmc_fruid[];
extern const size_t gb200nvl_bmc_fruid_len;
#endif #endif

View file

@ -91,6 +91,7 @@
#define BMC_DEV_ID TO_REG(0x1A4) #define BMC_DEV_ID TO_REG(0x1A4)
#define AST2600_PROT_KEY TO_REG(0x00) #define AST2600_PROT_KEY TO_REG(0x00)
#define AST2600_PROT_KEY2 TO_REG(0x10)
#define AST2600_SILICON_REV TO_REG(0x04) #define AST2600_SILICON_REV TO_REG(0x04)
#define AST2600_SILICON_REV2 TO_REG(0x14) #define AST2600_SILICON_REV2 TO_REG(0x14)
#define AST2600_SYS_RST_CTRL TO_REG(0x40) #define AST2600_SYS_RST_CTRL TO_REG(0x40)
@ -176,6 +177,7 @@
#define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330) #define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
#define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334) #define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388) #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 #define SCU_IO_REGION_SIZE 0x1000
@ -722,6 +724,8 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
int reg = TO_REG(offset); int reg = TO_REG(offset);
/* Truncate here so bitwise operations below behave as expected */ /* Truncate here so bitwise operations below behave as expected */
uint32_t data = data64; 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) { if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
@ -730,15 +734,24 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
return; 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__); qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
return;
} }
trace_aspeed_scu_write(offset, size, data); trace_aspeed_scu_write(offset, size, data);
switch (reg) { switch (reg) {
case AST2600_PROT_KEY: 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; return;
case AST2600_HW_STRAP1: case AST2600_HW_STRAP1:
case AST2600_HW_STRAP2: case AST2600_HW_STRAP2:
@ -1022,6 +1035,10 @@ static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
s->regs[reg - 1] ^= data; s->regs[reg - 1] ^= data;
updated = true; updated = true;
break; break;
case AST2700_SCUIO_FREQ_CNT_CTL:
s->regs[reg] = deposit32(s->regs[reg], 6, 1, !!(data & BIT(1)));
updated = true;
break;
default: default:
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n", "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
@ -1066,6 +1083,7 @@ static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
[AST2700_SCUIO_UARTCLK_GEN] = 0x00014506, [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
[AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0, [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
[AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2, [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) static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data)

View file

@ -570,6 +570,9 @@ static void aspeed_2700_sdmc_reset(DeviceState *dev)
/* Set ram size bit and defaults values */ /* Set ram size bit and defaults values */
s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0); s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
/* Skipping dram init */
s->regs[R_MAIN_CONTROL] = BIT(16);
if (s->unlocked) { if (s->unlocked) {
s->regs[R_2700_PROT] = PROT_UNLOCKED; s->regs[R_2700_PROT] = PROT_UNLOCKED;
} }

View file

@ -35,7 +35,9 @@ struct AspeedMachineClass {
uint32_t hw_strap2; uint32_t hw_strap2;
const char *fmc_model; const char *fmc_model;
const char *spi_model; const char *spi_model;
const char *spi2_model;
uint32_t num_cs; uint32_t num_cs;
uint32_t num_cs2;
uint32_t macs_mask; uint32_t macs_mask;
void (*i2c_init)(AspeedMachineState *bmc); void (*i2c_init)(AspeedMachineState *bmc);
uint32_t uart_default; uint32_t uart_default;

View file

@ -8,7 +8,12 @@ from qemu_test import LinuxKernelTest
class AspeedTest(LinuxKernelTest): class AspeedTest(LinuxKernelTest):
def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04', def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04',
cpu_id='0x0', soc='AST2500 rev A1'): 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') hostname = machine.removesuffix('-bmc')
self.set_machine(machine) self.set_machine(machine)

View file

@ -32,6 +32,8 @@ test_timeouts = {
'arm_aspeed_ast2500' : 720, 'arm_aspeed_ast2500' : 720,
'arm_aspeed_ast2600' : 1200, 'arm_aspeed_ast2600' : 1200,
'arm_aspeed_bletchley' : 480, 'arm_aspeed_bletchley' : 480,
'arm_aspeed_catalina' : 480,
'arm_aspeed_gb200nvl_bmc' : 480,
'arm_aspeed_rainier' : 480, 'arm_aspeed_rainier' : 480,
'arm_bpim2u' : 500, 'arm_bpim2u' : 500,
'arm_collie' : 180, 'arm_collie' : 180,
@ -127,6 +129,8 @@ tests_arm_system_thorough = [
'arm_aspeed_ast2500', 'arm_aspeed_ast2500',
'arm_aspeed_ast2600', 'arm_aspeed_ast2600',
'arm_aspeed_bletchley', 'arm_aspeed_bletchley',
'arm_aspeed_catalina',
'arm_aspeed_gb200nvl_bmc',
'arm_aspeed_rainier', 'arm_aspeed_rainier',
'arm_bpim2u', 'arm_bpim2u',
'arm_canona1100', 'arm_canona1100',

View file

@ -0,0 +1,25 @@
#!/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()

View file

@ -0,0 +1,26 @@
#!/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()

View file

@ -0,0 +1,231 @@
/*
* 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();
}

View file

@ -215,6 +215,7 @@ qtests_npcm8xx = \
qtests_aspeed = \ qtests_aspeed = \
['aspeed_gpio-test', ['aspeed_gpio-test',
'aspeed_hace-test', 'aspeed_hace-test',
'aspeed_scu-test',
'aspeed_smc-test'] 'aspeed_smc-test']
qtests_aspeed64 = \ qtests_aspeed64 = \
['ast2700-gpio-test', ['ast2700-gpio-test',