mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
aspeed queue:
* Removed tacoma-bmc machine * Added support for SDHCI on AST2700 SoC * Improved functional tests * Extended SMC qtest to all Aspeed SoCs -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmdZMTQACgkQUaNDx8/7 7KE9dhAAw9xNULQ7KG9udSNqYPRGP2w8teO4b9YOfRlJlSJuCInbeLjg1Hw3b/bZ rEtnwjl18f+mpmHzvasQthN4vUtcR1UwrW6SvmAjAQV8iNw059ugxWdxV9VR72hc 1AlzsW/Hea8s448INTEUvEjosYeLRRxZQyiJt9Lf5IkU/6yLj98YssKKvRqPpkxP Ens7PapgGPqA7cPnPYofRn2WINtHNnvX2FGlWTnCoPVp85VJzjJVFcK14kBych2U fmNZAY7pPTBkwwqR/qoPOyqBBCLeu3Jimk7hR8VbBbfwMT/Zg3RO7TJfwJex9TEs PIViRuM8krEppL6fmJlpDTatU2t0ffQY1SSVRWCDxJDDRpQN7iDei3vuzXOfLVAe lLSXS5Q1f+sO6JzbqkYSufh5V7zR5De8rk4j5WszC3cko2godTZm3qyqUxEaQGcx kjG58R+a7qLLeNMcPed5qgGjYeCPmhHay80E3faXKOezktSIM5z5b822ZPZfw3oG gTddZ4hdTg0BxtEjSv19qqnJW0Hs+NZJQuyu34QS82dZqPeZ22dmfULtf9uQ/3oV A/jKfTncl3sW1otfLABj6/RPVH/Sr7IM70XBjlc1+p9Ci7Es17er8umFOAyek9WL pE/Lq23MnAPBUsPKOJRdDFClTGwdnemXJoymwY/NZS4SgV3GcD8= =BiCq -----END PGP SIGNATURE----- Merge tag 'pull-aspeed-20241211' of https://github.com/legoater/qemu into staging aspeed queue: * Removed tacoma-bmc machine * Added support for SDHCI on AST2700 SoC * Improved functional tests * Extended SMC qtest to all Aspeed SoCs # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmdZMTQACgkQUaNDx8/7 # 7KE9dhAAw9xNULQ7KG9udSNqYPRGP2w8teO4b9YOfRlJlSJuCInbeLjg1Hw3b/bZ # rEtnwjl18f+mpmHzvasQthN4vUtcR1UwrW6SvmAjAQV8iNw059ugxWdxV9VR72hc # 1AlzsW/Hea8s448INTEUvEjosYeLRRxZQyiJt9Lf5IkU/6yLj98YssKKvRqPpkxP # Ens7PapgGPqA7cPnPYofRn2WINtHNnvX2FGlWTnCoPVp85VJzjJVFcK14kBych2U # fmNZAY7pPTBkwwqR/qoPOyqBBCLeu3Jimk7hR8VbBbfwMT/Zg3RO7TJfwJex9TEs # PIViRuM8krEppL6fmJlpDTatU2t0ffQY1SSVRWCDxJDDRpQN7iDei3vuzXOfLVAe # lLSXS5Q1f+sO6JzbqkYSufh5V7zR5De8rk4j5WszC3cko2godTZm3qyqUxEaQGcx # kjG58R+a7qLLeNMcPed5qgGjYeCPmhHay80E3faXKOezktSIM5z5b822ZPZfw3oG # gTddZ4hdTg0BxtEjSv19qqnJW0Hs+NZJQuyu34QS82dZqPeZ22dmfULtf9uQ/3oV # A/jKfTncl3sW1otfLABj6/RPVH/Sr7IM70XBjlc1+p9Ci7Es17er8umFOAyek9WL # pE/Lq23MnAPBUsPKOJRdDFClTGwdnemXJoymwY/NZS4SgV3GcD8= # =BiCq # -----END PGP SIGNATURE----- # gpg: Signature made Wed 11 Dec 2024 06:29:08 GMT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [full] # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-aspeed-20241211' of https://github.com/legoater/qemu: (24 commits) test/qtest/ast2700-smc-test: Support to test AST2700 test/qtest: Introduce a new aspeed-smc-utils.c to place common testcases test/qtest/aspeed_smc-test: Support write page command with QPI mode test/qtest/aspeed_smc-test: Support to test AST1030 test/qtest/aspeed_smc-test: Support to test AST2600 test/qtest/aspeed_smc-test: Support to test AST2500 test/qtest/aspeed_smc-test: Introducing a "page_addr" data field test/qtest/aspeed_smc-test: Support to test all CE pins test/qtest/aspeed_smc-test: Introduce a new TestData to test different BMC SOCs test/qtest/aspeed_smc-test: Move testcases to test_palmetto_bmc function tests/functional: Move debian boot test from avocado tests/functional: Introduce a specific test for rainier-bmc machine tests/functional: Introduce a specific test for ast2600 SoC tests/functional: Introduce a specific test for ast2500 SoC tests/functional: Introduce a specific test for romulus-bmc machine tests/functional: Introduce a specific test for palmetto-bmc machine tests/functional: Introduce a specific test for ast1030 SoC aspeed/soc: Support eMMC for AST2700 aspeed/soc: Support SDHCI for AST2700 hw/sd/aspeed_sdhci: Add AST2700 Support ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a5ba0a7e4e
24 changed files with 1623 additions and 1025 deletions
|
@ -263,14 +263,6 @@ 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)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
|
|
@ -1019,6 +1019,16 @@ 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)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ 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
|
||||
|
|
|
@ -185,10 +185,6 @@ 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
|
||||
|
@ -1425,26 +1421,6 @@ 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);
|
||||
|
@ -1766,10 +1742,6 @@ 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,
|
||||
|
|
|
@ -224,7 +224,8 @@ 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);
|
||||
|
||||
|
|
|
@ -236,8 +236,8 @@ 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);
|
||||
|
||||
|
@ -247,8 +247,7 @@ 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);
|
||||
|
||||
|
@ -541,7 +540,8 @@ 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));
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ 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
|
||||
|
@ -113,6 +114,7 @@ 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 */
|
||||
|
@ -158,6 +160,7 @@ 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,
|
||||
};
|
||||
|
||||
|
@ -380,6 +383,20 @@ 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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -681,6 +698,24 @@ 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));
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -87,10 +87,12 @@ 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,
|
||||
|
@ -146,6 +148,7 @@ 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,
|
||||
|
@ -165,7 +168,7 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -216,12 +219,70 @@ 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 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,
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.name = TYPE_ASPEED_2700_SDHCI,
|
||||
.parent = TYPE_ASPEED_SDHCI,
|
||||
.class_init = aspeed_2700_sdhci_class_init,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -13,9 +13,12 @@
|
|||
#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"
|
||||
#define TYPE_ASPEED_2700_SDHCI TYPE_ASPEED_SDHCI "-ast2700"
|
||||
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
|
||||
|
@ -32,4 +35,10 @@ struct AspeedSDHCIState {
|
|||
uint32_t regs[ASPEED_SDHCI_NUM_REGS];
|
||||
};
|
||||
|
||||
struct AspeedSDHCIClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint64_t capareg;
|
||||
};
|
||||
|
||||
#endif /* ASPEED_SDHCI_H */
|
||||
|
|
|
@ -470,29 +470,3 @@ class BootLinuxConsole(LinuxKernelTest):
|
|||
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")
|
||||
|
||||
|
|
56
tests/functional/aspeed.py
Normal file
56
tests/functional/aspeed.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Test class to boot aspeed machines
|
||||
#
|
||||
# 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):
|
||||
|
||||
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")
|
||||
|
||||
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 ...')
|
|
@ -18,7 +18,11 @@ test_timeouts = {
|
|||
'aarch64_tuxrun' : 240,
|
||||
'aarch64_virt' : 720,
|
||||
'acpi_bits' : 420,
|
||||
'arm_aspeed' : 600,
|
||||
'arm_aspeed_palmetto' : 120,
|
||||
'arm_aspeed_romulus' : 120,
|
||||
'arm_aspeed_ast2500' : 480,
|
||||
'arm_aspeed_ast2600' : 720,
|
||||
'arm_aspeed_rainier' : 240,
|
||||
'arm_bpim2u' : 500,
|
||||
'arm_collie' : 180,
|
||||
'arm_orangepi' : 540,
|
||||
|
@ -65,7 +69,12 @@ 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',
|
||||
|
|
|
@ -1,351 +0,0 @@
|
|||
#!/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
|
||||
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
|
||||
|
||||
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):
|
||||
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_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'),
|
||||
'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()
|
||||
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_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'),
|
||||
'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_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')
|
||||
|
||||
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(
|
||||
('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/'
|
||||
'mmc-p10bmc-20240617.qcow2'),
|
||||
'd523fb478d2b84d5adc5658d08502bc64b1486955683814f89c6137518acd90b')
|
||||
|
||||
def test_arm_aspeed_emmc_boot(self):
|
||||
self.set_machine('rainier-bmc')
|
||||
self.require_netdev('user')
|
||||
|
||||
image_path = self.ASSET_RAINIER_EMMC.fetch()
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-drive',
|
||||
'file=' + image_path + ',if=sd,id=sd2,index=2',
|
||||
'-net', 'nic', '-net', 'user', '-snapshot')
|
||||
self.vm.launch()
|
||||
|
||||
self.wait_for_console_pattern('U-Boot SPL 2019.04')
|
||||
self.wait_for_console_pattern('Trying to boot from MMC1')
|
||||
self.wait_for_console_pattern('U-Boot 2019.04')
|
||||
self.wait_for_console_pattern('eMMC 2nd Boot')
|
||||
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 0xf00')
|
||||
self.wait_for_console_pattern('mmcblk0: p1 p2 p3 p4 p5 p6 p7')
|
||||
self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise')
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
81
tests/functional/test_arm_aspeed_ast1030.py
Normal file
81
tests/functional/test_arm_aspeed_ast1030.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
#!/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()
|
59
tests/functional/test_arm_aspeed_ast2500.py
Normal file
59
tests/functional/test_arm_aspeed_ast2500.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
#!/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()
|
143
tests/functional/test_arm_aspeed_ast2600.py
Normal file
143
tests/functional/test_arm_aspeed_ast2600.py
Normal file
|
@ -0,0 +1,143 @@
|
|||
#!/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()
|
24
tests/functional/test_arm_aspeed_palmetto.py
Normal file
24
tests/functional/test_arm_aspeed_palmetto.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
#!/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()
|
64
tests/functional/test_arm_aspeed_rainier.py
Normal file
64
tests/functional/test_arm_aspeed_rainier.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/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 RainierMachine(AspeedTest):
|
||||
|
||||
ASSET_RAINIER_EMMC = Asset(
|
||||
('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/'
|
||||
'mmc-p10bmc-20240617.qcow2'),
|
||||
'd523fb478d2b84d5adc5658d08502bc64b1486955683814f89c6137518acd90b')
|
||||
|
||||
def test_arm_aspeed_emmc_boot(self):
|
||||
self.set_machine('rainier-bmc')
|
||||
self.require_netdev('user')
|
||||
|
||||
image_path = self.ASSET_RAINIER_EMMC.fetch()
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-drive',
|
||||
'file=' + image_path + ',if=sd,id=sd2,index=2',
|
||||
'-net', 'nic', '-net', 'user', '-snapshot')
|
||||
self.vm.launch()
|
||||
|
||||
self.wait_for_console_pattern('U-Boot SPL 2019.04')
|
||||
self.wait_for_console_pattern('Trying to boot from MMC1')
|
||||
self.wait_for_console_pattern('U-Boot 2019.04')
|
||||
self.wait_for_console_pattern('eMMC 2nd Boot')
|
||||
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 0xf00')
|
||||
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()
|
24
tests/functional/test_arm_aspeed_romulus.py
Normal file
24
tests/functional/test_arm_aspeed_romulus.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
#!/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()
|
686
tests/qtest/aspeed-smc-utils.c
Normal file
686
tests/qtest/aspeed-smc-utils.c
Normal file
|
@ -0,0 +1,686 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
|
95
tests/qtest/aspeed-smc-utils.h
Normal file
95
tests/qtest/aspeed-smc-utils.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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 */
|
|
@ -27,625 +27,206 @@
|
|||
#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 (1 << 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_READMODE 0x0
|
||||
#define CTRL_FREADMODE 0x1
|
||||
#define CTRL_WRITEMODE 0x2
|
||||
#define CTRL_USERMODE 0x3
|
||||
#define SR_WEL BIT(1)
|
||||
|
||||
#define ASPEED_FMC_BASE 0x1E620000
|
||||
#define ASPEED_FLASH_BASE 0x20000000
|
||||
|
||||
/*
|
||||
* 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 FLASH_JEDEC 0x20ba19 /* n25q256a */
|
||||
#define FLASH_SIZE (32 * 1024 * 1024)
|
||||
|
||||
#define FLASH_PAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* 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)
|
||||
static void test_palmetto_bmc(AspeedSMCTestData *data)
|
||||
{
|
||||
return bswap32(data);
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
fd = g_file_open_tmp("qtest.m25p80.n25q256a.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("-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;
|
||||
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, 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, aspeed_smc_test_read_page_mem);
|
||||
qtest_add_data_func("/ast2400/smc/write_page_mem",
|
||||
data, aspeed_smc_test_write_page_mem);
|
||||
qtest_add_data_func("/ast2400/smc/read_status_reg",
|
||||
data, aspeed_smc_test_read_status_reg);
|
||||
qtest_add_data_func("/ast2400/smc/status_reg_write_protection",
|
||||
data, aspeed_smc_test_status_reg_write_protection);
|
||||
qtest_add_data_func("/ast2400/smc/write_block_protect",
|
||||
data, aspeed_smc_test_write_block_protect);
|
||||
qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit",
|
||||
data, aspeed_smc_test_write_block_protect_bottom_bit);
|
||||
}
|
||||
|
||||
static void spi_conf(uint32_t value)
|
||||
static void test_ast2500_evb(AspeedSMCTestData *data)
|
||||
{
|
||||
uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF);
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
conf |= value;
|
||||
writel(ASPEED_FMC_BASE + R_CONF, conf);
|
||||
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, 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, aspeed_smc_test_read_page_mem);
|
||||
qtest_add_data_func("/ast2500/smc/write_page_mem",
|
||||
data, aspeed_smc_test_write_page_mem);
|
||||
qtest_add_data_func("/ast2500/smc/read_status_reg",
|
||||
data, aspeed_smc_test_read_status_reg);
|
||||
qtest_add_data_func("/ast2500/smc/write_page_qpi",
|
||||
data, aspeed_smc_test_write_page_qpi);
|
||||
}
|
||||
|
||||
static void spi_conf_remove(uint32_t value)
|
||||
static void test_ast2600_evb(AspeedSMCTestData *data)
|
||||
{
|
||||
uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF);
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
conf &= ~value;
|
||||
writel(ASPEED_FMC_BASE + R_CONF, conf);
|
||||
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, 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, aspeed_smc_test_read_page_mem);
|
||||
qtest_add_data_func("/ast2600/smc/write_page_mem",
|
||||
data, aspeed_smc_test_write_page_mem);
|
||||
qtest_add_data_func("/ast2600/smc/read_status_reg",
|
||||
data, aspeed_smc_test_read_status_reg);
|
||||
qtest_add_data_func("/ast2600/smc/write_page_qpi",
|
||||
data, aspeed_smc_test_write_page_qpi);
|
||||
}
|
||||
|
||||
static void spi_ce_ctrl(uint32_t value)
|
||||
static void test_ast1030_evb(AspeedSMCTestData *data)
|
||||
{
|
||||
uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL);
|
||||
|
||||
conf |= value;
|
||||
writel(ASPEED_FMC_BASE + R_CE_CTRL, conf);
|
||||
}
|
||||
|
||||
static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd)
|
||||
{
|
||||
uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
|
||||
ctrl &= ~(CTRL_USERMODE | 0xff << 16);
|
||||
ctrl |= mode | (cmd << 16);
|
||||
writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
|
||||
}
|
||||
|
||||
static void spi_ctrl_start_user(void)
|
||||
{
|
||||
uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
|
||||
|
||||
ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
|
||||
writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
|
||||
|
||||
ctrl &= ~CTRL_CE_STOP_ACTIVE;
|
||||
writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
|
||||
}
|
||||
|
||||
static void spi_ctrl_stop_user(void)
|
||||
{
|
||||
uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
|
||||
|
||||
ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
|
||||
writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
|
||||
}
|
||||
|
||||
static void flash_reset(void)
|
||||
{
|
||||
spi_conf(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_conf_remove(CONF_ENABLE_W0);
|
||||
}
|
||||
|
||||
static void test_read_jedec(void)
|
||||
{
|
||||
uint32_t jedec = 0x0;
|
||||
|
||||
spi_conf(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();
|
||||
|
||||
flash_reset();
|
||||
|
||||
g_assert_cmphex(jedec, ==, FLASH_JEDEC);
|
||||
}
|
||||
|
||||
static void read_page(uint32_t addr, uint32_t *page)
|
||||
{
|
||||
int i;
|
||||
|
||||
spi_ctrl_start_user();
|
||||
|
||||
writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
|
||||
writeb(ASPEED_FLASH_BASE, READ);
|
||||
writel(ASPEED_FLASH_BASE, make_be32(addr));
|
||||
|
||||
/* Continuous read are supported */
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
page[i] = make_be32(readl(ASPEED_FLASH_BASE));
|
||||
}
|
||||
spi_ctrl_stop_user();
|
||||
}
|
||||
|
||||
static void read_page_mem(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);
|
||||
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
static void write_page_mem(uint32_t addr, uint32_t write_value)
|
||||
{
|
||||
spi_ctrl_setmode(CTRL_WRITEMODE, PP);
|
||||
|
||||
for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
writel(ASPEED_FLASH_BASE + addr + i * 4, write_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void assert_page_mem(uint32_t addr, uint32_t expected_value)
|
||||
{
|
||||
uint32_t page[FLASH_PAGE_SIZE / 4];
|
||||
read_page_mem(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)
|
||||
{
|
||||
uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE;
|
||||
uint32_t page[FLASH_PAGE_SIZE / 4];
|
||||
int i;
|
||||
|
||||
spi_conf(CONF_ENABLE_W0);
|
||||
|
||||
/*
|
||||
* Previous page should be full of 0xffs after backend is
|
||||
* initialized
|
||||
*/
|
||||
read_page(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));
|
||||
|
||||
/* 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));
|
||||
}
|
||||
spi_ctrl_stop_user();
|
||||
|
||||
/* Check the page is correctly written */
|
||||
read_page(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();
|
||||
|
||||
/* Check the page is erased */
|
||||
read_page(some_page_addr, page);
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
g_assert_cmphex(page[i], ==, 0xffffffff);
|
||||
}
|
||||
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_erase_all(void)
|
||||
{
|
||||
uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
|
||||
uint32_t page[FLASH_PAGE_SIZE / 4];
|
||||
int i;
|
||||
|
||||
spi_conf(CONF_ENABLE_W0);
|
||||
|
||||
/*
|
||||
* Previous page should be full of 0xffs after backend is
|
||||
* initialized
|
||||
*/
|
||||
read_page(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));
|
||||
|
||||
/* 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));
|
||||
}
|
||||
spi_ctrl_stop_user();
|
||||
|
||||
/* Check the page is correctly written */
|
||||
read_page(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();
|
||||
|
||||
/* Check the page is erased */
|
||||
read_page(some_page_addr, page);
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
g_assert_cmphex(page[i], ==, 0xffffffff);
|
||||
}
|
||||
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_write_page(void)
|
||||
{
|
||||
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_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));
|
||||
|
||||
/* 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));
|
||||
}
|
||||
spi_ctrl_stop_user();
|
||||
|
||||
/* Check what was written */
|
||||
read_page(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);
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
g_assert_cmphex(page[i], ==, 0xffffffff);
|
||||
}
|
||||
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_read_page_mem(void)
|
||||
{
|
||||
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;
|
||||
|
||||
/*
|
||||
* Enable 4BYTE mode for controller. This is should be strapped by
|
||||
* HW for CE0 anyhow.
|
||||
*/
|
||||
spi_ce_ctrl(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));
|
||||
|
||||
/* 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));
|
||||
}
|
||||
spi_ctrl_stop_user();
|
||||
spi_conf_remove(CONF_ENABLE_W0);
|
||||
|
||||
/* Check what was written */
|
||||
read_page_mem(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);
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
g_assert_cmphex(page[i], ==, 0xffffffff);
|
||||
}
|
||||
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_write_page_mem(void)
|
||||
{
|
||||
uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE;
|
||||
uint32_t page[FLASH_PAGE_SIZE / 4];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Enable 4BYTE mode for controller. This is should be strapped by
|
||||
* HW for CE0 anyhow.
|
||||
*/
|
||||
spi_ce_ctrl(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();
|
||||
|
||||
/* move out USER mode to use direct writes to the AHB bus */
|
||||
spi_ctrl_setmode(CTRL_WRITEMODE, PP);
|
||||
|
||||
for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
|
||||
writel(ASPEED_FLASH_BASE + my_page_addr + i * 4,
|
||||
make_be32(my_page_addr + i * 4));
|
||||
}
|
||||
|
||||
/* Check what was written */
|
||||
read_page_mem(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();
|
||||
}
|
||||
|
||||
static void test_read_status_reg(void)
|
||||
{
|
||||
uint8_t r;
|
||||
|
||||
spi_conf(CONF_ENABLE_W0);
|
||||
|
||||
spi_ctrl_start_user();
|
||||
writeb(ASPEED_FLASH_BASE, RDSR);
|
||||
r = readb(ASPEED_FLASH_BASE);
|
||||
spi_ctrl_stop_user();
|
||||
|
||||
g_assert_cmphex(r & SR_WEL, ==, 0);
|
||||
g_assert(!qtest_qom_get_bool
|
||||
(global_qtest, "/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();
|
||||
|
||||
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"));
|
||||
|
||||
spi_ctrl_start_user();
|
||||
writeb(ASPEED_FLASH_BASE, WRDI);
|
||||
writeb(ASPEED_FLASH_BASE, RDSR);
|
||||
r = readb(ASPEED_FLASH_BASE);
|
||||
spi_ctrl_stop_user();
|
||||
|
||||
g_assert_cmphex(r & SR_WEL, ==, 0);
|
||||
g_assert(!qtest_qom_get_bool
|
||||
(global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
|
||||
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_status_reg_write_protection(void)
|
||||
{
|
||||
uint8_t r;
|
||||
|
||||
spi_conf(CONF_ENABLE_W0);
|
||||
|
||||
/* default case: WP# is high and SRWD is low -> status register writable */
|
||||
spi_ctrl_start_user();
|
||||
writeb(ASPEED_FLASH_BASE, 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();
|
||||
g_assert_cmphex(r & SRWD, ==, SRWD);
|
||||
|
||||
/* WP# high and SRWD high -> status register writable */
|
||||
spi_ctrl_start_user();
|
||||
writeb(ASPEED_FLASH_BASE, 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();
|
||||
g_assert_cmphex(r & SRWD, ==, 0);
|
||||
|
||||
/* WP# low and SRWD low -> status register writable */
|
||||
qtest_set_irq_in(global_qtest,
|
||||
"/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0);
|
||||
spi_ctrl_start_user();
|
||||
writeb(ASPEED_FLASH_BASE, 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();
|
||||
g_assert_cmphex(r & SRWD, ==, SRWD);
|
||||
|
||||
/* WP# low and SRWD high -> status register NOT writable */
|
||||
spi_ctrl_start_user();
|
||||
writeb(ASPEED_FLASH_BASE, 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();
|
||||
/* write is not successful */
|
||||
g_assert_cmphex(r & SRWD, ==, SRWD);
|
||||
|
||||
qtest_set_irq_in(global_qtest,
|
||||
"/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1);
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_write_block_protect(void)
|
||||
{
|
||||
uint32_t sector_size = 65536;
|
||||
uint32_t n_sectors = 512;
|
||||
|
||||
spi_ce_ctrl(1 << CRTL_EXTENDED0);
|
||||
spi_conf(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();
|
||||
|
||||
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(addr, 0xffffffff);
|
||||
write_page_mem(addr, make_be32(0xabcdef12));
|
||||
|
||||
uint32_t expected_value = protection_start <= sector
|
||||
&& sector < protection_end
|
||||
? 0xffffffff : 0xabcdef12;
|
||||
|
||||
assert_page_mem(addr, expected_value);
|
||||
}
|
||||
}
|
||||
|
||||
flash_reset();
|
||||
}
|
||||
|
||||
static void test_write_block_protect_bottom_bit(void)
|
||||
{
|
||||
uint32_t sector_size = 65536;
|
||||
uint32_t n_sectors = 512;
|
||||
|
||||
spi_ce_ctrl(1 << CRTL_EXTENDED0);
|
||||
spi_conf(CONF_ENABLE_W0);
|
||||
|
||||
/* 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();
|
||||
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();
|
||||
|
||||
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(addr, 0xffffffff);
|
||||
write_page_mem(addr, make_be32(0xabcdef12));
|
||||
|
||||
uint32_t expected_value = protection_start <= sector
|
||||
&& sector < protection_end
|
||||
? 0xffffffff : 0xabcdef12;
|
||||
|
||||
assert_page_mem(addr, expected_value);
|
||||
}
|
||||
}
|
||||
|
||||
flash_reset();
|
||||
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, 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, aspeed_smc_test_read_page_mem);
|
||||
qtest_add_data_func("/ast1030/smc/write_page_mem",
|
||||
data, aspeed_smc_test_write_page_mem);
|
||||
qtest_add_data_func("/ast1030/smc/read_status_reg",
|
||||
data, aspeed_smc_test_read_status_reg);
|
||||
qtest_add_data_func("/ast1030/smc/write_page_qpi",
|
||||
data, aspeed_smc_test_write_page_qpi);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_autofree char *tmp_path = NULL;
|
||||
AspeedSMCTestData palmetto_data;
|
||||
AspeedSMCTestData ast2500_evb_data;
|
||||
AspeedSMCTestData ast2600_evb_data;
|
||||
AspeedSMCTestData ast1030_evb_data;
|
||||
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);
|
||||
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();
|
||||
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(global_qtest);
|
||||
unlink(tmp_path);
|
||||
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;
|
||||
}
|
||||
|
|
71
tests/qtest/ast2700-smc-test.c
Normal file
71
tests/qtest/ast2700-smc-test.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -214,7 +214,8 @@ qtests_aspeed = \
|
|||
'aspeed_smc-test',
|
||||
'aspeed_gpio-test']
|
||||
qtests_aspeed64 = \
|
||||
['ast2700-gpio-test']
|
||||
['ast2700-gpio-test',
|
||||
'ast2700-smc-test']
|
||||
|
||||
qtests_stm32l4x5 = \
|
||||
['stm32l4x5_exti-test',
|
||||
|
@ -360,6 +361,8 @@ 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'),
|
||||
'ast2700-smc-test': files('aspeed-smc-utils.c', 'ast2700-smc-test.c'),
|
||||
}
|
||||
|
||||
if vnc.found()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue