:p
atchew
Login
The following changes since commit ae35f033b874c627d81d51070187fbf55f0bf1a7: Update version for v9.2.0 release (2024-12-10 16:20:54 +0000) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-aspeed-20241211 for you to fetch changes up to 124f4dc0d832c1bf3a4513c05a2b93bac0a5fac0: test/qtest/ast2700-smc-test: Support to test AST2700 (2024-12-11 07:25:53 +0100) ---------------------------------------------------------------- aspeed queue: * Removed tacoma-bmc machine * Added support for SDHCI on AST2700 SoC * Improved functional tests * Extended SMC qtest to all Aspeed SoCs ---------------------------------------------------------------- Cédric Le Goater (8): arm: Remove tacoma-bmc machine tests/functional: Introduce a specific test for ast1030 SoC tests/functional: Introduce a specific test for palmetto-bmc machine tests/functional: Introduce a specific test for romulus-bmc machine tests/functional: Introduce a specific test for ast2500 SoC tests/functional: Introduce a specific test for ast2600 SoC tests/functional: Introduce a specific test for rainier-bmc machine tests/functional: Move debian boot test from avocado Jamin Lin (16): hw/sd/aspeed_sdhci: Fix coding style hw/arm/aspeed: Fix coding style hw:sdhci: Introduce a new "capareg" class member to set the different Capability Registers hw/sd/aspeed_sdhci: Add AST2700 Support aspeed/soc: Support SDHCI for AST2700 aspeed/soc: Support eMMC for AST2700 test/qtest/aspeed_smc-test: Move testcases to test_palmetto_bmc function test/qtest/aspeed_smc-test: Introduce a new TestData to test different BMC SOCs test/qtest/aspeed_smc-test: Support to test all CE pins test/qtest/aspeed_smc-test: Introducing a "page_addr" data field test/qtest/aspeed_smc-test: Support to test AST2500 test/qtest/aspeed_smc-test: Support to test AST2600 test/qtest/aspeed_smc-test: Support to test AST1030 test/qtest/aspeed_smc-test: Support write page command with QPI mode test/qtest: Introduce a new aspeed-smc-utils.c to place common testcases test/qtest/ast2700-smc-test: Support to test AST2700 docs/about/deprecated.rst | 8 - docs/about/removed-features.rst | 10 + docs/system/arm/aspeed.rst | 1 - include/hw/sd/aspeed_sdhci.h | 13 +- tests/qtest/aspeed-smc-utils.h | 95 ++++ hw/arm/aspeed.c | 28 - hw/arm/aspeed_ast2400.c | 3 +- hw/arm/aspeed_ast2600.c | 10 +- hw/arm/aspeed_ast27x0.c | 35 ++ hw/sd/aspeed_sdhci.c | 67 ++- tests/qtest/aspeed-smc-utils.c | 686 ++++++++++++++++++++++++ tests/qtest/aspeed_smc-test.c | 775 ++++++--------------------- tests/qtest/ast2700-smc-test.c | 71 +++ tests/avocado/boot_linux_console.py | 26 - tests/functional/aspeed.py | 56 ++ tests/functional/meson.build | 13 +- tests/functional/test_arm_aspeed.py | 351 ------------ tests/functional/test_arm_aspeed_ast1030.py | 81 +++ tests/functional/test_arm_aspeed_ast2500.py | 59 ++ tests/functional/test_arm_aspeed_ast2600.py | 143 +++++ tests/functional/test_arm_aspeed_palmetto.py | 24 + tests/functional/test_arm_aspeed_rainier.py | 64 +++ tests/functional/test_arm_aspeed_romulus.py | 24 + tests/qtest/meson.build | 5 +- 24 files changed, 1623 insertions(+), 1025 deletions(-) create mode 100644 tests/qtest/aspeed-smc-utils.h create mode 100644 tests/qtest/aspeed-smc-utils.c create mode 100644 tests/qtest/ast2700-smc-test.c create mode 100644 tests/functional/aspeed.py delete mode 100755 tests/functional/test_arm_aspeed.py create mode 100644 tests/functional/test_arm_aspeed_ast1030.py create mode 100644 tests/functional/test_arm_aspeed_ast2500.py create mode 100644 tests/functional/test_arm_aspeed_ast2600.py create mode 100644 tests/functional/test_arm_aspeed_palmetto.py create mode 100644 tests/functional/test_arm_aspeed_rainier.py create mode 100644 tests/functional/test_arm_aspeed_romulus.py
Removal was scheduled for 10.0. Use the rainier-bmc machine or the ast2600-evb as a replacement. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Link: https://lore.kernel.org/r/20241119071352.515790-1-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- docs/about/deprecated.rst | 8 -------- docs/about/removed-features.rst | 10 ++++++++++ docs/system/arm/aspeed.rst | 1 - hw/arm/aspeed.c | 28 ---------------------------- 4 files changed, 10 insertions(+), 37 deletions(-) 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 @@ images are not available, OpenWRT dropped support in 2019, U-Boot in 2017, Linux also is dropping support in 2024. It is time to let go of this ancient hardware and focus on newer CPUs and platforms. -Arm ``tacoma-bmc`` machine (since 9.1) -'''''''''''''''''''''''''''''''''''''''' - -The ``tacoma-bmc`` machine was a board including an AST2600 SoC based -BMC and a witherspoon like OpenPOWER system. It was used for bring up -of the AST2600 SoC in labs. It can be easily replaced by the -``rainier-bmc`` machine which is a real product. - Big-Endian variants of MicroBlaze ``petalogix-ml605`` and ``xlnx-zynqmp-pmu`` machines (since 9.2) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -XXX,XX +XXX,XX @@ Aspeed ``swift-bmc`` machine (removed in 7.0) This machine was removed because it was unused. Alternative AST2500 based OpenPOWER machines are ``witherspoon-bmc`` and ``romulus-bmc``. +Aspeed ``tacoma-bmc`` machine (removed in 10.0) +''''''''''''''''''''''''''''''''''''''''''''''' + +The ``tacoma-bmc`` machine was removed because it didn't bring much +compared to the ``rainier-bmc`` machine. Also, the ``tacoma-bmc`` was +a board used for bring up of the AST2600 SoC that never left the +labs. It can be easily replaced by the ``rainier-bmc`` machine, which +was the actual final product, or by the ``ast2600-evb`` with some +tweaks. + ppc ``taihu`` machine (removed in 7.2) ''''''''''''''''''''''''''''''''''''''''''''' 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 @@ AST2500 SoC based machines : AST2600 SoC based machines : - ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex-A7) -- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC - ``rainier-bmc`` IBM Rainier POWER10 BMC - ``fuji-bmc`` Facebook Fuji BMC - ``bletchley-bmc`` Facebook Bletchley BMC 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 AST2700_EVB_HW_STRAP2 0x00000003 #endif -/* Tacoma hardware value */ -#define TACOMA_BMC_HW_STRAP1 0x00000000 -#define TACOMA_BMC_HW_STRAP2 0x00000040 - /* Rainier hardware value: (QEMU prototype) */ #define RAINIER_BMC_HW_STRAP1 (0x00422016 | SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC) #define RAINIER_BMC_HW_STRAP2 0x80000848 @@ -XXX,XX +XXX,XX @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data) aspeed_machine_ast2600_class_emmc_init(oc); }; -static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); - - mc->desc = "OpenPOWER Tacoma BMC (Cortex-A7)"; - amc->soc_name = "ast2600-a3"; - amc->hw_strap1 = TACOMA_BMC_HW_STRAP1; - amc->hw_strap2 = TACOMA_BMC_HW_STRAP2; - amc->fmc_model = "mx66l1g45g"; - amc->spi_model = "mx66l1g45g"; - amc->num_cs = 2; - amc->macs_mask = ASPEED_MAC2_ON; - amc->i2c_init = witherspoon_bmc_i2c_init; /* Same board layout */ - mc->default_ram_size = 1 * GiB; - aspeed_machine_class_init_cpus_defaults(mc); - - mc->deprecation_reason = "Please use the similar 'rainier-bmc' machine"; -}; - static void aspeed_machine_g220a_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = { .name = MACHINE_TYPE_NAME("yosemitev2-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_yosemitev2_class_init, - }, { - .name = MACHINE_TYPE_NAME("tacoma-bmc"), - .parent = TYPE_ASPEED_MACHINE, - .class_init = aspeed_machine_tacoma_class_init, }, { .name = MACHINE_TYPE_NAME("tiogapass-bmc"), .parent = TYPE_ASPEED_MACHINE, -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Fix coding style issues from checkpatch.pl. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241204084453.610660-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/sd/aspeed_sdhci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/sd/aspeed_sdhci.c +++ b/hw/sd/aspeed_sdhci.c @@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_write(void *opaque, hwaddr addr, uint64_t val, sdhci->regs[TO_REG(addr)] = (uint32_t)val & ~ASPEED_SDHCI_INFO_RESET; break; case ASPEED_SDHCI_SDIO_140: - sdhci->slots[0].capareg = deposit64(sdhci->slots[0].capareg, 0, 32, val); + sdhci->slots[0].capareg = deposit64(sdhci->slots[0].capareg, + 0, 32, val); break; case ASPEED_SDHCI_SDIO_144: - sdhci->slots[0].capareg = deposit64(sdhci->slots[0].capareg, 32, 32, val); + sdhci->slots[0].capareg = deposit64(sdhci->slots[0].capareg, + 32, 32, val); break; case ASPEED_SDHCI_SDIO_148: sdhci->slots[0].maxcurr = deposit64(sdhci->slots[0].maxcurr, -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Fix coding style issues from checkpatch.pl. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241204084453.610660-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast2600.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { return; } - aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_DEV_GPIO]); + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio), 0, + sc->memmap[ASPEED_DEV_GPIO]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, aspeed_soc_get_irq(s, ASPEED_DEV_GPIO)); -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Currently, it set the hardcode value of capability registers to all ASPEED SOCs However, the value of capability registers should be different for all ASPEED SOCs. For example: the bit 28 of the Capability Register 1 should be 1 for 64-bits System Bus support for AST2700. Introduce a new "capareg" class member whose data type is uint_64 to set the different Capability Registers to all ASPEED SOCs. The value of Capability Register is "0x0000000001e80080" for AST2400 and AST2500. The value of Capability Register is "0x0000000701f80080" for AST2600. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241204084453.610660-4-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/sd/aspeed_sdhci.h | 12 +++++++-- hw/arm/aspeed_ast2400.c | 3 ++- hw/arm/aspeed_ast2600.c | 7 +++--- hw/sd/aspeed_sdhci.c | 47 +++++++++++++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/sd/aspeed_sdhci.h +++ b/include/hw/sd/aspeed_sdhci.h @@ -XXX,XX +XXX,XX @@ #include "qom/object.h" #define TYPE_ASPEED_SDHCI "aspeed.sdhci" -OBJECT_DECLARE_SIMPLE_TYPE(AspeedSDHCIState, ASPEED_SDHCI) +#define TYPE_ASPEED_2400_SDHCI TYPE_ASPEED_SDHCI "-ast2400" +#define TYPE_ASPEED_2500_SDHCI TYPE_ASPEED_SDHCI "-ast2500" +#define TYPE_ASPEED_2600_SDHCI TYPE_ASPEED_SDHCI "-ast2600" +OBJECT_DECLARE_TYPE(AspeedSDHCIState, AspeedSDHCIClass, ASPEED_SDHCI) -#define ASPEED_SDHCI_CAPABILITIES 0x01E80080 #define ASPEED_SDHCI_NUM_SLOTS 2 #define ASPEED_SDHCI_NUM_REGS (ASPEED_SDHCI_REG_SIZE / sizeof(uint32_t)) #define ASPEED_SDHCI_REG_SIZE 0x100 @@ -XXX,XX +XXX,XX @@ struct AspeedSDHCIState { uint32_t regs[ASPEED_SDHCI_NUM_REGS]; }; +struct AspeedSDHCIClass { + SysBusDeviceClass parent_class; + + uint64_t capareg; +}; + #endif /* ASPEED_SDHCI_H */ diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -XXX,XX +XXX,XX @@ static void aspeed_ast2400_soc_init(Object *obj) snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); object_initialize_child(obj, "gpio", &s->gpio, typename); - object_initialize_child(obj, "sdc", &s->sdhci, TYPE_ASPEED_SDHCI); + snprintf(typename, sizeof(typename), "aspeed.sdhci-%s", socname); + object_initialize_child(obj, "sdc", &s->sdhci, typename); object_property_set_int(OBJECT(&s->sdhci), "num-slots", 2, &error_abort); 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 void aspeed_soc_ast2600_init(Object *obj) snprintf(typename, sizeof(typename), "aspeed.gpio-%s-1_8v", socname); object_initialize_child(obj, "gpio_1_8v", &s->gpio_1_8v, typename); - object_initialize_child(obj, "sd-controller", &s->sdhci, - TYPE_ASPEED_SDHCI); + snprintf(typename, sizeof(typename), "aspeed.sdhci-%s", socname); + object_initialize_child(obj, "sd-controller", &s->sdhci, typename); object_property_set_int(OBJECT(&s->sdhci), "num-slots", 2, &error_abort); @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj) &s->sdhci.slots[i], TYPE_SYSBUS_SDHCI); } - object_initialize_child(obj, "emmc-controller", &s->emmc, - TYPE_ASPEED_SDHCI); + object_initialize_child(obj, "emmc-controller", &s->emmc, typename); object_property_set_int(OBJECT(&s->emmc), "num-slots", 1, &error_abort); diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/sd/aspeed_sdhci.c +++ b/hw/sd/aspeed_sdhci.c @@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(dev); AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev); + AspeedSDHCIClass *asc = ASPEED_SDHCI_GET_CLASS(sdhci); /* Create input irqs for the slots */ qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq, @@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp) } if (!object_property_set_uint(sdhci_slot, "capareg", - ASPEED_SDHCI_CAPABILITIES, errp)) { + asc->capareg, errp)) { return; } @@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_class_init(ObjectClass *classp, void *data) device_class_set_props(dc, aspeed_sdhci_properties); } +static void aspeed_2400_sdhci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSDHCIClass *asc = ASPEED_SDHCI_CLASS(klass); + + dc->desc = "ASPEED 2400 SDHCI Controller"; + asc->capareg = 0x0000000001e80080; +} + +static void aspeed_2500_sdhci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSDHCIClass *asc = ASPEED_SDHCI_CLASS(klass); + + dc->desc = "ASPEED 2500 SDHCI Controller"; + asc->capareg = 0x0000000001e80080; +} + +static void aspeed_2600_sdhci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSDHCIClass *asc = ASPEED_SDHCI_CLASS(klass); + + dc->desc = "ASPEED 2600 SDHCI Controller"; + asc->capareg = 0x0000000701f80080; +} + static const TypeInfo aspeed_sdhci_types[] = { { .name = TYPE_ASPEED_SDHCI, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AspeedSDHCIState), .class_init = aspeed_sdhci_class_init, + .class_size = sizeof(AspeedSDHCIClass), + .abstract = true, + }, + { + .name = TYPE_ASPEED_2400_SDHCI, + .parent = TYPE_ASPEED_SDHCI, + .class_init = aspeed_2400_sdhci_class_init, + }, + { + .name = TYPE_ASPEED_2500_SDHCI, + .parent = TYPE_ASPEED_SDHCI, + .class_init = aspeed_2500_sdhci_class_init, + }, + { + .name = TYPE_ASPEED_2600_SDHCI, + .parent = TYPE_ASPEED_SDHCI, + .class_init = aspeed_2600_sdhci_class_init, }, }; -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Introduce a new ast2700 class to support AST2700. Add a new ast2700 SDHCI class init function and set the value of capability register to "0x0000000719f80080". Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241204084453.610660-5-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- include/hw/sd/aspeed_sdhci.h | 1 + hw/sd/aspeed_sdhci.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/sd/aspeed_sdhci.h +++ b/include/hw/sd/aspeed_sdhci.h @@ -XXX,XX +XXX,XX @@ #define TYPE_ASPEED_2400_SDHCI TYPE_ASPEED_SDHCI "-ast2400" #define TYPE_ASPEED_2500_SDHCI TYPE_ASPEED_SDHCI "-ast2500" #define TYPE_ASPEED_2600_SDHCI TYPE_ASPEED_SDHCI "-ast2600" +#define TYPE_ASPEED_2700_SDHCI TYPE_ASPEED_SDHCI "-ast2700" OBJECT_DECLARE_TYPE(AspeedSDHCIState, AspeedSDHCIClass, ASPEED_SDHCI) #define ASPEED_SDHCI_NUM_SLOTS 2 diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/sd/aspeed_sdhci.c +++ b/hw/sd/aspeed_sdhci.c @@ -XXX,XX +XXX,XX @@ static void aspeed_2600_sdhci_class_init(ObjectClass *klass, void *data) asc->capareg = 0x0000000701f80080; } +static void aspeed_2700_sdhci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSDHCIClass *asc = ASPEED_SDHCI_CLASS(klass); + + dc->desc = "ASPEED 2700 SDHCI Controller"; + asc->capareg = 0x0000000719f80080; +} + static const TypeInfo aspeed_sdhci_types[] = { { .name = TYPE_ASPEED_SDHCI, @@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_sdhci_types[] = { .parent = TYPE_ASPEED_SDHCI, .class_init = aspeed_2600_sdhci_class_init, }, + { + .name = TYPE_ASPEED_2700_SDHCI, + .parent = TYPE_ASPEED_SDHCI, + .class_init = aspeed_2700_sdhci_class_init, + }, }; DEFINE_TYPES(aspeed_sdhci_types) -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add SDHCI model for AST2700 SDHCI support. The SDHCI controller only support 1 slot and registers base address is start at 0x1408_0000 and its interrupt is connected to GICINT133_INTC at bit 1. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241204084453.610660-6-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast27x0.c | 20 ++++++++++++++++++++ 1 file changed, 20 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 hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_I2C] = 0x14C0F000, [ASPEED_DEV_GPIO] = 0x14C0B000, [ASPEED_DEV_RTC] = 0x12C0F000, + [ASPEED_DEV_SDHCI] = 0x14080000, }; #define AST2700_MAX_IRQ 256 @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2700_irqmap[] = { [ASPEED_DEV_KCS] = 128, [ASPEED_DEV_DP] = 28, [ASPEED_DEV_I3C] = 131, + [ASPEED_DEV_SDHCI] = 133, }; /* GICINT 128 */ @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2700_gic132_intcmap[] = { /* GICINT 133 */ static const int aspeed_soc_ast2700_gic133_intcmap[] = { + [ASPEED_DEV_SDHCI] = 1, [ASPEED_DEV_PECI] = 4, }; @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_init(Object *obj) object_initialize_child(obj, "gpio", &s->gpio, typename); object_initialize_child(obj, "rtc", &s->rtc, TYPE_ASPEED_RTC); + + snprintf(typename, sizeof(typename), "aspeed.sdhci-%s", socname); + object_initialize_child(obj, "sd-controller", &s->sdhci, typename); + object_property_set_int(OBJECT(&s->sdhci), "num-slots", 1, &error_abort); + + /* Init sd card slot class here so that they're under the correct parent */ + object_initialize_child(obj, "sd-controller.sdhci", + &s->sdhci.slots[0], TYPE_SYSBUS_SDHCI); } /* @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_RTC)); + /* SDHCI */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) { + return; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdhci), 0, + sc->memmap[ASPEED_DEV_SDHCI]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI)); + create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000); create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000); create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000); -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add SDHCI model for AST2700 eMMC support. The eMMC controller only support 1 slot and registers base address is start at 0x1209_0000 and its interrupt is connected to GICINT 15. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241204084453.610660-7-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- hw/arm/aspeed_ast27x0.c | 15 +++++++++++++++ 1 file changed, 15 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 void aspeed_soc_ast2700_init(Object *obj) /* Init sd card slot class here so that they're under the correct parent */ object_initialize_child(obj, "sd-controller.sdhci", &s->sdhci.slots[0], TYPE_SYSBUS_SDHCI); + + object_initialize_child(obj, "emmc-controller", &s->emmc, typename); + object_property_set_int(OBJECT(&s->emmc), "num-slots", 1, &error_abort); + + object_initialize_child(obj, "emmc-controller.sdhci", &s->emmc.slots[0], + TYPE_SYSBUS_SDHCI); } /* @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI)); + /* eMMC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->emmc), errp)) { + return; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->emmc), 0, + sc->memmap[ASPEED_DEV_EMMC]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_EMMC)); + create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000); create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000); create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000); -- 2.47.1
This simply moves the ast1030 tests to a new test file. No changes. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-2-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/meson.build | 1 + tests/functional/test_arm_aspeed.py | 64 ---------------- tests/functional/test_arm_aspeed_ast1030.py | 81 +++++++++++++++++++++ 3 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 tests/functional/test_arm_aspeed_ast1030.py 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 @@ tests_alpha_system_thorough = [ tests_arm_system_thorough = [ 'arm_aspeed', + 'arm_aspeed_ast1030', 'arm_bpim2u', 'arm_canona1100', 'arm_collie', diff --git a/tests/functional/test_arm_aspeed.py b/tests/functional/test_arm_aspeed.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/test_arm_aspeed.py +++ b/tests/functional/test_arm_aspeed.py @@ -XXX,XX +XXX,XX @@ from zipfile import ZipFile from unittest import skipUnless -class AST1030Machine(LinuxKernelTest): - - ASSET_ZEPHYR_1_04 = Asset( - ('https://github.com/AspeedTech-BMC' - '/zephyr/releases/download/v00.01.04/ast1030-evb-demo.zip'), - '4ac6210adcbc61294927918707c6762483fd844dde5e07f3ba834ad1f91434d3') - - def test_ast1030_zephyros_1_04(self): - self.set_machine('ast1030-evb') - - zip_file = self.ASSET_ZEPHYR_1_04.fetch() - - kernel_name = "ast1030-evb-demo/zephyr.elf" - with ZipFile(zip_file, 'r') as zf: - zf.extract(kernel_name, path=self.workdir) - kernel_file = os.path.join(self.workdir, kernel_name) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_file, '-nographic') - self.vm.launch() - self.wait_for_console_pattern("Booting Zephyr OS") - exec_command_and_wait_for_pattern(self, "help", - "Available commands") - - ASSET_ZEPHYR_1_07 = Asset( - ('https://github.com/AspeedTech-BMC' - '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip'), - 'ad52e27959746988afaed8429bf4e12ab988c05c4d07c9d90e13ec6f7be4574c') - - def test_ast1030_zephyros_1_07(self): - self.set_machine('ast1030-evb') - - zip_file = self.ASSET_ZEPHYR_1_07.fetch() - - kernel_name = "ast1030-evb-demo/zephyr.bin" - with ZipFile(zip_file, 'r') as zf: - zf.extract(kernel_name, path=self.workdir) - kernel_file = os.path.join(self.workdir, kernel_name) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_file, '-nographic') - self.vm.launch() - self.wait_for_console_pattern("Booting Zephyr OS") - for shell_cmd in [ - 'kernel stacks', - 'otp info conf', - 'otp info scu', - 'hwinfo devid', - 'crypto aes256_cbc_vault', - 'random get', - 'jtag JTAG1 sw_xfer high TMS', - 'adc ADC0 resolution 12', - 'adc ADC0 read 42', - 'adc ADC1 read 69', - 'i2c scan I2C_0', - 'i3c attach I3C_0', - 'hash test', - 'kernel uptime', - 'kernel reboot warm', - 'kernel uptime', - 'kernel reboot cold', - 'kernel uptime', - ]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$") - class AST2x00Machine(LinuxKernelTest): def do_test_arm_aspeed(self, machine, image): diff --git a/tests/functional/test_arm_aspeed_ast1030.py b/tests/functional/test_arm_aspeed_ast1030.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_ast1030.py @@ -XXX,XX +XXX,XX @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED SoCs with firmware +# +# Copyright (C) 2022 ASPEED Technology Inc +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern +from zipfile import ZipFile + +class AST1030Machine(LinuxKernelTest): + + ASSET_ZEPHYR_1_04 = Asset( + ('https://github.com/AspeedTech-BMC' + '/zephyr/releases/download/v00.01.04/ast1030-evb-demo.zip'), + '4ac6210adcbc61294927918707c6762483fd844dde5e07f3ba834ad1f91434d3') + + def test_ast1030_zephyros_1_04(self): + self.set_machine('ast1030-evb') + + zip_file = self.ASSET_ZEPHYR_1_04.fetch() + + kernel_name = "ast1030-evb-demo/zephyr.elf" + with ZipFile(zip_file, 'r') as zf: + zf.extract(kernel_name, path=self.workdir) + kernel_file = os.path.join(self.workdir, kernel_name) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_file, '-nographic') + self.vm.launch() + self.wait_for_console_pattern("Booting Zephyr OS") + exec_command_and_wait_for_pattern(self, "help", + "Available commands") + + ASSET_ZEPHYR_1_07 = Asset( + ('https://github.com/AspeedTech-BMC' + '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip'), + 'ad52e27959746988afaed8429bf4e12ab988c05c4d07c9d90e13ec6f7be4574c') + + def test_ast1030_zephyros_1_07(self): + self.set_machine('ast1030-evb') + + zip_file = self.ASSET_ZEPHYR_1_07.fetch() + + kernel_name = "ast1030-evb-demo/zephyr.bin" + with ZipFile(zip_file, 'r') as zf: + zf.extract(kernel_name, path=self.workdir) + kernel_file = os.path.join(self.workdir, kernel_name) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_file, '-nographic') + self.vm.launch() + self.wait_for_console_pattern("Booting Zephyr OS") + for shell_cmd in [ + 'kernel stacks', + 'otp info conf', + 'otp info scu', + 'hwinfo devid', + 'crypto aes256_cbc_vault', + 'random get', + 'jtag JTAG1 sw_xfer high TMS', + 'adc ADC0 resolution 12', + 'adc ADC0 read 42', + 'adc ADC1 read 69', + 'i2c scan I2C_0', + 'i3c attach I3C_0', + 'hash test', + 'kernel uptime', + 'kernel reboot warm', + 'kernel uptime', + 'kernel reboot cold', + 'kernel uptime', + ]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$") + + +if __name__ == '__main__': + LinuxKernelTest.main() -- 2.47.1
This introduces a new aspeed module for sharing code between tests and moves the palmetto test to a new test file. No changes in the test. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-3-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/aspeed.py | 23 +++++++++++++++++++ tests/functional/meson.build | 2 ++ tests/functional/test_arm_aspeed.py | 10 -------- tests/functional/test_arm_aspeed_palmetto.py | 24 ++++++++++++++++++++ 4 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 tests/functional/aspeed.py create mode 100644 tests/functional/test_arm_aspeed_palmetto.py diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/aspeed.py @@ -XXX,XX +XXX,XX @@ +# Test class to boot aspeed machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest + +class AspeedTest(LinuxKernelTest): + + def do_test_arm_aspeed(self, machine, image): + self.set_machine(machine) + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic', '-snapshot') + self.vm.launch() + + self.wait_for_console_pattern("U-Boot 2016.07") + self.wait_for_console_pattern("## Loading kernel from FIT Image at 20080000") + self.wait_for_console_pattern("Starting kernel ...") + self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") + self.wait_for_console_pattern( + "aspeed-smc 1e620000.spi: read control register: 203b0641") + self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") + self.wait_for_console_pattern("systemd[1]: Set hostname to") 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 = { 'aarch64_tuxrun' : 240, 'aarch64_virt' : 720, 'acpi_bits' : 420, + 'arm_aspeed_palmetto' : 120, 'arm_aspeed' : 600, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -XXX,XX +XXX,XX @@ tests_alpha_system_thorough = [ tests_arm_system_thorough = [ 'arm_aspeed', 'arm_aspeed_ast1030', + 'arm_aspeed_palmetto', 'arm_bpim2u', 'arm_canona1100', 'arm_collie', diff --git a/tests/functional/test_arm_aspeed.py b/tests/functional/test_arm_aspeed.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/test_arm_aspeed.py +++ b/tests/functional/test_arm_aspeed.py @@ -XXX,XX +XXX,XX @@ def do_test_arm_aspeed(self, machine, image): self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") self.wait_for_console_pattern("systemd[1]: Set hostname to") - ASSET_PALMETTO_FLASH = Asset( - ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' - 'obmc-phosphor-image-palmetto.static.mtd'), - '3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d'); - - def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): - image_path = self.ASSET_PALMETTO_FLASH.fetch() - - self.do_test_arm_aspeed('palmetto-bmc', image_path) - ASSET_ROMULUS_FLASH = Asset( ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' 'obmc-phosphor-image-romulus.static.mtd'), diff --git a/tests/functional/test_arm_aspeed_palmetto.py b/tests/functional/test_arm_aspeed_palmetto.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_palmetto.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 PalmettoMachine(AspeedTest): + + ASSET_PALMETTO_FLASH = Asset( + ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-palmetto.static.mtd'), + '3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d'); + + def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): + image_path = self.ASSET_PALMETTO_FLASH.fetch() + + self.do_test_arm_aspeed('palmetto-bmc', image_path) + + +if __name__ == '__main__': + AspeedTest.main() -- 2.47.1
This simply moves the romulus-bmc test to a new test file. No changes in the test. The do_test_arm_aspeed routine is removed from the test_arm_aspeed.py file because it is now unused. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-4-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/meson.build | 2 ++ tests/functional/test_arm_aspeed.py | 26 --------------------- tests/functional/test_arm_aspeed_romulus.py | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 tests/functional/test_arm_aspeed_romulus.py 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 = { 'aarch64_virt' : 720, 'acpi_bits' : 420, 'arm_aspeed_palmetto' : 120, + 'arm_aspeed_romulus' : 120, 'arm_aspeed' : 600, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -XXX,XX +XXX,XX @@ tests_arm_system_thorough = [ 'arm_aspeed', 'arm_aspeed_ast1030', 'arm_aspeed_palmetto', + 'arm_aspeed_romulus', 'arm_bpim2u', 'arm_canona1100', 'arm_collie', diff --git a/tests/functional/test_arm_aspeed.py b/tests/functional/test_arm_aspeed.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/test_arm_aspeed.py +++ b/tests/functional/test_arm_aspeed.py @@ -XXX,XX +XXX,XX @@ class AST2x00Machine(LinuxKernelTest): - def do_test_arm_aspeed(self, machine, image): - self.set_machine(machine) - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', - '-net', 'nic', '-snapshot') - self.vm.launch() - - self.wait_for_console_pattern("U-Boot 2016.07") - self.wait_for_console_pattern("## Loading kernel from FIT Image at 20080000") - self.wait_for_console_pattern("Starting kernel ...") - self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") - self.wait_for_console_pattern( - "aspeed-smc 1e620000.spi: read control register: 203b0641") - self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") - self.wait_for_console_pattern("systemd[1]: Set hostname to") - - ASSET_ROMULUS_FLASH = Asset( - ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' - 'obmc-phosphor-image-romulus.static.mtd'), - '820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') - - def test_arm_ast2500_romulus_openbmc_v2_9_0(self): - image_path = self.ASSET_ROMULUS_FLASH.fetch() - - self.do_test_arm_aspeed('romulus-bmc', image_path) - def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB'): self.require_netdev('user') self.vm.set_console() diff --git a/tests/functional/test_arm_aspeed_romulus.py b/tests/functional/test_arm_aspeed_romulus.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_romulus.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 RomulusMachine(AspeedTest): + + ASSET_ROMULUS_FLASH = Asset( + ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-romulus.static.mtd'), + '820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') + + def test_arm_ast2500_romulus_openbmc_v2_9_0(self): + image_path = self.ASSET_ROMULUS_FLASH.fetch() + + self.do_test_arm_aspeed('romulus-bmc', image_path) + + +if __name__ == '__main__': + AspeedTest.main() -- 2.47.1
This moves the ast2500-evb tests to a new test file and extends the aspeed module with routines used to run the buildroot and sdk tests. No changes in the test. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-5-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/aspeed.py | 33 ++++++++++++ tests/functional/meson.build | 2 + tests/functional/test_arm_aspeed.py | 44 --------------- tests/functional/test_arm_aspeed_ast2500.py | 59 +++++++++++++++++++++ 4 files changed, 94 insertions(+), 44 deletions(-) create mode 100644 tests/functional/test_arm_aspeed_ast2500.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 @@ # # SPDX-License-Identifier: GPL-2.0-or-later +from qemu_test import exec_command_and_wait_for_pattern from qemu_test import LinuxKernelTest class AspeedTest(LinuxKernelTest): @@ -XXX,XX +XXX,XX @@ def do_test_arm_aspeed(self, machine, image): "aspeed-smc 1e620000.spi: read control register: 203b0641") self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") self.wait_for_console_pattern("systemd[1]: Set hostname to") + + def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB'): + self.require_netdev('user') + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw,read-only=true', + '-net', 'nic', '-net', 'user') + self.vm.launch() + + self.wait_for_console_pattern('U-Boot 2019.04') + self.wait_for_console_pattern('## Loading kernel from FIT Image') + self.wait_for_console_pattern('Starting kernel ...') + self.wait_for_console_pattern('Booting Linux on physical CPU ' + cpu_id) + self.wait_for_console_pattern('lease of 10.0.2.15') + # the line before login: + self.wait_for_console_pattern(pattern) + exec_command_and_wait_for_pattern(self, 'root', 'Password:') + exec_command_and_wait_for_pattern(self, 'passw0rd', '#') + + def do_test_arm_aspeed_buildroot_poweroff(self): + exec_command_and_wait_for_pattern(self, 'poweroff', + 'reboot: System halted'); + + def do_test_arm_aspeed_sdk_start(self, image): + self.require_netdev('user') + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic', '-net', 'user', '-snapshot') + self.vm.launch() + + self.wait_for_console_pattern('U-Boot 2019.04') + self.wait_for_console_pattern('## Loading kernel from FIT Image') + self.wait_for_console_pattern('Starting kernel ...') 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 = { 'acpi_bits' : 420, 'arm_aspeed_palmetto' : 120, 'arm_aspeed_romulus' : 120, + 'arm_aspeed_ast2500' : 480, 'arm_aspeed' : 600, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -XXX,XX +XXX,XX @@ tests_arm_system_thorough = [ 'arm_aspeed_ast1030', 'arm_aspeed_palmetto', 'arm_aspeed_romulus', + 'arm_aspeed_ast2500', 'arm_bpim2u', 'arm_canona1100', 'arm_collie', diff --git a/tests/functional/test_arm_aspeed.py b/tests/functional/test_arm_aspeed.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/test_arm_aspeed.py +++ b/tests/functional/test_arm_aspeed.py @@ -XXX,XX +XXX,XX @@ def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB' def do_test_arm_aspeed_buildroot_poweroff(self): exec_command_and_wait_for_pattern(self, 'poweroff', 'reboot: System halted'); - - ASSET_BR2_202311_AST2500_FLASH = Asset( - ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2500-evb/buildroot-2023.11/flash.img'), - 'c23db6160cf77d0258397eb2051162c8473a56c441417c52a91ba217186e715f') - - def test_arm_ast2500_evb_buildroot(self): - self.set_machine('ast2500-evb') - - image_path = self.ASSET_BR2_202311_AST2500_FLASH.fetch() - - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); - self.do_test_arm_aspeed_buildroot_start(image_path, '0x0', - 'ast2500-evb login:') - - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', - 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d'); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') - - self.do_test_arm_aspeed_buildroot_poweroff() - ASSET_BR2_202311_AST2600_FLASH = Asset( ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' 'images/ast2600-evb/buildroot-2023.11/flash.img'), @@ -XXX,XX +XXX,XX @@ def do_test_arm_aspeed_sdk_start(self, image): self.wait_for_console_pattern('## Loading kernel from FIT Image') self.wait_for_console_pattern('Starting kernel ...') - ASSET_SDK_V806_AST2500 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2500-default-obmc.tar.gz', - 'e1755f3cadff69190438c688d52dd0f0d399b70a1e14b1d3d5540fc4851d38ca') - - def test_arm_ast2500_evb_sdk(self): - self.set_machine('ast2500-evb') - - image_path = self.ASSET_SDK_V806_AST2500.fetch() - - archive_extract(image_path, self.workdir) - - self.do_test_arm_aspeed_sdk_start( - self.workdir + '/ast2500-default/image-bmc') - - self.wait_for_console_pattern('ast2500-default login:') - ASSET_SDK_V806_AST2600_A2 = Asset( 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2600-a2-obmc.tar.gz', '9083506135f622d5e7351fcf7d4e1c7125cee5ba16141220c0ba88931f3681a4') diff --git a/tests/functional/test_arm_aspeed_ast2500.py b/tests/functional/test_arm_aspeed_ast2500.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_ast2500.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 +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test.utils import archive_extract + +class AST2500Machine(AspeedTest): + + ASSET_BR2_202311_AST2500_FLASH = Asset( + ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' + 'images/ast2500-evb/buildroot-2023.11/flash.img'), + 'c23db6160cf77d0258397eb2051162c8473a56c441417c52a91ba217186e715f') + + def test_arm_ast2500_evb_buildroot(self): + self.set_machine('ast2500-evb') + + image_path = self.ASSET_BR2_202311_AST2500_FLASH.fetch() + + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); + self.do_test_arm_aspeed_buildroot_start(image_path, '0x0', + 'ast2500-evb login:') + + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', + 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d'); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') + + self.do_test_arm_aspeed_buildroot_poweroff() + + ASSET_SDK_V806_AST2500 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2500-default-obmc.tar.gz', + 'e1755f3cadff69190438c688d52dd0f0d399b70a1e14b1d3d5540fc4851d38ca') + + def test_arm_ast2500_evb_sdk(self): + self.set_machine('ast2500-evb') + + image_path = self.ASSET_SDK_V806_AST2500.fetch() + + archive_extract(image_path, self.workdir) + + self.do_test_arm_aspeed_sdk_start( + self.workdir + '/ast2500-default/image-bmc') + + self.wait_for_console_pattern('ast2500-default login:') + + +if __name__ == '__main__': + AspeedTest.main() -- 2.47.1
This moves the ast2600-evb tests to a new test file. No changes in the test. The routines used to run the buildroot and sdk tests are removed from the test_arm_aspeed.py file because now unused. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-6-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/meson.build | 2 + tests/functional/test_arm_aspeed.py | 155 -------------------- tests/functional/test_arm_aspeed_ast2600.py | 143 ++++++++++++++++++ 3 files changed, 145 insertions(+), 155 deletions(-) create mode 100644 tests/functional/test_arm_aspeed_ast2600.py 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_palmetto' : 120, 'arm_aspeed_romulus' : 120, 'arm_aspeed_ast2500' : 480, + 'arm_aspeed_ast2600' : 720, 'arm_aspeed' : 600, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -XXX,XX +XXX,XX @@ tests_arm_system_thorough = [ 'arm_aspeed_palmetto', 'arm_aspeed_romulus', 'arm_aspeed_ast2500', + 'arm_aspeed_ast2600', 'arm_bpim2u', 'arm_canona1100', 'arm_collie', diff --git a/tests/functional/test_arm_aspeed.py b/tests/functional/test_arm_aspeed.py index XXXXXXX..XXXXXXX 100755 --- a/tests/functional/test_arm_aspeed.py +++ b/tests/functional/test_arm_aspeed.py @@ -XXX,XX +XXX,XX @@ from zipfile import ZipFile from unittest import skipUnless -class AST2x00Machine(LinuxKernelTest): - - def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB'): - self.require_netdev('user') - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw,read-only=true', - '-net', 'nic', '-net', 'user') - self.vm.launch() - - self.wait_for_console_pattern('U-Boot 2019.04') - self.wait_for_console_pattern('## Loading kernel from FIT Image') - self.wait_for_console_pattern('Starting kernel ...') - self.wait_for_console_pattern('Booting Linux on physical CPU ' + cpu_id) - self.wait_for_console_pattern('lease of 10.0.2.15') - # the line before login: - self.wait_for_console_pattern(pattern) - exec_command_and_wait_for_pattern(self, 'root', 'Password:') - exec_command_and_wait_for_pattern(self, 'passw0rd', '#') - - def do_test_arm_aspeed_buildroot_poweroff(self): - exec_command_and_wait_for_pattern(self, 'poweroff', - 'reboot: System halted'); - ASSET_BR2_202311_AST2600_FLASH = Asset( - ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2023.11/flash.img'), - 'b62808daef48b438d0728ee07662290490ecfa65987bb91294cafb1bb7ad1a68') - - def test_arm_ast2600_evb_buildroot(self): - self.set_machine('ast2600-evb') - - image_path = self.ASSET_BR2_202311_AST2600_FLASH.fetch() - - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); - self.vm.add_args('-device', - 'ds1338,bus=aspeed.i2c.bus.3,address=0x32'); - self.vm.add_args('-device', - 'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42'); - self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', - 'ast2600-evb login:') - - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', - 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d'); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') - - exec_command_and_wait_for_pattern(self, - 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device', - 'i2c i2c-3: new_device: Instantiated device ds1307 at 0x32'); - year = time.strftime("%Y") - exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year); - - exec_command_and_wait_for_pattern(self, - 'echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-3/new_device', - 'i2c i2c-3: new_device: Instantiated device slave-24c02 at 0x64'); - exec_command_and_wait_for_pattern(self, - 'i2cset -y 3 0x42 0x64 0x00 0xaa i', '#'); - exec_command_and_wait_for_pattern(self, - 'hexdump /sys/bus/i2c/devices/3-1064/slave-eeprom', - '0000000 ffaa ffff ffff ffff ffff ffff ffff ffff'); - self.do_test_arm_aspeed_buildroot_poweroff() - - ASSET_BR2_202302_AST2600_TPM_FLASH = Asset( - ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2023.02-tpm/flash.img'), - 'a46009ae8a5403a0826d607215e731a8c68d27c14c41e55331706b8f9c7bd997') - - @skipUnless(*has_cmd('swtpm')) - def test_arm_ast2600_evb_buildroot_tpm(self): - self.set_machine('ast2600-evb') - - image_path = self.ASSET_BR2_202302_AST2600_TPM_FLASH.fetch() - - tpmstate_dir = tempfile.TemporaryDirectory(prefix="qemu_") - socket = os.path.join(tpmstate_dir.name, 'swtpm-socket') - - # We must put the TPM state dir in /tmp/, not the build dir, - # because some distros use AppArmor to lock down swtpm and - # restrict the set of locations it can access files in. - subprocess.run(['swtpm', 'socket', '-d', '--tpm2', - '--tpmstate', f'dir={tpmstate_dir.name}', - '--ctrl', f'type=unixio,path={socket}']) - - self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}') - self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm') - self.vm.add_args('-device', - 'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e') - self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB') - - exec_command_and_wait_for_pattern(self, - 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device', - 'tpm_tis_i2c 12-002e: 2.0 TPM (device-id 0x1, rev-id 1)'); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/tpm/tpm0/pcr-sha256/0', - 'B804724EA13F52A9072BA87FE8FDCC497DFC9DF9AA15B9088694639C431688E0'); - - self.do_test_arm_aspeed_buildroot_poweroff() - - def do_test_arm_aspeed_sdk_start(self, image): - self.require_netdev('user') - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', - '-net', 'nic', '-net', 'user', '-snapshot') - self.vm.launch() - - self.wait_for_console_pattern('U-Boot 2019.04') - self.wait_for_console_pattern('## Loading kernel from FIT Image') - self.wait_for_console_pattern('Starting kernel ...') - - ASSET_SDK_V806_AST2600_A2 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2600-a2-obmc.tar.gz', - '9083506135f622d5e7351fcf7d4e1c7125cee5ba16141220c0ba88931f3681a4') - - def test_arm_ast2600_evb_sdk(self): - self.set_machine('ast2600-evb') - - image_path = self.ASSET_SDK_V806_AST2600_A2.fetch() - - archive_extract(image_path, self.workdir) - - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test'); - self.vm.add_args('-device', - 'ds1338,bus=aspeed.i2c.bus.5,address=0x32'); - self.do_test_arm_aspeed_sdk_start( - self.workdir + '/ast2600-a2/image-bmc') - - self.wait_for_console_pattern('ast2600-a2 login:') - - exec_command_and_wait_for_pattern(self, 'root', 'Password:') - exec_command_and_wait_for_pattern(self, '0penBmc', 'root@ast2600-a2:~#') - - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device', - 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d'); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon19/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000); - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000') - - exec_command_and_wait_for_pattern(self, - 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device', - 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32'); - year = time.strftime("%Y") - exec_command_and_wait_for_pattern(self, - '/sbin/hwclock -f /dev/rtc1', year); - - class AST2x00MachineMMC(LinuxKernelTest): ASSET_RAINIER_EMMC = Asset( diff --git a/tests/functional/test_arm_aspeed_ast2600.py b/tests/functional/test_arm_aspeed_ast2600.py new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/functional/test_arm_aspeed_ast2600.py @@ -XXX,XX +XXX,XX @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import time +import tempfile +import subprocess + +from qemu_test import Asset +from aspeed import AspeedTest +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import has_cmd +from qemu_test.utils import archive_extract +from unittest import skipUnless + +class AST2600Machine(AspeedTest): + + ASSET_BR2_202311_AST2600_FLASH = Asset( + ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' + 'images/ast2600-evb/buildroot-2023.11/flash.img'), + 'b62808daef48b438d0728ee07662290490ecfa65987bb91294cafb1bb7ad1a68') + + def test_arm_ast2600_evb_buildroot(self): + self.set_machine('ast2600-evb') + + image_path = self.ASSET_BR2_202311_AST2600_FLASH.fetch() + + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); + self.vm.add_args('-device', + 'ds1338,bus=aspeed.i2c.bus.3,address=0x32'); + self.vm.add_args('-device', + 'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42'); + self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', + 'ast2600-evb login:') + + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', + 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d'); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') + + exec_command_and_wait_for_pattern(self, + 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device', + 'i2c i2c-3: new_device: Instantiated device ds1307 at 0x32'); + year = time.strftime("%Y") + exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year); + + exec_command_and_wait_for_pattern(self, + 'echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-3/new_device', + 'i2c i2c-3: new_device: Instantiated device slave-24c02 at 0x64'); + exec_command_and_wait_for_pattern(self, + 'i2cset -y 3 0x42 0x64 0x00 0xaa i', '#'); + exec_command_and_wait_for_pattern(self, + 'hexdump /sys/bus/i2c/devices/3-1064/slave-eeprom', + '0000000 ffaa ffff ffff ffff ffff ffff ffff ffff'); + self.do_test_arm_aspeed_buildroot_poweroff() + + ASSET_BR2_202302_AST2600_TPM_FLASH = Asset( + ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' + 'images/ast2600-evb/buildroot-2023.02-tpm/flash.img'), + 'a46009ae8a5403a0826d607215e731a8c68d27c14c41e55331706b8f9c7bd997') + + @skipUnless(*has_cmd('swtpm')) + def test_arm_ast2600_evb_buildroot_tpm(self): + self.set_machine('ast2600-evb') + + image_path = self.ASSET_BR2_202302_AST2600_TPM_FLASH.fetch() + + tpmstate_dir = tempfile.TemporaryDirectory(prefix="qemu_") + socket = os.path.join(tpmstate_dir.name, 'swtpm-socket') + + # We must put the TPM state dir in /tmp/, not the build dir, + # because some distros use AppArmor to lock down swtpm and + # restrict the set of locations it can access files in. + subprocess.run(['swtpm', 'socket', '-d', '--tpm2', + '--tpmstate', f'dir={tpmstate_dir.name}', + '--ctrl', f'type=unixio,path={socket}']) + + self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}') + self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm') + self.vm.add_args('-device', + 'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e') + self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB') + + exec_command_and_wait_for_pattern(self, + 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device', + 'tpm_tis_i2c 12-002e: 2.0 TPM (device-id 0x1, rev-id 1)'); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/tpm/tpm0/pcr-sha256/0', + 'B804724EA13F52A9072BA87FE8FDCC497DFC9DF9AA15B9088694639C431688E0'); + + self.do_test_arm_aspeed_buildroot_poweroff() + + ASSET_SDK_V806_AST2600_A2 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2600-a2-obmc.tar.gz', + '9083506135f622d5e7351fcf7d4e1c7125cee5ba16141220c0ba88931f3681a4') + + def test_arm_ast2600_evb_sdk(self): + self.set_machine('ast2600-evb') + + image_path = self.ASSET_SDK_V806_AST2600_A2.fetch() + + archive_extract(image_path, self.workdir) + + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test'); + self.vm.add_args('-device', + 'ds1338,bus=aspeed.i2c.bus.5,address=0x32'); + self.do_test_arm_aspeed_sdk_start( + self.workdir + '/ast2600-a2/image-bmc') + + self.wait_for_console_pattern('ast2600-a2 login:') + + exec_command_and_wait_for_pattern(self, 'root', 'Password:') + exec_command_and_wait_for_pattern(self, '0penBmc', 'root@ast2600-a2:~#') + + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device', + 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d'); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon19/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000); + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000') + + exec_command_and_wait_for_pattern(self, + 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device', + 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32'); + year = time.strftime("%Y") + exec_command_and_wait_for_pattern(self, + '/sbin/hwclock -f /dev/rtc1', year); + +if __name__ == '__main__': + AspeedTest.main() -- 2.47.1
This simply moves the rainier-bmc test to a new test file. No changes in the test. The test_arm_aspeed.py is deleted. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-7-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/functional/meson.build | 4 ++-- ...m_aspeed.py => test_arm_aspeed_rainier.py} | 22 +++++-------------- 2 files changed, 7 insertions(+), 19 deletions(-) rename tests/functional/{test_arm_aspeed.py => test_arm_aspeed_rainier.py} (71%) mode change 100755 => 100644 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_romulus' : 120, 'arm_aspeed_ast2500' : 480, 'arm_aspeed_ast2600' : 720, - 'arm_aspeed' : 600, + 'arm_aspeed_rainier' : 240, 'arm_bpim2u' : 500, 'arm_collie' : 180, 'arm_orangepi' : 540, @@ -XXX,XX +XXX,XX @@ tests_alpha_system_thorough = [ ] tests_arm_system_thorough = [ - 'arm_aspeed', 'arm_aspeed_ast1030', 'arm_aspeed_palmetto', 'arm_aspeed_romulus', 'arm_aspeed_ast2500', 'arm_aspeed_ast2600', + 'arm_aspeed_rainier', 'arm_bpim2u', 'arm_canona1100', 'arm_collie', diff --git a/tests/functional/test_arm_aspeed.py b/tests/functional/test_arm_aspeed_rainier.py old mode 100755 new mode 100644 similarity index 71% rename from tests/functional/test_arm_aspeed.py rename to tests/functional/test_arm_aspeed_rainier.py index XXXXXXX..XXXXXXX --- a/tests/functional/test_arm_aspeed.py +++ b/tests/functional/test_arm_aspeed_rainier.py @@ -XXX,XX +XXX,XX @@ #!/usr/bin/env python3 # -# Functional test that boots the ASPEED SoCs with firmware -# -# Copyright (C) 2022 ASPEED Technology Inc +# Functional test that boots the ASPEED machines # # SPDX-License-Identifier: GPL-2.0-or-later -import os -import time -import subprocess -import tempfile - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import interrupt_interactive_console_until_pattern -from qemu_test import has_cmd -from qemu_test.utils import archive_extract -from zipfile import ZipFile -from unittest import skipUnless +from qemu_test import Asset +from aspeed import AspeedTest -class AST2x00MachineMMC(LinuxKernelTest): +class RainierMachine(AspeedTest): ASSET_RAINIER_EMMC = Asset( ('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/' @@ -XXX,XX +XXX,XX @@ def test_arm_aspeed_emmc_boot(self): self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise') if __name__ == '__main__': - LinuxKernelTest.main() + AspeedTest.main() -- 2.47.1
This simply moves the debian boot test from the avocado testsuite to the new functional testsuite. No changes in the test. Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/r/20241206131132.520911-8-clg@redhat.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/avocado/boot_linux_console.py | 26 --------------------- tests/functional/test_arm_aspeed_rainier.py | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index XXXXXXX..XXXXXXX 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -XXX,XX +XXX,XX @@ def test_arm_quanta_gsj_initrd(self): self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') self.wait_for_console_pattern( 'Give root password for system maintenance') - - def test_arm_ast2600_debian(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:rainier-bmc - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20220606T211338Z/' - 'pool/main/l/linux/' - 'linux-image-5.17.0-2-armmp_5.17.6-1%2Bb1_armhf.deb') - deb_hash = '8acb2b4439faedc2f3ed4bdb2847ad4f6e0491f73debaeb7f660c8abe4dcdc0e' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash, - algorithm='sha256') - kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.17.0-2-armmp') - dtb_path = self.extract_from_deb(deb_path, - '/usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb') - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-net', 'nic') - self.vm.launch() - self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") - self.wait_for_console_pattern("SMP: Total of 2 processors activated") - self.wait_for_console_pattern("No filesystem could mount root") - diff --git a/tests/functional/test_arm_aspeed_rainier.py b/tests/functional/test_arm_aspeed_rainier.py index XXXXXXX..XXXXXXX 100644 --- a/tests/functional/test_arm_aspeed_rainier.py +++ b/tests/functional/test_arm_aspeed_rainier.py @@ -XXX,XX +XXX,XX @@ def test_arm_aspeed_emmc_boot(self): self.wait_for_console_pattern('mmcblk0: p1 p2 p3 p4 p5 p6 p7') self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise') + ASSET_DEBIAN_LINUX_ARMHF_DEB = Asset( + ('http://snapshot.debian.org/archive/debian/20220606T211338Z/pool/main/l/linux/linux-image-5.17.0-2-armmp_5.17.6-1%2Bb1_armhf.deb'), + '8acb2b4439faedc2f3ed4bdb2847ad4f6e0491f73debaeb7f660c8abe4dcdc0e') + + def test_arm_debian_kernel_boot(self): + self.set_machine('rainier-bmc') + + deb_path = self.ASSET_DEBIAN_LINUX_ARMHF_DEB.fetch() + + kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.17.0-2-armmp') + dtb_path = self.extract_from_deb(deb_path, + '/usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb') + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-net', 'nic') + self.vm.launch() + + self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") + self.wait_for_console_pattern("SMP: Total of 2 processors activated") + self.wait_for_console_pattern("No filesystem could mount root") + + if __name__ == '__main__': AspeedTest.main() -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> So far, the test cases are used for testing SMC model with AST2400 BMC. However, AST2400 is end off live and ASPEED is no longer support this SOC. To test SMC model for AST2500, AST2600 and AST1030, move the test cases from main to test_palmetto_bmc function. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect_bottom_bit(void) flash_reset(); } -int main(int argc, char **argv) +static int test_palmetto_bmc(void) { g_autofree char *tmp_path = NULL; int ret; int fd; - g_test_init(&argc, &argv, NULL); - fd = g_file_open_tmp("qtest.m25p80.XXXXXX", &tmp_path, NULL); g_assert(fd >= 0); ret = ftruncate(fd, FLASH_SIZE); @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) flash_reset(); ret = g_test_run(); - qtest_quit(global_qtest); unlink(tmp_path); + + return ret; +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + ret = test_palmetto_bmc(); + return ret; } -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Currently, these test cases are only used for testing fmc_cs0 for AST2400. To test others BMC SOCs, introduces a new TestData structure. Users can set the spi base address, flash base address, jedesc id and so on for different BMC SOCs and flash model testing. Introduce new helper functions to make the test case more readable. Set spi base address 0x1E620000, flash_base address 0x20000000 and jedec id 0x20ba19 for fmc_cs0 with n25q256a flash for AST2400 SMC model testing. To pass the TestData into the test case, replace qtest_add_func with qtest_add_data_func. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 546 +++++++++++++++++++--------------- 1 file changed, 299 insertions(+), 247 deletions(-) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ #define CTRL_USERMODE 0x3 #define SR_WEL BIT(1) -#define ASPEED_FMC_BASE 0x1E620000 -#define ASPEED_FLASH_BASE 0x20000000 - /* * Flash commands */ @@ -XXX,XX +XXX,XX @@ enum { ERASE_SECTOR = 0xd8, }; -#define FLASH_JEDEC 0x20ba19 /* n25q256a */ -#define FLASH_SIZE (32 * 1024 * 1024) - #define FLASH_PAGE_SIZE 256 +typedef struct TestData { + QTestState *s; + uint64_t spi_base; + uint64_t flash_base; + uint32_t jedec_id; + char *tmp_path; +} TestData; + /* * Use an explicit bswap for the values read/wrote to the flash region * as they are BE and the Aspeed CPU is LE. @@ -XXX,XX +XXX,XX @@ static inline uint32_t make_be32(uint32_t data) return bswap32(data); } -static void spi_conf(uint32_t value) +static inline void spi_writel(const TestData *data, uint64_t offset, + uint32_t value) +{ + qtest_writel(data->s, data->spi_base + offset, value); +} + +static inline uint32_t spi_readl(const TestData *data, uint64_t offset) +{ + return qtest_readl(data->s, data->spi_base + offset); +} + +static inline void flash_writeb(const TestData *data, uint64_t offset, + uint8_t value) +{ + qtest_writeb(data->s, data->flash_base + offset, value); +} + +static inline void flash_writel(const TestData *data, uint64_t offset, + uint32_t value) +{ + qtest_writel(data->s, data->flash_base + offset, value); +} + +static inline uint8_t flash_readb(const TestData *data, uint64_t offset) { - uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF); + return qtest_readb(data->s, data->flash_base + offset); +} + +static inline uint32_t flash_readl(const TestData *data, uint64_t offset) +{ + return qtest_readl(data->s, data->flash_base + offset); +} + +static void spi_conf(const TestData *data, uint32_t value) +{ + uint32_t conf = spi_readl(data, R_CONF); conf |= value; - writel(ASPEED_FMC_BASE + R_CONF, conf); + spi_writel(data, R_CONF, conf); } -static void spi_conf_remove(uint32_t value) +static void spi_conf_remove(const TestData *data, uint32_t value) { - uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF); + uint32_t conf = spi_readl(data, R_CONF); conf &= ~value; - writel(ASPEED_FMC_BASE + R_CONF, conf); + spi_writel(data, R_CONF, conf); } -static void spi_ce_ctrl(uint32_t value) +static void spi_ce_ctrl(const TestData *data, uint32_t value) { - uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL); + uint32_t conf = spi_readl(data, R_CE_CTRL); conf |= value; - writel(ASPEED_FMC_BASE + R_CE_CTRL, conf); + spi_writel(data, R_CE_CTRL, conf); } -static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd) +static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd) { - uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0); + uint32_t ctrl = spi_readl(data, R_CTRL0); ctrl &= ~(CTRL_USERMODE | 0xff << 16); ctrl |= mode | (cmd << 16); - writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); + spi_writel(data, R_CTRL0, ctrl); } -static void spi_ctrl_start_user(void) +static void spi_ctrl_start_user(const TestData *data) { - uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0); + uint32_t ctrl = spi_readl(data, R_CTRL0); ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; - writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); + spi_writel(data, R_CTRL0, ctrl); ctrl &= ~CTRL_CE_STOP_ACTIVE; - writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); + spi_writel(data, R_CTRL0, ctrl); } -static void spi_ctrl_stop_user(void) +static void spi_ctrl_stop_user(const TestData *data) { - uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0); + uint32_t ctrl = spi_readl(data, R_CTRL0); ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; - writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); + spi_writel(data, R_CTRL0, ctrl); } -static void flash_reset(void) +static void flash_reset(const TestData *data) { - spi_conf(CONF_ENABLE_W0); + spi_conf(data, CONF_ENABLE_W0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, RESET_ENABLE); - writeb(ASPEED_FLASH_BASE, RESET_MEMORY); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, BULK_ERASE); - writeb(ASPEED_FLASH_BASE, WRDI); - spi_ctrl_stop_user(); + spi_ctrl_start_user(data); + flash_writeb(data, 0, RESET_ENABLE); + flash_writeb(data, 0, RESET_MEMORY); + flash_writeb(data, 0, WREN); + flash_writeb(data, 0, BULK_ERASE); + flash_writeb(data, 0, WRDI); + spi_ctrl_stop_user(data); - spi_conf_remove(CONF_ENABLE_W0); + spi_conf_remove(data, CONF_ENABLE_W0); } -static void test_read_jedec(void) +static void test_read_jedec(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t jedec = 0x0; - spi_conf(CONF_ENABLE_W0); + spi_conf(test_data, CONF_ENABLE_W0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, JEDEC_READ); - jedec |= readb(ASPEED_FLASH_BASE) << 16; - jedec |= readb(ASPEED_FLASH_BASE) << 8; - jedec |= readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, JEDEC_READ); + jedec |= flash_readb(test_data, 0) << 16; + jedec |= flash_readb(test_data, 0) << 8; + jedec |= flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); - flash_reset(); + flash_reset(test_data); - g_assert_cmphex(jedec, ==, FLASH_JEDEC); + g_assert_cmphex(jedec, ==, test_data->jedec_id); } -static void read_page(uint32_t addr, uint32_t *page) +static void read_page(const TestData *data, uint32_t addr, uint32_t *page) { int i; - spi_ctrl_start_user(); + spi_ctrl_start_user(data); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, READ); - writel(ASPEED_FLASH_BASE, make_be32(addr)); + flash_writeb(data, 0, EN_4BYTE_ADDR); + flash_writeb(data, 0, READ); + flash_writel(data, 0, make_be32(addr)); /* Continuous read are supported */ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - page[i] = make_be32(readl(ASPEED_FLASH_BASE)); + page[i] = make_be32(flash_readl(data, 0)); } - spi_ctrl_stop_user(); + spi_ctrl_stop_user(data); } -static void read_page_mem(uint32_t addr, uint32_t *page) +static void read_page_mem(const TestData *data, uint32_t addr, uint32_t *page) { int i; /* move out USER mode to use direct reads from the AHB bus */ - spi_ctrl_setmode(CTRL_READMODE, READ); + spi_ctrl_setmode(data, CTRL_READMODE, READ); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4)); + page[i] = make_be32(flash_readl(data, addr + i * 4)); } } -static void write_page_mem(uint32_t addr, uint32_t write_value) +static void write_page_mem(const TestData *data, uint32_t addr, + uint32_t write_value) { - spi_ctrl_setmode(CTRL_WRITEMODE, PP); + spi_ctrl_setmode(data, CTRL_WRITEMODE, PP); for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - writel(ASPEED_FLASH_BASE + addr + i * 4, write_value); + flash_writel(data, addr + i * 4, write_value); } } -static void assert_page_mem(uint32_t addr, uint32_t expected_value) +static void assert_page_mem(const TestData *data, uint32_t addr, + uint32_t expected_value) { uint32_t page[FLASH_PAGE_SIZE / 4]; - read_page_mem(addr, page); + read_page_mem(data, addr, page); for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, expected_value); } } -static void test_erase_sector(void) +static void test_erase_sector(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; - spi_conf(CONF_ENABLE_W0); + spi_conf(test_data, CONF_ENABLE_W0); /* * Previous page should be full of 0xffs after backend is * initialized */ - read_page(some_page_addr - FLASH_PAGE_SIZE, page); + read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, 0xffffffff); } - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, PP); - writel(ASPEED_FLASH_BASE, make_be32(some_page_addr)); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(some_page_addr)); /* Fill the page with its own addresses */ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - writel(ASPEED_FLASH_BASE, make_be32(some_page_addr + i * 4)); + flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); } - spi_ctrl_stop_user(); + spi_ctrl_stop_user(test_data); /* Check the page is correctly written */ - read_page(some_page_addr, page); + read_page(test_data, some_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, some_page_addr + i * 4); } - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, ERASE_SECTOR); - writel(ASPEED_FLASH_BASE, make_be32(some_page_addr)); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, ERASE_SECTOR); + flash_writel(test_data, 0, make_be32(some_page_addr)); + spi_ctrl_stop_user(test_data); /* Check the page is erased */ - read_page(some_page_addr, page); + read_page(test_data, some_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, 0xffffffff); } - flash_reset(); + flash_reset(test_data); } -static void test_erase_all(void) +static void test_erase_all(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; - spi_conf(CONF_ENABLE_W0); + spi_conf(test_data, CONF_ENABLE_W0); /* * Previous page should be full of 0xffs after backend is * initialized */ - read_page(some_page_addr - FLASH_PAGE_SIZE, page); + read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, 0xffffffff); } - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, PP); - writel(ASPEED_FLASH_BASE, make_be32(some_page_addr)); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(some_page_addr)); /* Fill the page with its own addresses */ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - writel(ASPEED_FLASH_BASE, make_be32(some_page_addr + i * 4)); + flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); } - spi_ctrl_stop_user(); + spi_ctrl_stop_user(test_data); /* Check the page is correctly written */ - read_page(some_page_addr, page); + read_page(test_data, some_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, some_page_addr + i * 4); } - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, BULK_ERASE); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, BULK_ERASE); + spi_ctrl_stop_user(test_data); /* Check the page is erased */ - read_page(some_page_addr, page); + read_page(test_data, some_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, 0xffffffff); } - flash_reset(); + flash_reset(test_data); } -static void test_write_page(void) +static void test_write_page(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */ uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; - spi_conf(CONF_ENABLE_W0); + spi_conf(test_data, CONF_ENABLE_W0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, PP); - writel(ASPEED_FLASH_BASE, make_be32(my_page_addr)); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(my_page_addr)); /* Fill the page with its own addresses */ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4)); + flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); } - spi_ctrl_stop_user(); + spi_ctrl_stop_user(test_data); /* Check what was written */ - read_page(my_page_addr, page); + read_page(test_data, my_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, my_page_addr + i * 4); } /* Check some other page. It should be full of 0xff */ - read_page(some_page_addr, page); + read_page(test_data, some_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, 0xffffffff); } - flash_reset(); + flash_reset(test_data); } -static void test_read_page_mem(void) +static void test_read_page_mem(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */ uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; @@ -XXX,XX +XXX,XX @@ static void test_read_page_mem(void) * Enable 4BYTE mode for controller. This is should be strapped by * HW for CE0 anyhow. */ - spi_ce_ctrl(1 << CRTL_EXTENDED0); + spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); /* Enable 4BYTE mode for flash. */ - spi_conf(CONF_ENABLE_W0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, PP); - writel(ASPEED_FLASH_BASE, make_be32(my_page_addr)); + spi_conf(test_data, CONF_ENABLE_W0); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(my_page_addr)); /* Fill the page with its own addresses */ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4)); + flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); } - spi_ctrl_stop_user(); - spi_conf_remove(CONF_ENABLE_W0); + spi_ctrl_stop_user(test_data); + spi_conf_remove(test_data, CONF_ENABLE_W0); /* Check what was written */ - read_page_mem(my_page_addr, page); + read_page_mem(test_data, my_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, my_page_addr + i * 4); } /* Check some other page. It should be full of 0xff */ - read_page_mem(some_page_addr, page); + read_page_mem(test_data, some_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, 0xffffffff); } - flash_reset(); + flash_reset(test_data); } -static void test_write_page_mem(void) +static void test_write_page_mem(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; @@ -XXX,XX +XXX,XX @@ static void test_write_page_mem(void) * Enable 4BYTE mode for controller. This is should be strapped by * HW for CE0 anyhow. */ - spi_ce_ctrl(1 << CRTL_EXTENDED0); + spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); /* Enable 4BYTE mode for flash. */ - spi_conf(CONF_ENABLE_W0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - spi_ctrl_stop_user(); + spi_conf(test_data, CONF_ENABLE_W0); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + spi_ctrl_stop_user(test_data); /* move out USER mode to use direct writes to the AHB bus */ - spi_ctrl_setmode(CTRL_WRITEMODE, PP); + spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - writel(ASPEED_FLASH_BASE + my_page_addr + i * 4, + flash_writel(test_data, my_page_addr + i * 4, make_be32(my_page_addr + i * 4)); } /* Check what was written */ - read_page_mem(my_page_addr, page); + read_page_mem(test_data, my_page_addr, page); for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { g_assert_cmphex(page[i], ==, my_page_addr + i * 4); } - flash_reset(); + flash_reset(test_data); } -static void test_read_status_reg(void) +static void test_read_status_reg(const void *data) { + const TestData *test_data = (const TestData *)data; uint8_t r; - spi_conf(CONF_ENABLE_W0); + spi_conf(test_data, CONF_ENABLE_W0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); g_assert_cmphex(r & SR_WEL, ==, 0); g_assert(!qtest_qom_get_bool - (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); g_assert_cmphex(r & SR_WEL, ==, SR_WEL); g_assert(qtest_qom_get_bool - (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WRDI); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WRDI); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); g_assert_cmphex(r & SR_WEL, ==, 0); g_assert(!qtest_qom_get_bool - (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); - flash_reset(); + flash_reset(test_data); } -static void test_status_reg_write_protection(void) +static void test_status_reg_write_protection(const void *data) { + const TestData *test_data = (const TestData *)data; uint8_t r; - spi_conf(CONF_ENABLE_W0); + spi_conf(test_data, CONF_ENABLE_W0); /* default case: WP# is high and SRWD is low -> status register writable */ - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); /* test ability to write SRWD */ - writeb(ASPEED_FLASH_BASE, WRSR); - writeb(ASPEED_FLASH_BASE, SRWD); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, SRWD); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); g_assert_cmphex(r & SRWD, ==, SRWD); /* WP# high and SRWD high -> status register writable */ - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); /* test ability to write SRWD */ - writeb(ASPEED_FLASH_BASE, WRSR); - writeb(ASPEED_FLASH_BASE, 0); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, 0); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); g_assert_cmphex(r & SRWD, ==, 0); /* WP# low and SRWD low -> status register writable */ - qtest_set_irq_in(global_qtest, + qtest_set_irq_in(test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); /* test ability to write SRWD */ - writeb(ASPEED_FLASH_BASE, WRSR); - writeb(ASPEED_FLASH_BASE, SRWD); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, SRWD); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); g_assert_cmphex(r & SRWD, ==, SRWD); /* WP# low and SRWD high -> status register NOT writable */ - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0 , WREN); /* test ability to write SRWD */ - writeb(ASPEED_FLASH_BASE, WRSR); - writeb(ASPEED_FLASH_BASE, 0); - writeb(ASPEED_FLASH_BASE, RDSR); - r = readb(ASPEED_FLASH_BASE); - spi_ctrl_stop_user(); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, 0); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); /* write is not successful */ g_assert_cmphex(r & SRWD, ==, SRWD); - qtest_set_irq_in(global_qtest, + qtest_set_irq_in(test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1); - flash_reset(); + flash_reset(test_data); } -static void test_write_block_protect(void) +static void test_write_block_protect(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t sector_size = 65536; uint32_t n_sectors = 512; - spi_ce_ctrl(1 << CRTL_EXTENDED0); - spi_conf(CONF_ENABLE_W0); + spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); + spi_conf(test_data, CONF_ENABLE_W0); uint32_t bp_bits = 0b0; for (int i = 0; i < 16; i++) { bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, BULK_ERASE); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, WRSR); - writeb(ASPEED_FLASH_BASE, bp_bits); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, BULK_ERASE); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, bp_bits); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + spi_ctrl_stop_user(test_data); uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; uint32_t protection_start = n_sectors - num_protected_sectors; @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect(void) for (int sector = 0; sector < n_sectors; sector++) { uint32_t addr = sector * sector_size; - assert_page_mem(addr, 0xffffffff); - write_page_mem(addr, make_be32(0xabcdef12)); + assert_page_mem(test_data, addr, 0xffffffff); + write_page_mem(test_data, addr, make_be32(0xabcdef12)); uint32_t expected_value = protection_start <= sector && sector < protection_end ? 0xffffffff : 0xabcdef12; - assert_page_mem(addr, expected_value); + assert_page_mem(test_data, addr, expected_value); } } - flash_reset(); + flash_reset(test_data); } -static void test_write_block_protect_bottom_bit(void) +static void test_write_block_protect_bottom_bit(const void *data) { + const TestData *test_data = (const TestData *)data; uint32_t sector_size = 65536; uint32_t n_sectors = 512; - spi_ce_ctrl(1 << CRTL_EXTENDED0); - spi_conf(CONF_ENABLE_W0); + spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); + spi_conf(test_data, CONF_ENABLE_W0); /* top bottom bit is enabled */ uint32_t bp_bits = 0b00100 << 3; @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect_bottom_bit(void) for (int i = 0; i < 16; i++) { bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); - spi_ctrl_start_user(); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, BULK_ERASE); - writeb(ASPEED_FLASH_BASE, WREN); - writeb(ASPEED_FLASH_BASE, WRSR); - writeb(ASPEED_FLASH_BASE, bp_bits); - writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); - writeb(ASPEED_FLASH_BASE, WREN); - spi_ctrl_stop_user(); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, BULK_ERASE); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, bp_bits); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + spi_ctrl_stop_user(test_data); uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; uint32_t protection_start = 0; @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect_bottom_bit(void) for (int sector = 0; sector < n_sectors; sector++) { uint32_t addr = sector * sector_size; - assert_page_mem(addr, 0xffffffff); - write_page_mem(addr, make_be32(0xabcdef12)); + assert_page_mem(test_data, addr, 0xffffffff); + write_page_mem(test_data, addr, make_be32(0xabcdef12)); uint32_t expected_value = protection_start <= sector && sector < protection_end ? 0xffffffff : 0xabcdef12; - assert_page_mem(addr, expected_value); + assert_page_mem(test_data, addr, expected_value); } } - flash_reset(); + flash_reset(test_data); } -static int test_palmetto_bmc(void) +static void test_palmetto_bmc(TestData *data) { - g_autofree char *tmp_path = NULL; int ret; int fd; - fd = g_file_open_tmp("qtest.m25p80.XXXXXX", &tmp_path, NULL); + fd = g_file_open_tmp("qtest.m25p80.n25q256a.XXXXXX", &data->tmp_path, NULL); g_assert(fd >= 0); - ret = ftruncate(fd, FLASH_SIZE); + ret = ftruncate(fd, 32 * 1024 * 1024); g_assert(ret == 0); close(fd); - global_qtest = qtest_initf("-m 256 -machine palmetto-bmc " - "-drive file=%s,format=raw,if=mtd", - tmp_path); - - qtest_add_func("/ast2400/smc/read_jedec", test_read_jedec); - qtest_add_func("/ast2400/smc/erase_sector", test_erase_sector); - qtest_add_func("/ast2400/smc/erase_all", test_erase_all); - qtest_add_func("/ast2400/smc/write_page", test_write_page); - qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem); - qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem); - qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg); - qtest_add_func("/ast2400/smc/status_reg_write_protection", - test_status_reg_write_protection); - qtest_add_func("/ast2400/smc/write_block_protect", - test_write_block_protect); - qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit", - test_write_block_protect_bottom_bit); - - flash_reset(); - ret = g_test_run(); - qtest_quit(global_qtest); - unlink(tmp_path); - - return ret; + data->s = qtest_initf("-m 256 -machine palmetto-bmc " + "-drive file=%s,format=raw,if=mtd", + data->tmp_path); + + /* fmc cs0 with n25q256a flash */ + data->flash_base = 0x20000000; + data->spi_base = 0x1E620000; + data->jedec_id = 0x20ba19; + + qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec); + qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector); + qtest_add_data_func("/ast2400/smc/erase_all", data, test_erase_all); + qtest_add_data_func("/ast2400/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast2400/smc/read_page_mem", + data, test_read_page_mem); + qtest_add_data_func("/ast2400/smc/write_page_mem", + data, test_write_page_mem); + qtest_add_data_func("/ast2400/smc/read_status_reg", + data, test_read_status_reg); + qtest_add_data_func("/ast2400/smc/status_reg_write_protection", + data, test_status_reg_write_protection); + qtest_add_data_func("/ast2400/smc/write_block_protect", + data, test_write_block_protect); + qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit", + data, test_write_block_protect_bottom_bit); } int main(int argc, char **argv) { + TestData palmetto_data; int ret; g_test_init(&argc, &argv, NULL); - ret = test_palmetto_bmc(); + test_palmetto_bmc(&palmetto_data); + ret = g_test_run(); + + qtest_quit(palmetto_data.s); + unlink(palmetto_data.tmp_path); return ret; } -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Currently, these test cases only support to test CE0. To test all CE pins, introduces new ce and node members in TestData structure. The ce member is used for saving the ce index and node member is used for saving the node path, respectively. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-4-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 77 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ * ASPEED SPI Controller registers */ #define R_CONF 0x00 -#define CONF_ENABLE_W0 (1 << 16) +#define CONF_ENABLE_W0 16 #define R_CE_CTRL 0x04 #define CRTL_EXTENDED0 0 /* 32 bit addressing for SPI */ #define R_CTRL0 0x10 -#define CTRL_CE_STOP_ACTIVE (1 << 2) +#define CTRL_CE_STOP_ACTIVE BIT(2) #define CTRL_READMODE 0x0 #define CTRL_FREADMODE 0x1 #define CTRL_WRITEMODE 0x2 @@ -XXX,XX +XXX,XX @@ typedef struct TestData { uint64_t flash_base; uint32_t jedec_id; char *tmp_path; + uint8_t cs; + const char *node; } TestData; /* @@ -XXX,XX +XXX,XX @@ static void spi_ce_ctrl(const TestData *data, uint32_t value) static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd) { - uint32_t ctrl = spi_readl(data, R_CTRL0); + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); ctrl &= ~(CTRL_USERMODE | 0xff << 16); ctrl |= mode | (cmd << 16); - spi_writel(data, R_CTRL0, ctrl); + spi_writel(data, ctrl_reg, ctrl); } static void spi_ctrl_start_user(const TestData *data) { - uint32_t ctrl = spi_readl(data, R_CTRL0); + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; - spi_writel(data, R_CTRL0, ctrl); + spi_writel(data, ctrl_reg, ctrl); ctrl &= ~CTRL_CE_STOP_ACTIVE; - spi_writel(data, R_CTRL0, ctrl); + spi_writel(data, ctrl_reg, ctrl); } static void spi_ctrl_stop_user(const TestData *data) { - uint32_t ctrl = spi_readl(data, R_CTRL0); + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; - spi_writel(data, R_CTRL0, ctrl); + spi_writel(data, ctrl_reg, ctrl); } static void flash_reset(const TestData *data) { - spi_conf(data, CONF_ENABLE_W0); + spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs)); spi_ctrl_start_user(data); flash_writeb(data, 0, RESET_ENABLE); @@ -XXX,XX +XXX,XX @@ static void flash_reset(const TestData *data) flash_writeb(data, 0, WRDI); spi_ctrl_stop_user(data); - spi_conf_remove(data, CONF_ENABLE_W0); + spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs)); } static void test_read_jedec(const void *data) @@ -XXX,XX +XXX,XX @@ static void test_read_jedec(const void *data) const TestData *test_data = (const TestData *)data; uint32_t jedec = 0x0; - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, JEDEC_READ); @@ -XXX,XX +XXX,XX @@ static void test_erase_sector(const void *data) uint32_t page[FLASH_PAGE_SIZE / 4]; int i; - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); /* * Previous page should be full of 0xffs after backend is @@ -XXX,XX +XXX,XX @@ static void test_erase_all(const void *data) uint32_t page[FLASH_PAGE_SIZE / 4]; int i; - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); /* * Previous page should be full of 0xffs after backend is @@ -XXX,XX +XXX,XX @@ static void test_write_page(const void *data) uint32_t page[FLASH_PAGE_SIZE / 4]; int i; - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, EN_4BYTE_ADDR); @@ -XXX,XX +XXX,XX @@ static void test_read_page_mem(const void *data) int i; /* - * Enable 4BYTE mode for controller. This is should be strapped by - * HW for CE0 anyhow. + * Enable 4BYTE mode for controller. */ - spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); /* Enable 4BYTE mode for flash. */ - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, EN_4BYTE_ADDR); flash_writeb(test_data, 0, WREN); @@ -XXX,XX +XXX,XX @@ static void test_read_page_mem(const void *data) flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); } spi_ctrl_stop_user(test_data); - spi_conf_remove(test_data, CONF_ENABLE_W0); + spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); /* Check what was written */ read_page_mem(test_data, my_page_addr, page); @@ -XXX,XX +XXX,XX @@ static void test_write_page_mem(const void *data) int i; /* - * Enable 4BYTE mode for controller. This is should be strapped by - * HW for CE0 anyhow. + * Enable 4BYTE mode for controller. */ - spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); /* Enable 4BYTE mode for flash. */ - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, EN_4BYTE_ADDR); flash_writeb(test_data, 0, WREN); @@ -XXX,XX +XXX,XX @@ static void test_read_status_reg(const void *data) const TestData *test_data = (const TestData *)data; uint8_t r; - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, RDSR); @@ -XXX,XX +XXX,XX @@ static void test_read_status_reg(const void *data) g_assert_cmphex(r & SR_WEL, ==, 0); g_assert(!qtest_qom_get_bool - (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + (test_data->s, test_data->node, "write-enable")); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, WREN); @@ -XXX,XX +XXX,XX @@ static void test_read_status_reg(const void *data) g_assert_cmphex(r & SR_WEL, ==, SR_WEL); g_assert(qtest_qom_get_bool - (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + (test_data->s, test_data->node, "write-enable")); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, WRDI); @@ -XXX,XX +XXX,XX @@ static void test_read_status_reg(const void *data) g_assert_cmphex(r & SR_WEL, ==, 0); g_assert(!qtest_qom_get_bool - (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); + (test_data->s, test_data->node, "write-enable")); flash_reset(test_data); } @@ -XXX,XX +XXX,XX @@ static void test_status_reg_write_protection(const void *data) const TestData *test_data = (const TestData *)data; uint8_t r; - spi_conf(test_data, CONF_ENABLE_W0); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); /* default case: WP# is high and SRWD is low -> status register writable */ spi_ctrl_start_user(test_data); @@ -XXX,XX +XXX,XX @@ static void test_status_reg_write_protection(const void *data) g_assert_cmphex(r & SRWD, ==, 0); /* WP# low and SRWD low -> status register writable */ - qtest_set_irq_in(test_data->s, - "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0); + qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0); spi_ctrl_start_user(test_data); flash_writeb(test_data, 0, WREN); /* test ability to write SRWD */ @@ -XXX,XX +XXX,XX @@ static void test_status_reg_write_protection(const void *data) /* write is not successful */ g_assert_cmphex(r & SRWD, ==, SRWD); - qtest_set_irq_in(test_data->s, - "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1); + qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1); flash_reset(test_data); } @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect(const void *data) uint32_t sector_size = 65536; uint32_t n_sectors = 512; - spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); - spi_conf(test_data, CONF_ENABLE_W0); + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); uint32_t bp_bits = 0b0; @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect_bottom_bit(const void *data) uint32_t sector_size = 65536; uint32_t n_sectors = 512; - spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0); - spi_conf(test_data, CONF_ENABLE_W0); + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); /* top bottom bit is enabled */ uint32_t bp_bits = 0b00100 << 3; @@ -XXX,XX +XXX,XX @@ static void test_palmetto_bmc(TestData *data) data->flash_base = 0x20000000; data->spi_base = 0x1E620000; data->jedec_id = 0x20ba19; + data->cs = 0; + data->node = "/machine/soc/fmc/ssi.0/child[0]"; qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec); qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector); -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Currently, these test cases used the hardcode offset 0x1400000 (0x14000 * 256) which was beyond the 16MB flash size for flash page read/write command testing. However, the default fmc flash model of ast1030-a1 EVB is "w25q80bl" whose size is 1MB. To test SoC flash models, introduces a new page_addr member in TestData structure, so users can set the offset for flash page read/write command testing. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-5-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ typedef struct TestData { char *tmp_path; uint8_t cs; const char *node; + uint32_t page_addr; } TestData; /* @@ -XXX,XX +XXX,XX @@ static void assert_page_mem(const TestData *data, uint32_t addr, static void test_erase_sector(const void *data) { const TestData *test_data = (const TestData *)data; - uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE; + uint32_t some_page_addr = test_data->page_addr; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; @@ -XXX,XX +XXX,XX @@ static void test_erase_sector(const void *data) static void test_erase_all(const void *data) { const TestData *test_data = (const TestData *)data; - uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; + uint32_t some_page_addr = test_data->page_addr; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; @@ -XXX,XX +XXX,XX @@ static void test_erase_all(const void *data) static void test_write_page(const void *data) { const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */ - uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; + uint32_t my_page_addr = test_data->page_addr; + uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; @@ -XXX,XX +XXX,XX @@ static void test_write_page(const void *data) static void test_read_page_mem(const void *data) { const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */ - uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; + uint32_t my_page_addr = test_data->page_addr; + uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; @@ -XXX,XX +XXX,XX @@ static void test_read_page_mem(const void *data) static void test_write_page_mem(const void *data) { const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE; + uint32_t my_page_addr = test_data->page_addr; uint32_t page[FLASH_PAGE_SIZE / 4]; int i; @@ -XXX,XX +XXX,XX @@ static void test_palmetto_bmc(TestData *data) data->jedec_id = 0x20ba19; data->cs = 0; data->node = "/machine/soc/fmc/ssi.0/child[0]"; + /* beyond 16MB */ + data->page_addr = 0x14000 * FLASH_PAGE_SIZE; qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec); qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector); -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add test_ast2500_evb function and reused testcases for AST2500 testing. The spi base address, flash base address and ce index of fmc_cs0 are 0x1E620000, 0x20000000 and 0, respectively. The default flash model of fmc_cs0 is "mx25l25635e" whose size is 32MB, so set jedec_id 0xc22019. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-6-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ static void test_palmetto_bmc(TestData *data) data, test_write_block_protect_bottom_bit); } +static void test_ast2500_evb(TestData *data) +{ + int ret; + int fd; + + fd = g_file_open_tmp("qtest.m25p80.mx25l25635e.XXXXXX", + &data->tmp_path, NULL); + g_assert(fd >= 0); + ret = ftruncate(fd, 32 * 1024 * 1024); + g_assert(ret == 0); + close(fd); + + data->s = qtest_initf("-machine ast2500-evb " + "-drive file=%s,format=raw,if=mtd", + data->tmp_path); + + /* fmc cs0 with mx25l25635e flash */ + data->flash_base = 0x20000000; + data->spi_base = 0x1E620000; + data->jedec_id = 0xc22019; + data->cs = 0; + data->node = "/machine/soc/fmc/ssi.0/child[0]"; + /* beyond 16MB */ + data->page_addr = 0x14000 * FLASH_PAGE_SIZE; + + qtest_add_data_func("/ast2500/smc/read_jedec", data, test_read_jedec); + qtest_add_data_func("/ast2500/smc/erase_sector", data, test_erase_sector); + qtest_add_data_func("/ast2500/smc/erase_all", data, test_erase_all); + qtest_add_data_func("/ast2500/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast2500/smc/read_page_mem", + data, test_read_page_mem); + qtest_add_data_func("/ast2500/smc/write_page_mem", + data, test_write_page_mem); + qtest_add_data_func("/ast2500/smc/read_status_reg", + data, test_read_status_reg); +} int main(int argc, char **argv) { TestData palmetto_data; + TestData ast2500_evb_data; int ret; g_test_init(&argc, &argv, NULL); test_palmetto_bmc(&palmetto_data); + test_ast2500_evb(&ast2500_evb_data); ret = g_test_run(); qtest_quit(palmetto_data.s); + qtest_quit(ast2500_evb_data.s); unlink(palmetto_data.tmp_path); + unlink(ast2500_evb_data.tmp_path); return ret; } -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add test_ast2600_evb function and reused testcases for AST2600 testing. The spi base address, flash base address and ce index of fmc_cs0 are 0x1E620000, 0x20000000 and 0, respectively. The default flash model of fmc_cs0 is "mx66u51235f" whose size is 64MB, so set jedec_id 0xc2253a. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-7-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ static void test_ast2500_evb(TestData *data) qtest_add_data_func("/ast2500/smc/read_status_reg", data, test_read_status_reg); } + +static void test_ast2600_evb(TestData *data) +{ + int ret; + int fd; + + fd = g_file_open_tmp("qtest.m25p80.mx66u51235f.XXXXXX", + &data->tmp_path, NULL); + g_assert(fd >= 0); + ret = ftruncate(fd, 64 * 1024 * 1024); + g_assert(ret == 0); + close(fd); + + data->s = qtest_initf("-machine ast2600-evb " + "-drive file=%s,format=raw,if=mtd", + data->tmp_path); + + /* fmc cs0 with mx66u51235f flash */ + data->flash_base = 0x20000000; + data->spi_base = 0x1E620000; + data->jedec_id = 0xc2253a; + data->cs = 0; + data->node = "/machine/soc/fmc/ssi.0/child[0]"; + /* beyond 16MB */ + data->page_addr = 0x14000 * FLASH_PAGE_SIZE; + + qtest_add_data_func("/ast2600/smc/read_jedec", data, test_read_jedec); + qtest_add_data_func("/ast2600/smc/erase_sector", data, test_erase_sector); + qtest_add_data_func("/ast2600/smc/erase_all", data, test_erase_all); + qtest_add_data_func("/ast2600/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast2600/smc/read_page_mem", + data, test_read_page_mem); + qtest_add_data_func("/ast2600/smc/write_page_mem", + data, test_write_page_mem); + qtest_add_data_func("/ast2600/smc/read_status_reg", + data, test_read_status_reg); +} int main(int argc, char **argv) { TestData palmetto_data; TestData ast2500_evb_data; + TestData ast2600_evb_data; int ret; g_test_init(&argc, &argv, NULL); test_palmetto_bmc(&palmetto_data); test_ast2500_evb(&ast2500_evb_data); + test_ast2600_evb(&ast2600_evb_data); ret = g_test_run(); qtest_quit(palmetto_data.s); qtest_quit(ast2500_evb_data.s); + qtest_quit(ast2600_evb_data.s); unlink(palmetto_data.tmp_path); unlink(ast2500_evb_data.tmp_path); + unlink(ast2600_evb_data.tmp_path); return ret; } -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add test_ast1030_evb function and reused testcases for AST1030 testing. The base address, flash base address and ce index of fmc_cs0 are 0x7E620000, 0x80000000 and 0, respectively. The default flash model of fmc_cs0 is "w25q80bl" whose size is 1MB, so set jedec_id 0xef4014. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-8-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ static void test_ast2600_evb(TestData *data) qtest_add_data_func("/ast2600/smc/read_status_reg", data, test_read_status_reg); } + +static void test_ast1030_evb(TestData *data) +{ + int ret; + int fd; + + fd = g_file_open_tmp("qtest.m25p80.w25q80bl.XXXXXX", + &data->tmp_path, NULL); + g_assert(fd >= 0); + ret = ftruncate(fd, 1 * 1024 * 1024); + g_assert(ret == 0); + close(fd); + + data->s = qtest_initf("-machine ast1030-evb " + "-drive file=%s,format=raw,if=mtd", + data->tmp_path); + + /* fmc cs0 with w25q80bl flash */ + data->flash_base = 0x80000000; + data->spi_base = 0x7E620000; + data->jedec_id = 0xef4014; + data->cs = 0; + data->node = "/machine/soc/fmc/ssi.0/child[0]"; + /* beyond 512KB */ + data->page_addr = 0x800 * FLASH_PAGE_SIZE; + + qtest_add_data_func("/ast1030/smc/read_jedec", data, test_read_jedec); + qtest_add_data_func("/ast1030/smc/erase_sector", data, test_erase_sector); + qtest_add_data_func("/ast1030/smc/erase_all", data, test_erase_all); + qtest_add_data_func("/ast1030/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast1030/smc/read_page_mem", + data, test_read_page_mem); + qtest_add_data_func("/ast1030/smc/write_page_mem", + data, test_write_page_mem); + qtest_add_data_func("/ast1030/smc/read_status_reg", + data, test_read_status_reg); +} + int main(int argc, char **argv) { TestData palmetto_data; TestData ast2500_evb_data; TestData ast2600_evb_data; + TestData ast1030_evb_data; int ret; g_test_init(&argc, &argv, NULL); @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) test_palmetto_bmc(&palmetto_data); test_ast2500_evb(&ast2500_evb_data); test_ast2600_evb(&ast2600_evb_data); + test_ast1030_evb(&ast1030_evb_data); ret = g_test_run(); qtest_quit(palmetto_data.s); qtest_quit(ast2500_evb_data.s); qtest_quit(ast2600_evb_data.s); + qtest_quit(ast1030_evb_data.s); unlink(palmetto_data.tmp_path); unlink(ast2500_evb_data.tmp_path); unlink(ast2600_evb_data.tmp_path); + unlink(ast1030_evb_data.tmp_path); return ret; } -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add a new testcase for write page command with QPI mode testing. Currently, only run this testcase for AST2500, AST2600 and AST1030. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-9-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed_smc-test.c | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ #define R_CE_CTRL 0x04 #define CRTL_EXTENDED0 0 /* 32 bit addressing for SPI */ #define R_CTRL0 0x10 +#define CTRL_IO_QUAD_IO BIT(31) #define CTRL_CE_STOP_ACTIVE BIT(2) #define CTRL_READMODE 0x0 #define CTRL_FREADMODE 0x1 @@ -XXX,XX +XXX,XX @@ enum { ERASE_SECTOR = 0xd8, }; +#define CTRL_IO_MODE_MASK (BIT(31) | BIT(30) | BIT(29) | BIT(28)) #define FLASH_PAGE_SIZE 256 typedef struct TestData { @@ -XXX,XX +XXX,XX @@ static void spi_ctrl_stop_user(const TestData *data) spi_writel(data, ctrl_reg, ctrl); } +static void spi_ctrl_set_io_mode(const TestData *data, uint32_t value) +{ + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); + uint32_t mode; + + mode = value & CTRL_IO_MODE_MASK; + ctrl &= ~CTRL_IO_MODE_MASK; + ctrl |= mode; + spi_writel(data, ctrl_reg, ctrl); +} + static void flash_reset(const TestData *data) { spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs)); @@ -XXX,XX +XXX,XX @@ static void test_write_block_protect_bottom_bit(const void *data) flash_reset(test_data); } +static void test_write_page_qpi(const void *data) +{ + const TestData *test_data = (const TestData *)data; + uint32_t my_page_addr = test_data->page_addr; + uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; + uint32_t page[FLASH_PAGE_SIZE / 4]; + uint32_t page_pattern[] = { + 0xebd8c134, 0x5da196bc, 0xae15e729, 0x5085ccdf + }; + int i; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(my_page_addr)); + + /* Set QPI mode */ + spi_ctrl_set_io_mode(test_data, CTRL_IO_QUAD_IO); + + /* Fill the page pattern */ + for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { + flash_writel(test_data, 0, make_be32(page_pattern[i])); + } + + /* Fill the page with its own addresses */ + for (; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); + } + + /* Restore io mode */ + spi_ctrl_set_io_mode(test_data, 0); + spi_ctrl_stop_user(test_data); + + /* Check what was written */ + read_page(test_data, my_page_addr, page); + for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { + g_assert_cmphex(page[i], ==, page_pattern[i]); + } + for (; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, my_page_addr + i * 4); + } + + /* Check some other page. It should be full of 0xff */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + flash_reset(test_data); +} + static void test_palmetto_bmc(TestData *data) { int ret; @@ -XXX,XX +XXX,XX @@ static void test_ast2500_evb(TestData *data) data, test_write_page_mem); qtest_add_data_func("/ast2500/smc/read_status_reg", data, test_read_status_reg); + qtest_add_data_func("/ast2500/smc/write_page_qpi", + data, test_write_page_qpi); } static void test_ast2600_evb(TestData *data) @@ -XXX,XX +XXX,XX @@ static void test_ast2600_evb(TestData *data) data, test_write_page_mem); qtest_add_data_func("/ast2600/smc/read_status_reg", data, test_read_status_reg); + qtest_add_data_func("/ast2600/smc/write_page_qpi", + data, test_write_page_qpi); } static void test_ast1030_evb(TestData *data) @@ -XXX,XX +XXX,XX @@ static void test_ast1030_evb(TestData *data) data, test_write_page_mem); qtest_add_data_func("/ast1030/smc/read_status_reg", data, test_read_status_reg); + qtest_add_data_func("/ast1030/smc/write_page_qpi", + data, test_write_page_qpi); } int main(int argc, char **argv) -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> The testcases for ASPEED SMC model were placed in aspeed_smc-test.c. However, this test file only supports for ARM32. To support all ASPEED SOCs such as AST2700 whose CPU architecture is aarch64, introduces a new aspeed-smc-utils source file and move all common APIs and testcases from aspeed_smc-test.c to aspeed-smc-utils.c. Finally, users are able to re-used these testcase for AST2700 and future ASPEED SOCs testing. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-10-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/aspeed-smc-utils.h | 95 ++++ tests/qtest/aspeed-smc-utils.c | 686 ++++++++++++++++++++++++++++ tests/qtest/aspeed_smc-test.c | 800 +++------------------------------ tests/qtest/meson.build | 1 + 4 files changed, 841 insertions(+), 741 deletions(-) create mode 100644 tests/qtest/aspeed-smc-utils.h create mode 100644 tests/qtest/aspeed-smc-utils.c diff --git a/tests/qtest/aspeed-smc-utils.h b/tests/qtest/aspeed-smc-utils.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/qtest/aspeed-smc-utils.h @@ -XXX,XX +XXX,XX @@ +/* + * QTest testcase for the M25P80 Flash (Using the Aspeed SPI + * Controller) + * + * Copyright (C) 2016 IBM Corp. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TESTS_ASPEED_SMC_UTILS_H +#define TESTS_ASPEED_SMC_UTILS_H + +#include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "libqtest-single.h" +#include "qemu/bitops.h" + +/* + * ASPEED SPI Controller registers + */ +#define R_CONF 0x00 +#define CONF_ENABLE_W0 16 +#define R_CE_CTRL 0x04 +#define CRTL_EXTENDED0 0 /* 32 bit addressing for SPI */ +#define R_CTRL0 0x10 +#define CTRL_IO_QUAD_IO BIT(31) +#define CTRL_CE_STOP_ACTIVE BIT(2) +#define CTRL_READMODE 0x0 +#define CTRL_FREADMODE 0x1 +#define CTRL_WRITEMODE 0x2 +#define CTRL_USERMODE 0x3 +#define SR_WEL BIT(1) + +/* + * Flash commands + */ +enum { + JEDEC_READ = 0x9f, + RDSR = 0x5, + WRDI = 0x4, + BULK_ERASE = 0xc7, + READ = 0x03, + PP = 0x02, + WRSR = 0x1, + WREN = 0x6, + SRWD = 0x80, + RESET_ENABLE = 0x66, + RESET_MEMORY = 0x99, + EN_4BYTE_ADDR = 0xB7, + ERASE_SECTOR = 0xd8, +}; + +#define CTRL_IO_MODE_MASK (BIT(31) | BIT(30) | BIT(29) | BIT(28)) +#define FLASH_PAGE_SIZE 256 + +typedef struct AspeedSMCTestData { + QTestState *s; + uint64_t spi_base; + uint64_t flash_base; + uint32_t jedec_id; + char *tmp_path; + uint8_t cs; + const char *node; + uint32_t page_addr; +} AspeedSMCTestData; + +void aspeed_smc_test_read_jedec(const void *data); +void aspeed_smc_test_erase_sector(const void *data); +void aspeed_smc_test_erase_all(const void *data); +void aspeed_smc_test_write_page(const void *data); +void aspeed_smc_test_read_page_mem(const void *data); +void aspeed_smc_test_write_page_mem(const void *data); +void aspeed_smc_test_read_status_reg(const void *data); +void aspeed_smc_test_status_reg_write_protection(const void *data); +void aspeed_smc_test_write_block_protect(const void *data); +void aspeed_smc_test_write_block_protect_bottom_bit(const void *data); +void aspeed_smc_test_write_page_qpi(const void *data); + +#endif /* TESTS_ASPEED_SMC_UTILS_H */ diff --git a/tests/qtest/aspeed-smc-utils.c b/tests/qtest/aspeed-smc-utils.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/qtest/aspeed-smc-utils.c @@ -XXX,XX +XXX,XX @@ +/* + * QTest testcase for the M25P80 Flash (Using the Aspeed SPI + * Controller) + * + * Copyright (C) 2016 IBM Corp. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "libqtest-single.h" +#include "qemu/bitops.h" +#include "aspeed-smc-utils.h" + +/* + * Use an explicit bswap for the values read/wrote to the flash region + * as they are BE and the Aspeed CPU is LE. + */ +static inline uint32_t make_be32(uint32_t data) +{ + return bswap32(data); +} + +static inline void spi_writel(const AspeedSMCTestData *data, uint64_t offset, + uint32_t value) +{ + qtest_writel(data->s, data->spi_base + offset, value); +} + +static inline uint32_t spi_readl(const AspeedSMCTestData *data, uint64_t offset) +{ + return qtest_readl(data->s, data->spi_base + offset); +} + +static inline void flash_writeb(const AspeedSMCTestData *data, uint64_t offset, + uint8_t value) +{ + qtest_writeb(data->s, data->flash_base + offset, value); +} + +static inline void flash_writel(const AspeedSMCTestData *data, uint64_t offset, + uint32_t value) +{ + qtest_writel(data->s, data->flash_base + offset, value); +} + +static inline uint8_t flash_readb(const AspeedSMCTestData *data, + uint64_t offset) +{ + return qtest_readb(data->s, data->flash_base + offset); +} + +static inline uint32_t flash_readl(const AspeedSMCTestData *data, + uint64_t offset) +{ + return qtest_readl(data->s, data->flash_base + offset); +} + +static void spi_conf(const AspeedSMCTestData *data, uint32_t value) +{ + uint32_t conf = spi_readl(data, R_CONF); + + conf |= value; + spi_writel(data, R_CONF, conf); +} + +static void spi_conf_remove(const AspeedSMCTestData *data, uint32_t value) +{ + uint32_t conf = spi_readl(data, R_CONF); + + conf &= ~value; + spi_writel(data, R_CONF, conf); +} + +static void spi_ce_ctrl(const AspeedSMCTestData *data, uint32_t value) +{ + uint32_t conf = spi_readl(data, R_CE_CTRL); + + conf |= value; + spi_writel(data, R_CE_CTRL, conf); +} + +static void spi_ctrl_setmode(const AspeedSMCTestData *data, uint8_t mode, + uint8_t cmd) +{ + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); + ctrl &= ~(CTRL_USERMODE | 0xff << 16); + ctrl |= mode | (cmd << 16); + spi_writel(data, ctrl_reg, ctrl); +} + +static void spi_ctrl_start_user(const AspeedSMCTestData *data) +{ + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); + + ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; + spi_writel(data, ctrl_reg, ctrl); + + ctrl &= ~CTRL_CE_STOP_ACTIVE; + spi_writel(data, ctrl_reg, ctrl); +} + +static void spi_ctrl_stop_user(const AspeedSMCTestData *data) +{ + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); + + ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; + spi_writel(data, ctrl_reg, ctrl); +} + +static void spi_ctrl_set_io_mode(const AspeedSMCTestData *data, uint32_t value) +{ + uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; + uint32_t ctrl = spi_readl(data, ctrl_reg); + uint32_t mode; + + mode = value & CTRL_IO_MODE_MASK; + ctrl &= ~CTRL_IO_MODE_MASK; + ctrl |= mode; + spi_writel(data, ctrl_reg, ctrl); +} + +static void flash_reset(const AspeedSMCTestData *data) +{ + spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs)); + + spi_ctrl_start_user(data); + flash_writeb(data, 0, RESET_ENABLE); + flash_writeb(data, 0, RESET_MEMORY); + flash_writeb(data, 0, WREN); + flash_writeb(data, 0, BULK_ERASE); + flash_writeb(data, 0, WRDI); + spi_ctrl_stop_user(data); + + spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs)); +} + +static void read_page(const AspeedSMCTestData *data, uint32_t addr, + uint32_t *page) +{ + int i; + + spi_ctrl_start_user(data); + + flash_writeb(data, 0, EN_4BYTE_ADDR); + flash_writeb(data, 0, READ); + flash_writel(data, 0, make_be32(addr)); + + /* Continuous read are supported */ + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + page[i] = make_be32(flash_readl(data, 0)); + } + spi_ctrl_stop_user(data); +} + +static void read_page_mem(const AspeedSMCTestData *data, uint32_t addr, + uint32_t *page) +{ + int i; + + /* move out USER mode to use direct reads from the AHB bus */ + spi_ctrl_setmode(data, CTRL_READMODE, READ); + + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + page[i] = make_be32(flash_readl(data, addr + i * 4)); + } +} + +static void write_page_mem(const AspeedSMCTestData *data, uint32_t addr, + uint32_t write_value) +{ + spi_ctrl_setmode(data, CTRL_WRITEMODE, PP); + + for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(data, addr + i * 4, write_value); + } +} + +static void assert_page_mem(const AspeedSMCTestData *data, uint32_t addr, + uint32_t expected_value) +{ + uint32_t page[FLASH_PAGE_SIZE / 4]; + read_page_mem(data, addr, page); + for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, expected_value); + } +} + +void aspeed_smc_test_read_jedec(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t jedec = 0x0; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, JEDEC_READ); + jedec |= flash_readb(test_data, 0) << 16; + jedec |= flash_readb(test_data, 0) << 8; + jedec |= flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + + flash_reset(test_data); + + g_assert_cmphex(jedec, ==, test_data->jedec_id); +} + +void aspeed_smc_test_erase_sector(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t some_page_addr = test_data->page_addr; + uint32_t page[FLASH_PAGE_SIZE / 4]; + int i; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + /* + * Previous page should be full of 0xffs after backend is + * initialized + */ + read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(some_page_addr)); + + /* Fill the page with its own addresses */ + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); + } + spi_ctrl_stop_user(test_data); + + /* Check the page is correctly written */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, some_page_addr + i * 4); + } + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, ERASE_SECTOR); + flash_writel(test_data, 0, make_be32(some_page_addr)); + spi_ctrl_stop_user(test_data); + + /* Check the page is erased */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + flash_reset(test_data); +} + +void aspeed_smc_test_erase_all(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t some_page_addr = test_data->page_addr; + uint32_t page[FLASH_PAGE_SIZE / 4]; + int i; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + /* + * Previous page should be full of 0xffs after backend is + * initialized + */ + read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(some_page_addr)); + + /* Fill the page with its own addresses */ + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); + } + spi_ctrl_stop_user(test_data); + + /* Check the page is correctly written */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, some_page_addr + i * 4); + } + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, BULK_ERASE); + spi_ctrl_stop_user(test_data); + + /* Check the page is erased */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + flash_reset(test_data); +} + +void aspeed_smc_test_write_page(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t my_page_addr = test_data->page_addr; + uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; + uint32_t page[FLASH_PAGE_SIZE / 4]; + int i; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(my_page_addr)); + + /* Fill the page with its own addresses */ + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); + } + spi_ctrl_stop_user(test_data); + + /* Check what was written */ + read_page(test_data, my_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, my_page_addr + i * 4); + } + + /* Check some other page. It should be full of 0xff */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + flash_reset(test_data); +} + +void aspeed_smc_test_read_page_mem(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t my_page_addr = test_data->page_addr; + uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; + uint32_t page[FLASH_PAGE_SIZE / 4]; + int i; + + /* + * Enable 4BYTE mode for controller. + */ + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); + + /* Enable 4BYTE mode for flash. */ + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(my_page_addr)); + + /* Fill the page with its own addresses */ + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); + } + spi_ctrl_stop_user(test_data); + spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + /* Check what was written */ + read_page_mem(test_data, my_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, my_page_addr + i * 4); + } + + /* Check some other page. It should be full of 0xff */ + read_page_mem(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + flash_reset(test_data); +} + +void aspeed_smc_test_write_page_mem(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t my_page_addr = test_data->page_addr; + uint32_t page[FLASH_PAGE_SIZE / 4]; + int i; + + /* + * Enable 4BYTE mode for controller. + */ + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); + + /* Enable 4BYTE mode for flash. */ + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + spi_ctrl_stop_user(test_data); + + /* move out USER mode to use direct writes to the AHB bus */ + spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP); + + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, my_page_addr + i * 4, + make_be32(my_page_addr + i * 4)); + } + + /* Check what was written */ + read_page_mem(test_data, my_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, my_page_addr + i * 4); + } + + flash_reset(test_data); +} + +void aspeed_smc_test_read_status_reg(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint8_t r; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + + g_assert_cmphex(r & SR_WEL, ==, 0); + g_assert(!qtest_qom_get_bool + (test_data->s, test_data->node, "write-enable")); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + + g_assert_cmphex(r & SR_WEL, ==, SR_WEL); + g_assert(qtest_qom_get_bool + (test_data->s, test_data->node, "write-enable")); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WRDI); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + + g_assert_cmphex(r & SR_WEL, ==, 0); + g_assert(!qtest_qom_get_bool + (test_data->s, test_data->node, "write-enable")); + + flash_reset(test_data); +} + +void aspeed_smc_test_status_reg_write_protection(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint8_t r; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + /* default case: WP# is high and SRWD is low -> status register writable */ + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + /* test ability to write SRWD */ + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, SRWD); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + g_assert_cmphex(r & SRWD, ==, SRWD); + + /* WP# high and SRWD high -> status register writable */ + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + /* test ability to write SRWD */ + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, 0); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + g_assert_cmphex(r & SRWD, ==, 0); + + /* WP# low and SRWD low -> status register writable */ + qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0); + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + /* test ability to write SRWD */ + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, SRWD); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + g_assert_cmphex(r & SRWD, ==, SRWD); + + /* WP# low and SRWD high -> status register NOT writable */ + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0 , WREN); + /* test ability to write SRWD */ + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, 0); + flash_writeb(test_data, 0, RDSR); + r = flash_readb(test_data, 0); + spi_ctrl_stop_user(test_data); + /* write is not successful */ + g_assert_cmphex(r & SRWD, ==, SRWD); + + qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1); + flash_reset(test_data); +} + +void aspeed_smc_test_write_block_protect(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t sector_size = 65536; + uint32_t n_sectors = 512; + + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + uint32_t bp_bits = 0b0; + + for (int i = 0; i < 16; i++) { + bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, BULK_ERASE); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, bp_bits); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + spi_ctrl_stop_user(test_data); + + uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; + uint32_t protection_start = n_sectors - num_protected_sectors; + uint32_t protection_end = n_sectors; + + for (int sector = 0; sector < n_sectors; sector++) { + uint32_t addr = sector * sector_size; + + assert_page_mem(test_data, addr, 0xffffffff); + write_page_mem(test_data, addr, make_be32(0xabcdef12)); + + uint32_t expected_value = protection_start <= sector + && sector < protection_end + ? 0xffffffff : 0xabcdef12; + + assert_page_mem(test_data, addr, expected_value); + } + } + + flash_reset(test_data); +} + +void aspeed_smc_test_write_block_protect_bottom_bit(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t sector_size = 65536; + uint32_t n_sectors = 512; + + spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + /* top bottom bit is enabled */ + uint32_t bp_bits = 0b00100 << 3; + + for (int i = 0; i < 16; i++) { + bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, BULK_ERASE); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, WRSR); + flash_writeb(test_data, 0, bp_bits); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + spi_ctrl_stop_user(test_data); + + uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; + uint32_t protection_start = 0; + uint32_t protection_end = num_protected_sectors; + + for (int sector = 0; sector < n_sectors; sector++) { + uint32_t addr = sector * sector_size; + + assert_page_mem(test_data, addr, 0xffffffff); + write_page_mem(test_data, addr, make_be32(0xabcdef12)); + + uint32_t expected_value = protection_start <= sector + && sector < protection_end + ? 0xffffffff : 0xabcdef12; + + assert_page_mem(test_data, addr, expected_value); + } + } + + flash_reset(test_data); +} + +void aspeed_smc_test_write_page_qpi(const void *data) +{ + const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; + uint32_t my_page_addr = test_data->page_addr; + uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; + uint32_t page[FLASH_PAGE_SIZE / 4]; + uint32_t page_pattern[] = { + 0xebd8c134, 0x5da196bc, 0xae15e729, 0x5085ccdf + }; + int i; + + spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); + + spi_ctrl_start_user(test_data); + flash_writeb(test_data, 0, EN_4BYTE_ADDR); + flash_writeb(test_data, 0, WREN); + flash_writeb(test_data, 0, PP); + flash_writel(test_data, 0, make_be32(my_page_addr)); + + /* Set QPI mode */ + spi_ctrl_set_io_mode(test_data, CTRL_IO_QUAD_IO); + + /* Fill the page pattern */ + for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { + flash_writel(test_data, 0, make_be32(page_pattern[i])); + } + + /* Fill the page with its own addresses */ + for (; i < FLASH_PAGE_SIZE / 4; i++) { + flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); + } + + /* Restore io mode */ + spi_ctrl_set_io_mode(test_data, 0); + spi_ctrl_stop_user(test_data); + + /* Check what was written */ + read_page(test_data, my_page_addr, page); + for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { + g_assert_cmphex(page[i], ==, page_pattern[i]); + } + for (; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, my_page_addr + i * 4); + } + + /* Check some other page. It should be full of 0xff */ + read_page(test_data, some_page_addr, page); + for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], ==, 0xffffffff); + } + + flash_reset(test_data); +} + diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -XXX,XX +XXX,XX @@ #include "qemu/bswap.h" #include "libqtest-single.h" #include "qemu/bitops.h" +#include "aspeed-smc-utils.h" -/* - * ASPEED SPI Controller registers - */ -#define R_CONF 0x00 -#define CONF_ENABLE_W0 16 -#define R_CE_CTRL 0x04 -#define CRTL_EXTENDED0 0 /* 32 bit addressing for SPI */ -#define R_CTRL0 0x10 -#define CTRL_IO_QUAD_IO BIT(31) -#define CTRL_CE_STOP_ACTIVE BIT(2) -#define CTRL_READMODE 0x0 -#define CTRL_FREADMODE 0x1 -#define CTRL_WRITEMODE 0x2 -#define CTRL_USERMODE 0x3 -#define SR_WEL BIT(1) - -/* - * Flash commands - */ -enum { - JEDEC_READ = 0x9f, - RDSR = 0x5, - WRDI = 0x4, - BULK_ERASE = 0xc7, - READ = 0x03, - PP = 0x02, - WRSR = 0x1, - WREN = 0x6, - SRWD = 0x80, - RESET_ENABLE = 0x66, - RESET_MEMORY = 0x99, - EN_4BYTE_ADDR = 0xB7, - ERASE_SECTOR = 0xd8, -}; - -#define CTRL_IO_MODE_MASK (BIT(31) | BIT(30) | BIT(29) | BIT(28)) -#define FLASH_PAGE_SIZE 256 - -typedef struct TestData { - QTestState *s; - uint64_t spi_base; - uint64_t flash_base; - uint32_t jedec_id; - char *tmp_path; - uint8_t cs; - const char *node; - uint32_t page_addr; -} TestData; - -/* - * Use an explicit bswap for the values read/wrote to the flash region - * as they are BE and the Aspeed CPU is LE. - */ -static inline uint32_t make_be32(uint32_t data) -{ - return bswap32(data); -} - -static inline void spi_writel(const TestData *data, uint64_t offset, - uint32_t value) -{ - qtest_writel(data->s, data->spi_base + offset, value); -} - -static inline uint32_t spi_readl(const TestData *data, uint64_t offset) -{ - return qtest_readl(data->s, data->spi_base + offset); -} - -static inline void flash_writeb(const TestData *data, uint64_t offset, - uint8_t value) -{ - qtest_writeb(data->s, data->flash_base + offset, value); -} - -static inline void flash_writel(const TestData *data, uint64_t offset, - uint32_t value) -{ - qtest_writel(data->s, data->flash_base + offset, value); -} - -static inline uint8_t flash_readb(const TestData *data, uint64_t offset) -{ - return qtest_readb(data->s, data->flash_base + offset); -} - -static inline uint32_t flash_readl(const TestData *data, uint64_t offset) -{ - return qtest_readl(data->s, data->flash_base + offset); -} - -static void spi_conf(const TestData *data, uint32_t value) -{ - uint32_t conf = spi_readl(data, R_CONF); - - conf |= value; - spi_writel(data, R_CONF, conf); -} - -static void spi_conf_remove(const TestData *data, uint32_t value) -{ - uint32_t conf = spi_readl(data, R_CONF); - - conf &= ~value; - spi_writel(data, R_CONF, conf); -} - -static void spi_ce_ctrl(const TestData *data, uint32_t value) -{ - uint32_t conf = spi_readl(data, R_CE_CTRL); - - conf |= value; - spi_writel(data, R_CE_CTRL, conf); -} - -static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd) -{ - uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; - uint32_t ctrl = spi_readl(data, ctrl_reg); - ctrl &= ~(CTRL_USERMODE | 0xff << 16); - ctrl |= mode | (cmd << 16); - spi_writel(data, ctrl_reg, ctrl); -} - -static void spi_ctrl_start_user(const TestData *data) -{ - uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; - uint32_t ctrl = spi_readl(data, ctrl_reg); - - ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; - spi_writel(data, ctrl_reg, ctrl); - - ctrl &= ~CTRL_CE_STOP_ACTIVE; - spi_writel(data, ctrl_reg, ctrl); -} - -static void spi_ctrl_stop_user(const TestData *data) -{ - uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; - uint32_t ctrl = spi_readl(data, ctrl_reg); - - ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; - spi_writel(data, ctrl_reg, ctrl); -} - -static void spi_ctrl_set_io_mode(const TestData *data, uint32_t value) -{ - uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; - uint32_t ctrl = spi_readl(data, ctrl_reg); - uint32_t mode; - - mode = value & CTRL_IO_MODE_MASK; - ctrl &= ~CTRL_IO_MODE_MASK; - ctrl |= mode; - spi_writel(data, ctrl_reg, ctrl); -} - -static void flash_reset(const TestData *data) -{ - spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs)); - - spi_ctrl_start_user(data); - flash_writeb(data, 0, RESET_ENABLE); - flash_writeb(data, 0, RESET_MEMORY); - flash_writeb(data, 0, WREN); - flash_writeb(data, 0, BULK_ERASE); - flash_writeb(data, 0, WRDI); - spi_ctrl_stop_user(data); - - spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs)); -} - -static void test_read_jedec(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t jedec = 0x0; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, JEDEC_READ); - jedec |= flash_readb(test_data, 0) << 16; - jedec |= flash_readb(test_data, 0) << 8; - jedec |= flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - - flash_reset(test_data); - - g_assert_cmphex(jedec, ==, test_data->jedec_id); -} - -static void read_page(const TestData *data, uint32_t addr, uint32_t *page) -{ - int i; - - spi_ctrl_start_user(data); - - flash_writeb(data, 0, EN_4BYTE_ADDR); - flash_writeb(data, 0, READ); - flash_writel(data, 0, make_be32(addr)); - - /* Continuous read are supported */ - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - page[i] = make_be32(flash_readl(data, 0)); - } - spi_ctrl_stop_user(data); -} - -static void read_page_mem(const TestData *data, uint32_t addr, uint32_t *page) -{ - int i; - - /* move out USER mode to use direct reads from the AHB bus */ - spi_ctrl_setmode(data, CTRL_READMODE, READ); - - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - page[i] = make_be32(flash_readl(data, addr + i * 4)); - } -} - -static void write_page_mem(const TestData *data, uint32_t addr, - uint32_t write_value) -{ - spi_ctrl_setmode(data, CTRL_WRITEMODE, PP); - - for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(data, addr + i * 4, write_value); - } -} - -static void assert_page_mem(const TestData *data, uint32_t addr, - uint32_t expected_value) -{ - uint32_t page[FLASH_PAGE_SIZE / 4]; - read_page_mem(data, addr, page); - for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, expected_value); - } -} - -static void test_erase_sector(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t some_page_addr = test_data->page_addr; - uint32_t page[FLASH_PAGE_SIZE / 4]; - int i; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - /* - * Previous page should be full of 0xffs after backend is - * initialized - */ - read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, PP); - flash_writel(test_data, 0, make_be32(some_page_addr)); - - /* Fill the page with its own addresses */ - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); - } - spi_ctrl_stop_user(test_data); - - /* Check the page is correctly written */ - read_page(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, some_page_addr + i * 4); - } - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, ERASE_SECTOR); - flash_writel(test_data, 0, make_be32(some_page_addr)); - spi_ctrl_stop_user(test_data); - - /* Check the page is erased */ - read_page(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - flash_reset(test_data); -} - -static void test_erase_all(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t some_page_addr = test_data->page_addr; - uint32_t page[FLASH_PAGE_SIZE / 4]; - int i; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - /* - * Previous page should be full of 0xffs after backend is - * initialized - */ - read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, PP); - flash_writel(test_data, 0, make_be32(some_page_addr)); - - /* Fill the page with its own addresses */ - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); - } - spi_ctrl_stop_user(test_data); - - /* Check the page is correctly written */ - read_page(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, some_page_addr + i * 4); - } - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, BULK_ERASE); - spi_ctrl_stop_user(test_data); - - /* Check the page is erased */ - read_page(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - flash_reset(test_data); -} - -static void test_write_page(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = test_data->page_addr; - uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; - uint32_t page[FLASH_PAGE_SIZE / 4]; - int i; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, PP); - flash_writel(test_data, 0, make_be32(my_page_addr)); - - /* Fill the page with its own addresses */ - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); - } - spi_ctrl_stop_user(test_data); - - /* Check what was written */ - read_page(test_data, my_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, my_page_addr + i * 4); - } - - /* Check some other page. It should be full of 0xff */ - read_page(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - flash_reset(test_data); -} - -static void test_read_page_mem(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = test_data->page_addr; - uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; - uint32_t page[FLASH_PAGE_SIZE / 4]; - int i; - - /* - * Enable 4BYTE mode for controller. - */ - spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); - - /* Enable 4BYTE mode for flash. */ - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, PP); - flash_writel(test_data, 0, make_be32(my_page_addr)); - - /* Fill the page with its own addresses */ - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); - } - spi_ctrl_stop_user(test_data); - spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - /* Check what was written */ - read_page_mem(test_data, my_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, my_page_addr + i * 4); - } - - /* Check some other page. It should be full of 0xff */ - read_page_mem(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - flash_reset(test_data); -} - -static void test_write_page_mem(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = test_data->page_addr; - uint32_t page[FLASH_PAGE_SIZE / 4]; - int i; - - /* - * Enable 4BYTE mode for controller. - */ - spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); - - /* Enable 4BYTE mode for flash. */ - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - spi_ctrl_stop_user(test_data); - - /* move out USER mode to use direct writes to the AHB bus */ - spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP); - - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(test_data, my_page_addr + i * 4, - make_be32(my_page_addr + i * 4)); - } - - /* Check what was written */ - read_page_mem(test_data, my_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, my_page_addr + i * 4); - } - - flash_reset(test_data); -} - -static void test_read_status_reg(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint8_t r; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - - g_assert_cmphex(r & SR_WEL, ==, 0); - g_assert(!qtest_qom_get_bool - (test_data->s, test_data->node, "write-enable")); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - - g_assert_cmphex(r & SR_WEL, ==, SR_WEL); - g_assert(qtest_qom_get_bool - (test_data->s, test_data->node, "write-enable")); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WRDI); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - - g_assert_cmphex(r & SR_WEL, ==, 0); - g_assert(!qtest_qom_get_bool - (test_data->s, test_data->node, "write-enable")); - - flash_reset(test_data); -} - -static void test_status_reg_write_protection(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint8_t r; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - /* default case: WP# is high and SRWD is low -> status register writable */ - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - /* test ability to write SRWD */ - flash_writeb(test_data, 0, WRSR); - flash_writeb(test_data, 0, SRWD); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - g_assert_cmphex(r & SRWD, ==, SRWD); - - /* WP# high and SRWD high -> status register writable */ - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - /* test ability to write SRWD */ - flash_writeb(test_data, 0, WRSR); - flash_writeb(test_data, 0, 0); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - g_assert_cmphex(r & SRWD, ==, 0); - - /* WP# low and SRWD low -> status register writable */ - qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0); - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - /* test ability to write SRWD */ - flash_writeb(test_data, 0, WRSR); - flash_writeb(test_data, 0, SRWD); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - g_assert_cmphex(r & SRWD, ==, SRWD); - - /* WP# low and SRWD high -> status register NOT writable */ - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0 , WREN); - /* test ability to write SRWD */ - flash_writeb(test_data, 0, WRSR); - flash_writeb(test_data, 0, 0); - flash_writeb(test_data, 0, RDSR); - r = flash_readb(test_data, 0); - spi_ctrl_stop_user(test_data); - /* write is not successful */ - g_assert_cmphex(r & SRWD, ==, SRWD); - - qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1); - flash_reset(test_data); -} - -static void test_write_block_protect(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t sector_size = 65536; - uint32_t n_sectors = 512; - - spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - uint32_t bp_bits = 0b0; - - for (int i = 0; i < 16; i++) { - bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, BULK_ERASE); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, WRSR); - flash_writeb(test_data, 0, bp_bits); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - spi_ctrl_stop_user(test_data); - - uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; - uint32_t protection_start = n_sectors - num_protected_sectors; - uint32_t protection_end = n_sectors; - - for (int sector = 0; sector < n_sectors; sector++) { - uint32_t addr = sector * sector_size; - - assert_page_mem(test_data, addr, 0xffffffff); - write_page_mem(test_data, addr, make_be32(0xabcdef12)); - - uint32_t expected_value = protection_start <= sector - && sector < protection_end - ? 0xffffffff : 0xabcdef12; - - assert_page_mem(test_data, addr, expected_value); - } - } - - flash_reset(test_data); -} - -static void test_write_block_protect_bottom_bit(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t sector_size = 65536; - uint32_t n_sectors = 512; - - spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - /* top bottom bit is enabled */ - uint32_t bp_bits = 0b00100 << 3; - - for (int i = 0; i < 16; i++) { - bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, BULK_ERASE); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, WRSR); - flash_writeb(test_data, 0, bp_bits); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - spi_ctrl_stop_user(test_data); - - uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; - uint32_t protection_start = 0; - uint32_t protection_end = num_protected_sectors; - - for (int sector = 0; sector < n_sectors; sector++) { - uint32_t addr = sector * sector_size; - - assert_page_mem(test_data, addr, 0xffffffff); - write_page_mem(test_data, addr, make_be32(0xabcdef12)); - - uint32_t expected_value = protection_start <= sector - && sector < protection_end - ? 0xffffffff : 0xabcdef12; - - assert_page_mem(test_data, addr, expected_value); - } - } - - flash_reset(test_data); -} - -static void test_write_page_qpi(const void *data) -{ - const TestData *test_data = (const TestData *)data; - uint32_t my_page_addr = test_data->page_addr; - uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; - uint32_t page[FLASH_PAGE_SIZE / 4]; - uint32_t page_pattern[] = { - 0xebd8c134, 0x5da196bc, 0xae15e729, 0x5085ccdf - }; - int i; - - spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); - - spi_ctrl_start_user(test_data); - flash_writeb(test_data, 0, EN_4BYTE_ADDR); - flash_writeb(test_data, 0, WREN); - flash_writeb(test_data, 0, PP); - flash_writel(test_data, 0, make_be32(my_page_addr)); - - /* Set QPI mode */ - spi_ctrl_set_io_mode(test_data, CTRL_IO_QUAD_IO); - - /* Fill the page pattern */ - for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { - flash_writel(test_data, 0, make_be32(page_pattern[i])); - } - - /* Fill the page with its own addresses */ - for (; i < FLASH_PAGE_SIZE / 4; i++) { - flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); - } - - /* Restore io mode */ - spi_ctrl_set_io_mode(test_data, 0); - spi_ctrl_stop_user(test_data); - - /* Check what was written */ - read_page(test_data, my_page_addr, page); - for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { - g_assert_cmphex(page[i], ==, page_pattern[i]); - } - for (; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, my_page_addr + i * 4); - } - - /* Check some other page. It should be full of 0xff */ - read_page(test_data, some_page_addr, page); - for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { - g_assert_cmphex(page[i], ==, 0xffffffff); - } - - flash_reset(test_data); -} - -static void test_palmetto_bmc(TestData *data) +static void test_palmetto_bmc(AspeedSMCTestData *data) { int ret; int fd; @@ -XXX,XX +XXX,XX @@ static void test_palmetto_bmc(TestData *data) /* beyond 16MB */ data->page_addr = 0x14000 * FLASH_PAGE_SIZE; - qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec); - qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector); - qtest_add_data_func("/ast2400/smc/erase_all", data, test_erase_all); - qtest_add_data_func("/ast2400/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast2400/smc/read_jedec", + data, aspeed_smc_test_read_jedec); + qtest_add_data_func("/ast2400/smc/erase_sector", + data, aspeed_smc_test_erase_sector); + qtest_add_data_func("/ast2400/smc/erase_all", + data, aspeed_smc_test_erase_all); + qtest_add_data_func("/ast2400/smc/write_page", + data, aspeed_smc_test_write_page); qtest_add_data_func("/ast2400/smc/read_page_mem", - data, test_read_page_mem); + data, aspeed_smc_test_read_page_mem); qtest_add_data_func("/ast2400/smc/write_page_mem", - data, test_write_page_mem); + data, aspeed_smc_test_write_page_mem); qtest_add_data_func("/ast2400/smc/read_status_reg", - data, test_read_status_reg); + data, aspeed_smc_test_read_status_reg); qtest_add_data_func("/ast2400/smc/status_reg_write_protection", - data, test_status_reg_write_protection); + data, aspeed_smc_test_status_reg_write_protection); qtest_add_data_func("/ast2400/smc/write_block_protect", - data, test_write_block_protect); + data, aspeed_smc_test_write_block_protect); qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit", - data, test_write_block_protect_bottom_bit); + data, aspeed_smc_test_write_block_protect_bottom_bit); } -static void test_ast2500_evb(TestData *data) +static void test_ast2500_evb(AspeedSMCTestData *data) { int ret; int fd; @@ -XXX,XX +XXX,XX @@ static void test_ast2500_evb(TestData *data) /* beyond 16MB */ data->page_addr = 0x14000 * FLASH_PAGE_SIZE; - qtest_add_data_func("/ast2500/smc/read_jedec", data, test_read_jedec); - qtest_add_data_func("/ast2500/smc/erase_sector", data, test_erase_sector); - qtest_add_data_func("/ast2500/smc/erase_all", data, test_erase_all); - qtest_add_data_func("/ast2500/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast2500/smc/read_jedec", + data, aspeed_smc_test_read_jedec); + qtest_add_data_func("/ast2500/smc/erase_sector", + data, aspeed_smc_test_erase_sector); + qtest_add_data_func("/ast2500/smc/erase_all", + data, aspeed_smc_test_erase_all); + qtest_add_data_func("/ast2500/smc/write_page", + data, aspeed_smc_test_write_page); qtest_add_data_func("/ast2500/smc/read_page_mem", - data, test_read_page_mem); + data, aspeed_smc_test_read_page_mem); qtest_add_data_func("/ast2500/smc/write_page_mem", - data, test_write_page_mem); + data, aspeed_smc_test_write_page_mem); qtest_add_data_func("/ast2500/smc/read_status_reg", - data, test_read_status_reg); + data, aspeed_smc_test_read_status_reg); qtest_add_data_func("/ast2500/smc/write_page_qpi", - data, test_write_page_qpi); + data, aspeed_smc_test_write_page_qpi); } -static void test_ast2600_evb(TestData *data) +static void test_ast2600_evb(AspeedSMCTestData *data) { int ret; int fd; @@ -XXX,XX +XXX,XX @@ static void test_ast2600_evb(TestData *data) /* beyond 16MB */ data->page_addr = 0x14000 * FLASH_PAGE_SIZE; - qtest_add_data_func("/ast2600/smc/read_jedec", data, test_read_jedec); - qtest_add_data_func("/ast2600/smc/erase_sector", data, test_erase_sector); - qtest_add_data_func("/ast2600/smc/erase_all", data, test_erase_all); - qtest_add_data_func("/ast2600/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast2600/smc/read_jedec", + data, aspeed_smc_test_read_jedec); + qtest_add_data_func("/ast2600/smc/erase_sector", + data, aspeed_smc_test_erase_sector); + qtest_add_data_func("/ast2600/smc/erase_all", + data, aspeed_smc_test_erase_all); + qtest_add_data_func("/ast2600/smc/write_page", + data, aspeed_smc_test_write_page); qtest_add_data_func("/ast2600/smc/read_page_mem", - data, test_read_page_mem); + data, aspeed_smc_test_read_page_mem); qtest_add_data_func("/ast2600/smc/write_page_mem", - data, test_write_page_mem); + data, aspeed_smc_test_write_page_mem); qtest_add_data_func("/ast2600/smc/read_status_reg", - data, test_read_status_reg); + data, aspeed_smc_test_read_status_reg); qtest_add_data_func("/ast2600/smc/write_page_qpi", - data, test_write_page_qpi); + data, aspeed_smc_test_write_page_qpi); } -static void test_ast1030_evb(TestData *data) +static void test_ast1030_evb(AspeedSMCTestData *data) { int ret; int fd; @@ -XXX,XX +XXX,XX @@ static void test_ast1030_evb(TestData *data) /* beyond 512KB */ data->page_addr = 0x800 * FLASH_PAGE_SIZE; - qtest_add_data_func("/ast1030/smc/read_jedec", data, test_read_jedec); - qtest_add_data_func("/ast1030/smc/erase_sector", data, test_erase_sector); - qtest_add_data_func("/ast1030/smc/erase_all", data, test_erase_all); - qtest_add_data_func("/ast1030/smc/write_page", data, test_write_page); + qtest_add_data_func("/ast1030/smc/read_jedec", + data, aspeed_smc_test_read_jedec); + qtest_add_data_func("/ast1030/smc/erase_sector", + data, aspeed_smc_test_erase_sector); + qtest_add_data_func("/ast1030/smc/erase_all", + data, aspeed_smc_test_erase_all); + qtest_add_data_func("/ast1030/smc/write_page", + data, aspeed_smc_test_write_page); qtest_add_data_func("/ast1030/smc/read_page_mem", - data, test_read_page_mem); + data, aspeed_smc_test_read_page_mem); qtest_add_data_func("/ast1030/smc/write_page_mem", - data, test_write_page_mem); + data, aspeed_smc_test_write_page_mem); qtest_add_data_func("/ast1030/smc/read_status_reg", - data, test_read_status_reg); + data, aspeed_smc_test_read_status_reg); qtest_add_data_func("/ast1030/smc/write_page_qpi", - data, test_write_page_qpi); + data, aspeed_smc_test_write_page_qpi); } int main(int argc, char **argv) { - TestData palmetto_data; - TestData ast2500_evb_data; - TestData ast2600_evb_data; - TestData ast1030_evb_data; + AspeedSMCTestData palmetto_data; + AspeedSMCTestData ast2500_evb_data; + AspeedSMCTestData ast2600_evb_data; + AspeedSMCTestData ast1030_evb_data; int ret; g_test_init(&argc, &argv, NULL); 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 = { 'virtio-net-failover': files('migration-helpers.c'), 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'), + 'aspeed_smc-test': files('aspeed-smc-utils.c', 'aspeed_smc-test.c'), } if vnc.found() -- 2.47.1
From: Jamin Lin <jamin_lin@aspeedtech.com> Add test_ast2700_evb function and reused testcases which are from aspeed_smc-test.c for AST2700 testing. The base address, flash base address and ce index of fmc_cs0 are 0x14000000, 0x100000000 and 0, respectively. The default flash model of fmc_cs0 is "w25q01jvq" whose size is 128MB, so set jedec_id 0xef4021. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/r/20241127091543.1243114-11-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com> --- tests/qtest/ast2700-smc-test.c | 71 ++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 4 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/ast2700-smc-test.c diff --git a/tests/qtest/ast2700-smc-test.c b/tests/qtest/ast2700-smc-test.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/qtest/ast2700-smc-test.c @@ -XXX,XX +XXX,XX @@ +/* + * QTest testcase for the M25P80 Flash using the ASPEED SPI Controller since + * AST2700. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 ASPEED Technology Inc. + */ + +#include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "libqtest-single.h" +#include "qemu/bitops.h" +#include "aspeed-smc-utils.h" + +static void test_ast2700_evb(AspeedSMCTestData *data) +{ + int ret; + int fd; + + fd = g_file_open_tmp("qtest.m25p80.w25q01jvq.XXXXXX", + &data->tmp_path, NULL); + g_assert(fd >= 0); + ret = ftruncate(fd, 128 * 1024 * 1024); + g_assert(ret == 0); + close(fd); + + data->s = qtest_initf("-machine ast2700-evb " + "-drive file=%s,format=raw,if=mtd", + data->tmp_path); + + /* fmc cs0 with w25q01jvq flash */ + data->flash_base = 0x100000000; + data->spi_base = 0x14000000; + data->jedec_id = 0xef4021; + data->cs = 0; + data->node = "/machine/soc/fmc/ssi.0/child[0]"; + /* beyond 64MB */ + data->page_addr = 0x40000 * FLASH_PAGE_SIZE; + + qtest_add_data_func("/ast2700/smc/read_jedec", + data, aspeed_smc_test_read_jedec); + qtest_add_data_func("/ast2700/smc/erase_sector", + data, aspeed_smc_test_erase_sector); + qtest_add_data_func("/ast2700/smc/erase_all", + data, aspeed_smc_test_erase_all); + qtest_add_data_func("/ast2700/smc/write_page", + data, aspeed_smc_test_write_page); + qtest_add_data_func("/ast2700/smc/read_page_mem", + data, aspeed_smc_test_read_page_mem); + qtest_add_data_func("/ast2700/smc/write_page_mem", + data, aspeed_smc_test_write_page_mem); + qtest_add_data_func("/ast2700/smc/read_status_reg", + data, aspeed_smc_test_read_status_reg); + qtest_add_data_func("/ast2700/smc/write_page_qpi", + data, aspeed_smc_test_write_page_qpi); +} + +int main(int argc, char **argv) +{ + AspeedSMCTestData ast2700_evb_data; + int ret; + + g_test_init(&argc, &argv, NULL); + + test_ast2700_evb(&ast2700_evb_data); + ret = g_test_run(); + + qtest_quit(ast2700_evb_data.s); + unlink(ast2700_evb_data.tmp_path); + return ret; +} 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_aspeed = \ 'aspeed_smc-test', 'aspeed_gpio-test'] qtests_aspeed64 = \ - ['ast2700-gpio-test'] + ['ast2700-gpio-test', + 'ast2700-smc-test'] qtests_stm32l4x5 = \ ['stm32l4x5_exti-test', @@ -XXX,XX +XXX,XX @@ qtests = { 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'), 'aspeed_smc-test': files('aspeed-smc-utils.c', 'aspeed_smc-test.c'), + 'ast2700-smc-test': files('aspeed-smc-utils.c', 'ast2700-smc-test.c'), } if vnc.found() -- 2.47.1
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