Aspeed patches :
* Fixes for the DMA space * New model for ASPEED's Hash and Crypto Engine (Joel and Klaus) * Acceptance tests (Joel) * A fix for the XDMA model * Some extra features for the SMC controller. * Two new boards : rainier-bmc and quanta-q7l1-bmc (Patrick) -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmCPiNgACgkQUaNDx8/7 7KGqBhAAviQHW0A4UPGi91uGq6wN1V4skbdMJIGnvOVnkOH1aRySPfnwiRRYimpc /3re+dLzu/zf/ehwdJd7nk3zLG2HR3A+Lw0fdBR2gGvuQwyUz/D+34yR43eJ8ju4 HcuOVfo9ZeSIJZPZTHfHD/0/AhNxKCUv7PiV2T3XukGcaiuQKbQIlfY73LDjIIkS O5FT5IxknCXNWJ4eS8C04EsLzdkdxdZ1QsnaNyhLIywzdO5wThWQ6YE1AK1VPVES yGiJMRXcXHDicmwru9jZIDG3jiiEO01FUG6hBTB2qA/OaXVark/uw55+qsEwRuEv NYznDwEVwmN1CB5oGP+MbRlwyyJoirLlJ35FB3KC3OciZCRbrzHA1OtxsqlDf9eJ K4j3M51CuhU5D9AJ+77BxZewHN2RugIvvlSyQ8FP+mbbvDIBbiiY3mkks7pLpgRh U33HxOGmFNuSIYavlYD12OQcnimMv6Zqrf3WUikfredpXiY8UNAfxazQPpaCzNFq DcjNKt6DcdXXSHthQiRhMbWLPl+Lw8dih8Y+cs/xRnjqySHl8eLLb0tFL7Dlkl0z 7yTLyt+A5UN8AKqYZTvGfsofa4RdaIoBq+CG5unQwzulpU5ndOpaUJcc9QhNV+rN EtxvFEfiq9mDefg1kb2JW/W2ew22sr8fzhRJHnoIXGBJ2RtV+hc= =N5Us -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/legoater/tags/pull-aspeed-20210503' into staging Aspeed patches : * Fixes for the DMA space * New model for ASPEED's Hash and Crypto Engine (Joel and Klaus) * Acceptance tests (Joel) * A fix for the XDMA model * Some extra features for the SMC controller. * Two new boards : rainier-bmc and quanta-q7l1-bmc (Patrick) # gpg: Signature made Mon 03 May 2021 06:23:36 BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * remotes/legoater/tags/pull-aspeed-20210503: aspeed: Add support for the quanta-q7l1-bmc board hw/block: m25p80: Add support for mt25ql02g and mt25qu02g aspeed: Add support for the rainier-bmc board aspeed: Deprecate the swift-bmc machine tests/qtest: Rename m25p80 test in aspeed_smc test aspeed/smc: Add extra controls to request DMA aspeed/smc: Add a 'features' attribute to the object class hw/misc/aspeed_xdma: Add AST2600 support tests/acceptance: Test ast2600 machine tests/acceptance: Test ast2400 and ast2500 machines tests/qtest: Add test for Aspeed HACE aspeed: Integrate HACE hw: Model ASPEED's Hash and Crypto Engine hw/arm/aspeed: Do not sysbus-map mmio flash region directly, use alias aspeed/i2c: Rename DMA address space aspeed/i2c: Fix DMA address mask aspeed/smc: Remove unused "sdram-base" property aspeed/smc: Use the RAM memory region for DMAs Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
87c6cef605
@ -1027,6 +1027,7 @@ F: include/hw/misc/pca9552*.h
|
||||
F: hw/net/ftgmac100.c
|
||||
F: include/hw/net/ftgmac100.h
|
||||
F: docs/system/arm/aspeed.rst
|
||||
F: tests/qtest/*aspeed*
|
||||
|
||||
NRF51
|
||||
M: Joel Stanley <joel@jms.id.au>
|
||||
|
@ -49,6 +49,7 @@ Supported devices
|
||||
* Ethernet controllers
|
||||
* Front LEDs (PCA9552 on I2C bus)
|
||||
* LPC Peripheral Controller (a subset of subdevices are supported)
|
||||
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
|
||||
|
||||
|
||||
Missing devices
|
||||
@ -59,7 +60,6 @@ Missing devices
|
||||
* PWM and Fan Controller
|
||||
* Slave GPIO Controller
|
||||
* Super I/O Controller
|
||||
* Hash/Crypto Engine
|
||||
* PCI-Express 1 Controller
|
||||
* Graphic Display Controller
|
||||
* PECI Controller
|
||||
|
@ -245,6 +245,13 @@ The Raspberry Pi machines come in various models (A, A+, B, B+). To be able
|
||||
to distinguish which model QEMU is implementing, the ``raspi2`` and ``raspi3``
|
||||
machines have been renamed ``raspi2b`` and ``raspi3b``.
|
||||
|
||||
Aspeed ``swift-bmc`` machine (since 6.1)
|
||||
''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
This machine is deprecated because we have enough AST2500 based OpenPOWER
|
||||
machines. It can be easily replaced by the ``witherspoon-bmc`` or the
|
||||
``romulus-bmc`` machines.
|
||||
|
||||
Device options
|
||||
--------------
|
||||
|
||||
|
146
hw/arm/aspeed.c
146
hw/arm/aspeed.c
@ -138,6 +138,19 @@ struct AspeedMachineState {
|
||||
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
|
||||
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
|
||||
|
||||
/* Quanta-Q71l hardware value */
|
||||
#define QUANTA_Q71L_BMC_HW_STRAP1 ( \
|
||||
SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_128MB) | \
|
||||
SCU_AST2400_HW_STRAP_DRAM_CONFIG(2/* DDR3 with CL=6, CWL=5 */) | \
|
||||
SCU_AST2400_HW_STRAP_ACPI_DIS | \
|
||||
SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_24M_IN) | \
|
||||
SCU_HW_STRAP_VGA_CLASS_CODE | \
|
||||
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_PASS_THROUGH) | \
|
||||
SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
|
||||
SCU_HW_STRAP_SPI_WIDTH | \
|
||||
SCU_HW_STRAP_VGA_SIZE_SET(VGA_8M_DRAM) | \
|
||||
SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
|
||||
|
||||
/* AST2600 evb hardware value */
|
||||
#define AST2600_EVB_HW_STRAP1 0x000000C0
|
||||
#define AST2600_EVB_HW_STRAP2 0x00000003
|
||||
@ -146,6 +159,10 @@ struct AspeedMachineState {
|
||||
#define TACOMA_BMC_HW_STRAP1 0x00000000
|
||||
#define TACOMA_BMC_HW_STRAP2 0x00000040
|
||||
|
||||
/* Rainier hardware value: (QEMU prototype) */
|
||||
#define RAINIER_BMC_HW_STRAP1 0x00000000
|
||||
#define RAINIER_BMC_HW_STRAP2 0x00000000
|
||||
|
||||
/*
|
||||
* The max ram region is for firmwares that scan the address space
|
||||
* with load/store to guess how much RAM the SoC has.
|
||||
@ -327,7 +344,7 @@ static void aspeed_machine_init(MachineState *machine)
|
||||
object_property_set_int(OBJECT(&bmc->soc), "num-cs", amc->num_cs,
|
||||
&error_abort);
|
||||
object_property_set_link(OBJECT(&bmc->soc), "dram",
|
||||
OBJECT(&bmc->ram_container), &error_abort);
|
||||
OBJECT(machine->ram), &error_abort);
|
||||
if (machine->kernel_filename) {
|
||||
/*
|
||||
* When booting with a -kernel command line there is no u-boot
|
||||
@ -433,6 +450,34 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
object_property_set_int(OBJECT(dev), "temperature3", 110000, &error_abort);
|
||||
}
|
||||
|
||||
static void quanta_q71l_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
||||
/*
|
||||
* The quanta-q71l platform expects tmp75s which are compatible with
|
||||
* tmp105s.
|
||||
*/
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4c);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4e);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4f);
|
||||
|
||||
/* TODO: i2c-1: Add baseboard FRU eeprom@54 24c64 */
|
||||
/* TODO: i2c-1: Add Frontpanel FRU eeprom@57 24c64 */
|
||||
/* TODO: Add Memory Riser i2c mux and eeproms. */
|
||||
|
||||
/* TODO: i2c-2: pca9546@74 */
|
||||
/* TODO: i2c-2: pca9548@77 */
|
||||
/* TODO: i2c-3: Add BIOS FRU eeprom@56 24c64 */
|
||||
/* TODO: i2c-7: Add pca9546@70 */
|
||||
/* - i2c@0: pmbus@59 */
|
||||
/* - i2c@1: pmbus@58 */
|
||||
/* - i2c@2: pmbus@58 */
|
||||
/* - i2c@3: pmbus@59 */
|
||||
/* TODO: i2c-7: Add PDB FRU eeprom@52 */
|
||||
/* TODO: i2c-8: Add BMC FRU eeprom@50 */
|
||||
}
|
||||
|
||||
static void ast2500_evb_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
@ -629,6 +674,58 @@ static void g220a_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
eeprom_buf);
|
||||
}
|
||||
|
||||
static void rainier_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
||||
/* The rainier expects a TMP275 but a TMP105 is compatible */
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105,
|
||||
0x48);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105,
|
||||
0x49);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105,
|
||||
0x4a);
|
||||
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105,
|
||||
0x48);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105,
|
||||
0x49);
|
||||
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105,
|
||||
0x48);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105,
|
||||
0x4a);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105,
|
||||
0x4b);
|
||||
|
||||
/* Bus 7: TODO dps310@76 */
|
||||
/* Bus 7: TODO max31785@52 */
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x61);
|
||||
/* Bus 7: TODO si7021-a20@20 */
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105,
|
||||
0x48);
|
||||
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105,
|
||||
0x48);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105,
|
||||
0x4a);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x61);
|
||||
/* Bus 8: ucd90320@11 */
|
||||
/* Bus 8: ucd90320@b */
|
||||
/* Bus 8: ucd90320@c */
|
||||
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4d);
|
||||
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4d);
|
||||
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105,
|
||||
0x48);
|
||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105,
|
||||
0x49);
|
||||
}
|
||||
|
||||
static bool aspeed_get_mmio_exec(Object *obj, Error **errp)
|
||||
{
|
||||
return ASPEED_MACHINE(obj)->mmio_exec;
|
||||
@ -728,6 +825,23 @@ static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
|
||||
aspeed_soc_num_cpus(amc->soc_name);
|
||||
};
|
||||
|
||||
static void aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "Quanta-Q71l BMC (ARM926EJ-S)";
|
||||
amc->soc_name = "ast2400-a1";
|
||||
amc->hw_strap1 = QUANTA_Q71L_BMC_HW_STRAP1;
|
||||
amc->fmc_model = "n25q256a";
|
||||
amc->spi_model = "mx25l25635e";
|
||||
amc->num_cs = 1;
|
||||
amc->i2c_init = quanta_q71l_bmc_i2c_init;
|
||||
mc->default_ram_size = 128 * MiB;
|
||||
mc->default_cpus = mc->min_cpus = mc->max_cpus =
|
||||
aspeed_soc_num_cpus(amc->soc_name);
|
||||
}
|
||||
|
||||
static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
|
||||
void *data)
|
||||
{
|
||||
@ -811,6 +925,9 @@ static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
|
||||
mc->default_ram_size = 512 * MiB;
|
||||
mc->default_cpus = mc->min_cpus = mc->max_cpus =
|
||||
aspeed_soc_num_cpus(amc->soc_name);
|
||||
|
||||
mc->deprecation_reason = "redundant system. Please use a similar "
|
||||
"OpenPOWER BMC, Witherspoon or Romulus.";
|
||||
};
|
||||
|
||||
static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data)
|
||||
@ -886,6 +1003,25 @@ static void aspeed_machine_g220a_class_init(ObjectClass *oc, void *data)
|
||||
aspeed_soc_num_cpus(amc->soc_name);
|
||||
};
|
||||
|
||||
static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "IBM Rainier BMC (Cortex A7)";
|
||||
amc->soc_name = "ast2600-a1";
|
||||
amc->hw_strap1 = RAINIER_BMC_HW_STRAP1;
|
||||
amc->hw_strap2 = RAINIER_BMC_HW_STRAP2;
|
||||
amc->fmc_model = "mx66l1g45g";
|
||||
amc->spi_model = "mx66l1g45g";
|
||||
amc->num_cs = 2;
|
||||
amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
|
||||
amc->i2c_init = rainier_bmc_i2c_init;
|
||||
mc->default_ram_size = 1 * GiB;
|
||||
mc->default_cpus = mc->min_cpus = mc->max_cpus =
|
||||
aspeed_soc_num_cpus(amc->soc_name);
|
||||
};
|
||||
|
||||
static const TypeInfo aspeed_machine_types[] = {
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
|
||||
@ -927,6 +1063,14 @@ static const TypeInfo aspeed_machine_types[] = {
|
||||
.name = MACHINE_TYPE_NAME("g220a-bmc"),
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
.class_init = aspeed_machine_g220a_class_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("quanta-q71l-bmc"),
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
.class_init = aspeed_machine_quanta_q71l_class_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("rainier-bmc"),
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
.class_init = aspeed_machine_rainier_class_init,
|
||||
}, {
|
||||
.name = TYPE_ASPEED_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
|
@ -42,6 +42,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
||||
[ASPEED_DEV_ETH2] = 0x1E680000,
|
||||
[ASPEED_DEV_ETH4] = 0x1E690000,
|
||||
[ASPEED_DEV_VIC] = 0x1E6C0000,
|
||||
[ASPEED_DEV_HACE] = 0x1E6D0000,
|
||||
[ASPEED_DEV_SDMC] = 0x1E6E0000,
|
||||
[ASPEED_DEV_SCU] = 0x1E6E2000,
|
||||
[ASPEED_DEV_XDMA] = 0x1E6E7000,
|
||||
@ -102,6 +103,7 @@ static const int aspeed_soc_ast2600_irqmap[] = {
|
||||
[ASPEED_DEV_I2C] = 110, /* 110 -> 125 */
|
||||
[ASPEED_DEV_ETH1] = 2,
|
||||
[ASPEED_DEV_ETH2] = 3,
|
||||
[ASPEED_DEV_HACE] = 4,
|
||||
[ASPEED_DEV_ETH3] = 32,
|
||||
[ASPEED_DEV_ETH4] = 33,
|
||||
[ASPEED_DEV_KCS] = 138, /* 138 -> 142 */
|
||||
@ -185,7 +187,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
|
||||
object_initialize_child(obj, "mii[*]", &s->mii[i], TYPE_ASPEED_MII);
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "xdma", &s->xdma, TYPE_ASPEED_XDMA);
|
||||
snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname);
|
||||
object_initialize_child(obj, "xdma", &s->xdma, typename);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
|
||||
object_initialize_child(obj, "gpio", &s->gpio, typename);
|
||||
@ -213,6 +216,9 @@ static void aspeed_soc_ast2600_init(Object *obj)
|
||||
TYPE_SYSBUS_SDHCI);
|
||||
|
||||
object_initialize_child(obj, "lpc", &s->lpc, TYPE_ASPEED_LPC);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname);
|
||||
object_initialize_child(obj, "hace", &s->hace, typename);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -344,10 +350,6 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
||||
/* FMC, The number of CS is set at the board level */
|
||||
object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr),
|
||||
&error_abort);
|
||||
if (!object_property_set_int(OBJECT(&s->fmc), "sdram-base",
|
||||
sc->memmap[ASPEED_DEV_SDRAM], errp)) {
|
||||
return;
|
||||
}
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
|
||||
return;
|
||||
}
|
||||
@ -498,6 +500,16 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 1 + aspeed_lpc_kcs_4,
|
||||
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
|
||||
sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4));
|
||||
|
||||
/* HACE */
|
||||
object_property_set_link(OBJECT(&s->hace), "dram", OBJECT(s->dram_mr),
|
||||
&error_abort);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->hace), 0, sc->memmap[ASPEED_DEV_HACE]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
|
||||
}
|
||||
|
||||
static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -34,6 +34,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
|
||||
[ASPEED_DEV_VIC] = 0x1E6C0000,
|
||||
[ASPEED_DEV_SDMC] = 0x1E6E0000,
|
||||
[ASPEED_DEV_SCU] = 0x1E6E2000,
|
||||
[ASPEED_DEV_HACE] = 0x1E6E3000,
|
||||
[ASPEED_DEV_XDMA] = 0x1E6E7000,
|
||||
[ASPEED_DEV_VIDEO] = 0x1E700000,
|
||||
[ASPEED_DEV_ADC] = 0x1E6E9000,
|
||||
@ -65,6 +66,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = {
|
||||
[ASPEED_DEV_VIC] = 0x1E6C0000,
|
||||
[ASPEED_DEV_SDMC] = 0x1E6E0000,
|
||||
[ASPEED_DEV_SCU] = 0x1E6E2000,
|
||||
[ASPEED_DEV_HACE] = 0x1E6E3000,
|
||||
[ASPEED_DEV_XDMA] = 0x1E6E7000,
|
||||
[ASPEED_DEV_ADC] = 0x1E6E9000,
|
||||
[ASPEED_DEV_VIDEO] = 0x1E700000,
|
||||
@ -117,6 +119,7 @@ static const int aspeed_soc_ast2400_irqmap[] = {
|
||||
[ASPEED_DEV_ETH2] = 3,
|
||||
[ASPEED_DEV_XDMA] = 6,
|
||||
[ASPEED_DEV_SDHCI] = 26,
|
||||
[ASPEED_DEV_HACE] = 4,
|
||||
};
|
||||
|
||||
#define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap
|
||||
@ -196,7 +199,8 @@ static void aspeed_soc_init(Object *obj)
|
||||
TYPE_FTGMAC100);
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "xdma", &s->xdma, TYPE_ASPEED_XDMA);
|
||||
snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname);
|
||||
object_initialize_child(obj, "xdma", &s->xdma, typename);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
|
||||
object_initialize_child(obj, "gpio", &s->gpio, typename);
|
||||
@ -212,6 +216,9 @@ static void aspeed_soc_init(Object *obj)
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "lpc", &s->lpc, TYPE_ASPEED_LPC);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname);
|
||||
object_initialize_child(obj, "hace", &s->hace, typename);
|
||||
}
|
||||
|
||||
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
||||
@ -301,10 +308,6 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
||||
/* FMC, The number of CS is set at the board level */
|
||||
object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr),
|
||||
&error_abort);
|
||||
if (!object_property_set_int(OBJECT(&s->fmc), "sdram-base",
|
||||
sc->memmap[ASPEED_DEV_SDRAM], errp)) {
|
||||
return;
|
||||
}
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
|
||||
return;
|
||||
}
|
||||
@ -425,6 +428,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 1 + aspeed_lpc_kcs_4,
|
||||
qdev_get_gpio_in(DEVICE(&s->lpc), aspeed_lpc_kcs_4));
|
||||
|
||||
/* HACE */
|
||||
object_property_set_link(OBJECT(&s->hace), "dram", OBJECT(s->dram_mr),
|
||||
&error_abort);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->hace), 0, sc->memmap[ASPEED_DEV_HACE]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
|
||||
}
|
||||
static Property aspeed_soc_properties[] = {
|
||||
DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION,
|
||||
|
@ -259,6 +259,8 @@ static const FlashPartInfo known_devices[] = {
|
||||
{ INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) },
|
||||
{ INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) },
|
||||
{ INFO_STACKED("mt25qu01g", 0x20bb21, 0x1040, 64 << 10, 2048, ER_4K, 2) },
|
||||
{ INFO_STACKED("mt25ql02g", 0x20ba22, 0x1040, 64 << 10, 4096, ER_4K | ER_32K, 2) },
|
||||
{ INFO_STACKED("mt25qu02g", 0x20bb22, 0x1040, 64 << 10, 4096, ER_4K | ER_32K, 2) },
|
||||
|
||||
/* Spansion -- single (large) sector size only, at least
|
||||
* for the chips listed here (without boot sectors).
|
||||
|
@ -601,7 +601,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
|
||||
break;
|
||||
}
|
||||
|
||||
bus->dma_addr = value & 0xfffffffc;
|
||||
bus->dma_addr = value & 0x3ffffffc;
|
||||
break;
|
||||
|
||||
case I2CD_DMA_LEN:
|
||||
@ -816,7 +816,8 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
address_space_init(&s->dram_as, s->dram_mr, "dma-dram");
|
||||
address_space_init(&s->dram_as, s->dram_mr,
|
||||
TYPE_ASPEED_I2C "-dma-dram");
|
||||
}
|
||||
}
|
||||
|
||||
|
389
hw/misc/aspeed_hace.c
Normal file
389
hw/misc/aspeed_hace.c
Normal file
@ -0,0 +1,389 @@
|
||||
/*
|
||||
* ASPEED Hash and Crypto Engine
|
||||
*
|
||||
* Copyright (C) 2021 IBM Corp.
|
||||
*
|
||||
* Joel Stanley <joel@jms.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/misc/aspeed_hace.h"
|
||||
#include "qapi/error.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/irq.h"
|
||||
|
||||
#define R_CRYPT_CMD (0x10 / 4)
|
||||
|
||||
#define R_STATUS (0x1c / 4)
|
||||
#define HASH_IRQ BIT(9)
|
||||
#define CRYPT_IRQ BIT(12)
|
||||
#define TAG_IRQ BIT(15)
|
||||
|
||||
#define R_HASH_SRC (0x20 / 4)
|
||||
#define R_HASH_DEST (0x24 / 4)
|
||||
#define R_HASH_SRC_LEN (0x2c / 4)
|
||||
|
||||
#define R_HASH_CMD (0x30 / 4)
|
||||
/* Hash algorithm selection */
|
||||
#define HASH_ALGO_MASK (BIT(4) | BIT(5) | BIT(6))
|
||||
#define HASH_ALGO_MD5 0
|
||||
#define HASH_ALGO_SHA1 BIT(5)
|
||||
#define HASH_ALGO_SHA224 BIT(6)
|
||||
#define HASH_ALGO_SHA256 (BIT(4) | BIT(6))
|
||||
#define HASH_ALGO_SHA512_SERIES (BIT(5) | BIT(6))
|
||||
/* SHA512 algorithm selection */
|
||||
#define SHA512_HASH_ALGO_MASK (BIT(10) | BIT(11) | BIT(12))
|
||||
#define HASH_ALGO_SHA512_SHA512 0
|
||||
#define HASH_ALGO_SHA512_SHA384 BIT(10)
|
||||
#define HASH_ALGO_SHA512_SHA256 BIT(11)
|
||||
#define HASH_ALGO_SHA512_SHA224 (BIT(10) | BIT(11))
|
||||
/* HMAC modes */
|
||||
#define HASH_HMAC_MASK (BIT(7) | BIT(8))
|
||||
#define HASH_DIGEST 0
|
||||
#define HASH_DIGEST_HMAC BIT(7)
|
||||
#define HASH_DIGEST_ACCUM BIT(8)
|
||||
#define HASH_HMAC_KEY (BIT(7) | BIT(8))
|
||||
/* Cascaded operation modes */
|
||||
#define HASH_ONLY 0
|
||||
#define HASH_ONLY2 BIT(0)
|
||||
#define HASH_CRYPT_THEN_HASH BIT(1)
|
||||
#define HASH_HASH_THEN_CRYPT (BIT(0) | BIT(1))
|
||||
/* Other cmd bits */
|
||||
#define HASH_IRQ_EN BIT(9)
|
||||
#define HASH_SG_EN BIT(18)
|
||||
/* Scatter-gather data list */
|
||||
#define SG_LIST_LEN_SIZE 4
|
||||
#define SG_LIST_LEN_MASK 0x0FFFFFFF
|
||||
#define SG_LIST_LEN_LAST BIT(31)
|
||||
#define SG_LIST_ADDR_SIZE 4
|
||||
#define SG_LIST_ADDR_MASK 0x7FFFFFFF
|
||||
#define SG_LIST_ENTRY_SIZE (SG_LIST_LEN_SIZE + SG_LIST_ADDR_SIZE)
|
||||
#define ASPEED_HACE_MAX_SG 256 /* max number of entries */
|
||||
|
||||
static const struct {
|
||||
uint32_t mask;
|
||||
QCryptoHashAlgorithm algo;
|
||||
} hash_algo_map[] = {
|
||||
{ HASH_ALGO_MD5, QCRYPTO_HASH_ALG_MD5 },
|
||||
{ HASH_ALGO_SHA1, QCRYPTO_HASH_ALG_SHA1 },
|
||||
{ HASH_ALGO_SHA224, QCRYPTO_HASH_ALG_SHA224 },
|
||||
{ HASH_ALGO_SHA256, QCRYPTO_HASH_ALG_SHA256 },
|
||||
{ HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA512, QCRYPTO_HASH_ALG_SHA512 },
|
||||
{ HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA384, QCRYPTO_HASH_ALG_SHA384 },
|
||||
{ HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA256, QCRYPTO_HASH_ALG_SHA256 },
|
||||
};
|
||||
|
||||
static int hash_algo_lookup(uint32_t reg)
|
||||
{
|
||||
int i;
|
||||
|
||||
reg &= HASH_ALGO_MASK | SHA512_HASH_ALGO_MASK;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo_map); i++) {
|
||||
if (reg == hash_algo_map[i].mask) {
|
||||
return hash_algo_map[i].algo;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode)
|
||||
{
|
||||
struct iovec iov[ASPEED_HACE_MAX_SG];
|
||||
g_autofree uint8_t *digest_buf;
|
||||
size_t digest_len = 0;
|
||||
int i;
|
||||
|
||||
if (sg_mode) {
|
||||
uint32_t len = 0;
|
||||
|
||||
for (i = 0; !(len & SG_LIST_LEN_LAST); i++) {
|
||||
uint32_t addr, src;
|
||||
hwaddr plen;
|
||||
|
||||
if (i == ASPEED_HACE_MAX_SG) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"aspeed_hace: guest failed to set end of sg list marker\n");
|
||||
break;
|
||||
}
|
||||
|
||||
src = s->regs[R_HASH_SRC] + (i * SG_LIST_ENTRY_SIZE);
|
||||
|
||||
len = address_space_ldl_le(&s->dram_as, src,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
|
||||
addr = address_space_ldl_le(&s->dram_as, src + SG_LIST_LEN_SIZE,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
addr &= SG_LIST_ADDR_MASK;
|
||||
|
||||
iov[i].iov_len = len & SG_LIST_LEN_MASK;
|
||||
plen = iov[i].iov_len;
|
||||
iov[i].iov_base = address_space_map(&s->dram_as, addr, &plen, false,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
}
|
||||
} else {
|
||||
hwaddr len = s->regs[R_HASH_SRC_LEN];
|
||||
|
||||
iov[0].iov_len = len;
|
||||
iov[0].iov_base = address_space_map(&s->dram_as, s->regs[R_HASH_SRC],
|
||||
&len, false,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
i = 1;
|
||||
}
|
||||
|
||||
if (qcrypto_hash_bytesv(algo, iov, i, &digest_buf, &digest_len, NULL) < 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (address_space_write(&s->dram_as, s->regs[R_HASH_DEST],
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
digest_buf, digest_len)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"aspeed_hace: address space write failed\n");
|
||||
}
|
||||
|
||||
for (; i > 0; i--) {
|
||||
address_space_unmap(&s->dram_as, iov[i - 1].iov_base,
|
||||
iov[i - 1].iov_len, false,
|
||||
iov[i - 1].iov_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set status bits to indicate completion. Testing shows hardware sets
|
||||
* these irrespective of HASH_IRQ_EN.
|
||||
*/
|
||||
s->regs[R_STATUS] |= HASH_IRQ;
|
||||
}
|
||||
|
||||
static uint64_t aspeed_hace_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
AspeedHACEState *s = ASPEED_HACE(opaque);
|
||||
|
||||
addr >>= 2;
|
||||
|
||||
if (addr >= ASPEED_HACE_NR_REGS) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr << 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return s->regs[addr];
|
||||
}
|
||||
|
||||
static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned int size)
|
||||
{
|
||||
AspeedHACEState *s = ASPEED_HACE(opaque);
|
||||
AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s);
|
||||
|
||||
addr >>= 2;
|
||||
|
||||
if (addr >= ASPEED_HACE_NR_REGS) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr << 2);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (addr) {
|
||||
case R_STATUS:
|
||||
if (data & HASH_IRQ) {
|
||||
data &= ~HASH_IRQ;
|
||||
|
||||
if (s->regs[addr] & HASH_IRQ) {
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_HASH_SRC:
|
||||
data &= ahc->src_mask;
|
||||
break;
|
||||
case R_HASH_DEST:
|
||||
data &= ahc->dest_mask;
|
||||
break;
|
||||
case R_HASH_SRC_LEN:
|
||||
data &= 0x0FFFFFFF;
|
||||
break;
|
||||
case R_HASH_CMD: {
|
||||
int algo;
|
||||
data &= ahc->hash_mask;
|
||||
|
||||
if ((data & HASH_HMAC_MASK)) {
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s: HMAC engine command mode %"PRIx64" not implemented",
|
||||
__func__, (data & HASH_HMAC_MASK) >> 8);
|
||||
}
|
||||
if (data & BIT(1)) {
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s: Cascaded mode not implemented",
|
||||
__func__);
|
||||
}
|
||||
algo = hash_algo_lookup(data);
|
||||
if (algo < 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Invalid hash algorithm selection 0x%"PRIx64"\n",
|
||||
__func__, data & ahc->hash_mask);
|
||||
break;
|
||||
}
|
||||
do_hash_operation(s, algo, data & HASH_SG_EN);
|
||||
|
||||
if (data & HASH_IRQ_EN) {
|
||||
qemu_irq_raise(s->irq);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R_CRYPT_CMD:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Crypt commands not implemented\n",
|
||||
__func__);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s->regs[addr] = data;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps aspeed_hace_ops = {
|
||||
.read = aspeed_hace_read,
|
||||
.write = aspeed_hace_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
};
|
||||
|
||||
static void aspeed_hace_reset(DeviceState *dev)
|
||||
{
|
||||
struct AspeedHACEState *s = ASPEED_HACE(dev);
|
||||
|
||||
memset(s->regs, 0, sizeof(s->regs));
|
||||
}
|
||||
|
||||
static void aspeed_hace_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
AspeedHACEState *s = ASPEED_HACE(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_hace_ops, s,
|
||||
TYPE_ASPEED_HACE, 0x1000);
|
||||
|
||||
if (!s->dram_mr) {
|
||||
error_setg(errp, TYPE_ASPEED_HACE ": 'dram' link not set");
|
||||
return;
|
||||
}
|
||||
|
||||
address_space_init(&s->dram_as, s->dram_mr, "dram");
|
||||
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static Property aspeed_hace_properties[] = {
|
||||
DEFINE_PROP_LINK("dram", AspeedHACEState, dram_mr,
|
||||
TYPE_MEMORY_REGION, MemoryRegion *),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
||||
static const VMStateDescription vmstate_aspeed_hace = {
|
||||
.name = TYPE_ASPEED_HACE,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32_ARRAY(regs, AspeedHACEState, ASPEED_HACE_NR_REGS),
|
||||
VMSTATE_END_OF_LIST(),
|
||||
}
|
||||
};
|
||||
|
||||
static void aspeed_hace_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = aspeed_hace_realize;
|
||||
dc->reset = aspeed_hace_reset;
|
||||
device_class_set_props(dc, aspeed_hace_properties);
|
||||
dc->vmsd = &vmstate_aspeed_hace;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_hace_info = {
|
||||
.name = TYPE_ASPEED_HACE,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedHACEState),
|
||||
.class_init = aspeed_hace_class_init,
|
||||
.class_size = sizeof(AspeedHACEClass)
|
||||
};
|
||||
|
||||
static void aspeed_ast2400_hace_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass);
|
||||
|
||||
dc->desc = "AST2400 Hash and Crypto Engine";
|
||||
|
||||
ahc->src_mask = 0x0FFFFFFF;
|
||||
ahc->dest_mask = 0x0FFFFFF8;
|
||||
ahc->hash_mask = 0x000003ff; /* No SG or SHA512 modes */
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_ast2400_hace_info = {
|
||||
.name = TYPE_ASPEED_AST2400_HACE,
|
||||
.parent = TYPE_ASPEED_HACE,
|
||||
.class_init = aspeed_ast2400_hace_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_ast2500_hace_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass);
|
||||
|
||||
dc->desc = "AST2500 Hash and Crypto Engine";
|
||||
|
||||
ahc->src_mask = 0x3fffffff;
|
||||
ahc->dest_mask = 0x3ffffff8;
|
||||
ahc->hash_mask = 0x000003ff; /* No SG or SHA512 modes */
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_ast2500_hace_info = {
|
||||
.name = TYPE_ASPEED_AST2500_HACE,
|
||||
.parent = TYPE_ASPEED_HACE,
|
||||
.class_init = aspeed_ast2500_hace_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_ast2600_hace_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass);
|
||||
|
||||
dc->desc = "AST2600 Hash and Crypto Engine";
|
||||
|
||||
ahc->src_mask = 0x7FFFFFFF;
|
||||
ahc->dest_mask = 0x7FFFFFF8;
|
||||
ahc->hash_mask = 0x00147FFF;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_ast2600_hace_info = {
|
||||
.name = TYPE_ASPEED_AST2600_HACE,
|
||||
.parent = TYPE_ASPEED_HACE,
|
||||
.class_init = aspeed_ast2600_hace_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_hace_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_ast2400_hace_info);
|
||||
type_register_static(&aspeed_ast2500_hace_info);
|
||||
type_register_static(&aspeed_ast2600_hace_info);
|
||||
type_register_static(&aspeed_hace_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_hace_register_types);
|
@ -30,6 +30,19 @@
|
||||
#define XDMA_IRQ_ENG_STAT_US_COMP BIT(4)
|
||||
#define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5)
|
||||
#define XDMA_IRQ_ENG_STAT_RESET 0xF8000000
|
||||
|
||||
#define XDMA_AST2600_BMC_CMDQ_ADDR 0x14
|
||||
#define XDMA_AST2600_BMC_CMDQ_ENDP 0x18
|
||||
#define XDMA_AST2600_BMC_CMDQ_WRP 0x1c
|
||||
#define XDMA_AST2600_BMC_CMDQ_RDP 0x20
|
||||
#define XDMA_AST2600_IRQ_CTRL 0x38
|
||||
#define XDMA_AST2600_IRQ_CTRL_US_COMP BIT(16)
|
||||
#define XDMA_AST2600_IRQ_CTRL_DS_COMP BIT(17)
|
||||
#define XDMA_AST2600_IRQ_CTRL_W_MASK 0x017003FF
|
||||
#define XDMA_AST2600_IRQ_STATUS 0x3c
|
||||
#define XDMA_AST2600_IRQ_STATUS_US_COMP BIT(16)
|
||||
#define XDMA_AST2600_IRQ_STATUS_DS_COMP BIT(17)
|
||||
|
||||
#define XDMA_MEM_SIZE 0x1000
|
||||
|
||||
#define TO_REG(addr) ((addr) / sizeof(uint32_t))
|
||||
@ -52,56 +65,48 @@ static void aspeed_xdma_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned int idx;
|
||||
uint32_t val32 = (uint32_t)val;
|
||||
AspeedXDMAState *xdma = opaque;
|
||||
AspeedXDMAClass *axc = ASPEED_XDMA_GET_CLASS(xdma);
|
||||
|
||||
if (addr >= ASPEED_XDMA_REG_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (addr) {
|
||||
case XDMA_BMC_CMDQ_ENDP:
|
||||
if (addr == axc->cmdq_endp) {
|
||||
xdma->regs[TO_REG(addr)] = val32 & XDMA_BMC_CMDQ_W_MASK;
|
||||
break;
|
||||
case XDMA_BMC_CMDQ_WRP:
|
||||
} else if (addr == axc->cmdq_wrp) {
|
||||
idx = TO_REG(addr);
|
||||
xdma->regs[idx] = val32 & XDMA_BMC_CMDQ_W_MASK;
|
||||
xdma->regs[TO_REG(XDMA_BMC_CMDQ_RDP)] = xdma->regs[idx];
|
||||
xdma->regs[TO_REG(axc->cmdq_rdp)] = xdma->regs[idx];
|
||||
|
||||
trace_aspeed_xdma_write(addr, val);
|
||||
|
||||
if (xdma->bmc_cmdq_readp_set) {
|
||||
xdma->bmc_cmdq_readp_set = 0;
|
||||
} else {
|
||||
xdma->regs[TO_REG(XDMA_IRQ_ENG_STAT)] |=
|
||||
XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP;
|
||||
xdma->regs[TO_REG(axc->intr_status)] |= axc->intr_complete;
|
||||
|
||||
if (xdma->regs[TO_REG(XDMA_IRQ_ENG_CTRL)] &
|
||||
(XDMA_IRQ_ENG_CTRL_US_COMP | XDMA_IRQ_ENG_CTRL_DS_COMP))
|
||||
if (xdma->regs[TO_REG(axc->intr_ctrl)] & axc->intr_complete) {
|
||||
qemu_irq_raise(xdma->irq);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XDMA_BMC_CMDQ_RDP:
|
||||
} else if (addr == axc->cmdq_rdp) {
|
||||
trace_aspeed_xdma_write(addr, val);
|
||||
|
||||
if (val32 == XDMA_BMC_CMDQ_RDP_MAGIC) {
|
||||
xdma->bmc_cmdq_readp_set = 1;
|
||||
}
|
||||
break;
|
||||
case XDMA_IRQ_ENG_CTRL:
|
||||
xdma->regs[TO_REG(addr)] = val32 & XDMA_IRQ_ENG_CTRL_W_MASK;
|
||||
break;
|
||||
case XDMA_IRQ_ENG_STAT:
|
||||
} else if (addr == axc->intr_ctrl) {
|
||||
xdma->regs[TO_REG(addr)] = val32 & axc->intr_ctrl_mask;
|
||||
} else if (addr == axc->intr_status) {
|
||||
trace_aspeed_xdma_write(addr, val);
|
||||
|
||||
idx = TO_REG(addr);
|
||||
if (val32 & (XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP)) {
|
||||
xdma->regs[idx] &=
|
||||
~(XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP);
|
||||
if (val32 & axc->intr_complete) {
|
||||
xdma->regs[idx] &= ~axc->intr_complete;
|
||||
qemu_irq_lower(xdma->irq);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
xdma->regs[TO_REG(addr)] = val32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,10 +132,11 @@ static void aspeed_xdma_realize(DeviceState *dev, Error **errp)
|
||||
static void aspeed_xdma_reset(DeviceState *dev)
|
||||
{
|
||||
AspeedXDMAState *xdma = ASPEED_XDMA(dev);
|
||||
AspeedXDMAClass *axc = ASPEED_XDMA_GET_CLASS(xdma);
|
||||
|
||||
xdma->bmc_cmdq_readp_set = 0;
|
||||
memset(xdma->regs, 0, ASPEED_XDMA_REG_SIZE);
|
||||
xdma->regs[TO_REG(XDMA_IRQ_ENG_STAT)] = XDMA_IRQ_ENG_STAT_RESET;
|
||||
xdma->regs[TO_REG(axc->intr_status)] = XDMA_IRQ_ENG_STAT_RESET;
|
||||
|
||||
qemu_irq_lower(xdma->irq);
|
||||
}
|
||||
@ -144,6 +150,73 @@ static const VMStateDescription aspeed_xdma_vmstate = {
|
||||
},
|
||||
};
|
||||
|
||||
static void aspeed_2600_xdma_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedXDMAClass *axc = ASPEED_XDMA_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2600 XDMA Controller";
|
||||
|
||||
axc->cmdq_endp = XDMA_AST2600_BMC_CMDQ_ENDP;
|
||||
axc->cmdq_wrp = XDMA_AST2600_BMC_CMDQ_WRP;
|
||||
axc->cmdq_rdp = XDMA_AST2600_BMC_CMDQ_RDP;
|
||||
axc->intr_ctrl = XDMA_AST2600_IRQ_CTRL;
|
||||
axc->intr_ctrl_mask = XDMA_AST2600_IRQ_CTRL_W_MASK;
|
||||
axc->intr_status = XDMA_AST2600_IRQ_STATUS;
|
||||
axc->intr_complete = XDMA_AST2600_IRQ_STATUS_US_COMP |
|
||||
XDMA_AST2600_IRQ_STATUS_DS_COMP;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2600_xdma_info = {
|
||||
.name = TYPE_ASPEED_2600_XDMA,
|
||||
.parent = TYPE_ASPEED_XDMA,
|
||||
.class_init = aspeed_2600_xdma_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_2500_xdma_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedXDMAClass *axc = ASPEED_XDMA_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2500 XDMA Controller";
|
||||
|
||||
axc->cmdq_endp = XDMA_BMC_CMDQ_ENDP;
|
||||
axc->cmdq_wrp = XDMA_BMC_CMDQ_WRP;
|
||||
axc->cmdq_rdp = XDMA_BMC_CMDQ_RDP;
|
||||
axc->intr_ctrl = XDMA_IRQ_ENG_CTRL;
|
||||
axc->intr_ctrl_mask = XDMA_IRQ_ENG_CTRL_W_MASK;
|
||||
axc->intr_status = XDMA_IRQ_ENG_STAT;
|
||||
axc->intr_complete = XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP;
|
||||
};
|
||||
|
||||
static const TypeInfo aspeed_2500_xdma_info = {
|
||||
.name = TYPE_ASPEED_2500_XDMA,
|
||||
.parent = TYPE_ASPEED_XDMA,
|
||||
.class_init = aspeed_2500_xdma_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_2400_xdma_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedXDMAClass *axc = ASPEED_XDMA_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2400 XDMA Controller";
|
||||
|
||||
axc->cmdq_endp = XDMA_BMC_CMDQ_ENDP;
|
||||
axc->cmdq_wrp = XDMA_BMC_CMDQ_WRP;
|
||||
axc->cmdq_rdp = XDMA_BMC_CMDQ_RDP;
|
||||
axc->intr_ctrl = XDMA_IRQ_ENG_CTRL;
|
||||
axc->intr_ctrl_mask = XDMA_IRQ_ENG_CTRL_W_MASK;
|
||||
axc->intr_status = XDMA_IRQ_ENG_STAT;
|
||||
axc->intr_complete = XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP;
|
||||
};
|
||||
|
||||
static const TypeInfo aspeed_2400_xdma_info = {
|
||||
.name = TYPE_ASPEED_2400_XDMA,
|
||||
.parent = TYPE_ASPEED_XDMA,
|
||||
.class_init = aspeed_2400_xdma_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_xdma_class_init(ObjectClass *classp, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(classp);
|
||||
@ -158,10 +231,15 @@ static const TypeInfo aspeed_xdma_info = {
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedXDMAState),
|
||||
.class_init = aspeed_xdma_class_init,
|
||||
.class_size = sizeof(AspeedXDMAClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void aspeed_xdma_register_type(void)
|
||||
{
|
||||
type_register_static(&aspeed_xdma_info);
|
||||
type_register_static(&aspeed_2400_xdma_info);
|
||||
type_register_static(&aspeed_2500_xdma_info);
|
||||
type_register_static(&aspeed_2600_xdma_info);
|
||||
}
|
||||
type_init(aspeed_xdma_register_type);
|
||||
|
@ -109,6 +109,7 @@ softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
|
||||
'aspeed_hace.c',
|
||||
'aspeed_lpc.c',
|
||||
'aspeed_scu.c',
|
||||
'aspeed_sdmc.c',
|
||||
|
@ -127,6 +127,8 @@
|
||||
|
||||
/* DMA Control/Status Register */
|
||||
#define R_DMA_CTRL (0x80 / 4)
|
||||
#define DMA_CTRL_REQUEST (1 << 31)
|
||||
#define DMA_CTRL_GRANT (1 << 30)
|
||||
#define DMA_CTRL_DELAY_MASK 0xf
|
||||
#define DMA_CTRL_DELAY_SHIFT 8
|
||||
#define DMA_CTRL_FREQ_MASK 0xf
|
||||
@ -178,10 +180,8 @@
|
||||
* 0: 4 bytes
|
||||
* 0x7FFFFF: 32M bytes
|
||||
*/
|
||||
#define DMA_DRAM_ADDR(s, val) ((s)->sdram_base | \
|
||||
((val) & (s)->ctrl->dma_dram_mask))
|
||||
#define DMA_FLASH_ADDR(s, val) ((s)->ctrl->flash_window_base | \
|
||||
((val) & (s)->ctrl->dma_flash_mask))
|
||||
#define DMA_DRAM_ADDR(s, val) ((val) & (s)->ctrl->dma_dram_mask)
|
||||
#define DMA_FLASH_ADDR(s, val) ((val) & (s)->ctrl->dma_flash_mask)
|
||||
#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
|
||||
|
||||
/* Flash opcodes. */
|
||||
@ -230,6 +230,7 @@ static uint32_t aspeed_smc_segment_to_reg(const AspeedSMCState *s,
|
||||
const AspeedSegments *seg);
|
||||
static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, uint32_t reg,
|
||||
AspeedSegments *seg);
|
||||
static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint32_t value);
|
||||
|
||||
/*
|
||||
* AST2600 definitions
|
||||
@ -259,6 +260,15 @@ static uint32_t aspeed_2600_smc_segment_to_reg(const AspeedSMCState *s,
|
||||
const AspeedSegments *seg);
|
||||
static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s,
|
||||
uint32_t reg, AspeedSegments *seg);
|
||||
static void aspeed_2600_smc_dma_ctrl(AspeedSMCState *s, uint32_t value);
|
||||
|
||||
#define ASPEED_SMC_FEATURE_DMA 0x1
|
||||
#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
|
||||
|
||||
static inline bool aspeed_smc_has_dma(const AspeedSMCState *s)
|
||||
{
|
||||
return !!(s->ctrl->features & ASPEED_SMC_FEATURE_DMA);
|
||||
}
|
||||
|
||||
static const AspeedSMCController controllers[] = {
|
||||
{
|
||||
@ -273,10 +283,11 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_legacy,
|
||||
.flash_window_base = ASPEED_SOC_SMC_FLASH_BASE,
|
||||
.flash_window_size = 0x6000000,
|
||||
.has_dma = false,
|
||||
.features = 0x0,
|
||||
.nregs = ASPEED_SMC_R_SMC_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.fmc-ast2400",
|
||||
.r_conf = R_CONF,
|
||||
@ -289,12 +300,13 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_fmc,
|
||||
.flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = true,
|
||||
.features = ASPEED_SMC_FEATURE_DMA,
|
||||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x1FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.spi1-ast2400",
|
||||
.r_conf = R_SPI_CONF,
|
||||
@ -307,10 +319,11 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_spi,
|
||||
.flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = false,
|
||||
.features = 0x0,
|
||||
.nregs = ASPEED_SMC_R_SPI_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.fmc-ast2500",
|
||||
.r_conf = R_CONF,
|
||||
@ -323,12 +336,13 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_ast2500_fmc,
|
||||
.flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = true,
|
||||
.features = ASPEED_SMC_FEATURE_DMA,
|
||||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x3FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.spi1-ast2500",
|
||||
.r_conf = R_CONF,
|
||||
@ -341,10 +355,11 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_ast2500_spi1,
|
||||
.flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
|
||||
.flash_window_size = 0x8000000,
|
||||
.has_dma = false,
|
||||
.features = 0x0,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.spi2-ast2500",
|
||||
.r_conf = R_CONF,
|
||||
@ -357,10 +372,11 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_ast2500_spi2,
|
||||
.flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE,
|
||||
.flash_window_size = 0x8000000,
|
||||
.has_dma = false,
|
||||
.features = 0x0,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.fmc-ast2600",
|
||||
.r_conf = R_CONF,
|
||||
@ -373,12 +389,13 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_ast2600_fmc,
|
||||
.flash_window_base = ASPEED26_SOC_FMC_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = true,
|
||||
.features = ASPEED_SMC_FEATURE_DMA,
|
||||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x3FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_2600_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_2600_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_2600_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.spi1-ast2600",
|
||||
.r_conf = R_CONF,
|
||||
@ -391,12 +408,14 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_ast2600_spi1,
|
||||
.flash_window_base = ASPEED26_SOC_SPI_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = true,
|
||||
.features = ASPEED_SMC_FEATURE_DMA |
|
||||
ASPEED_SMC_FEATURE_DMA_GRANT,
|
||||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x3FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_2600_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_2600_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_2600_smc_dma_ctrl,
|
||||
}, {
|
||||
.name = "aspeed.spi2-ast2600",
|
||||
.r_conf = R_CONF,
|
||||
@ -409,12 +428,14 @@ static const AspeedSMCController controllers[] = {
|
||||
.segments = aspeed_segments_ast2600_spi2,
|
||||
.flash_window_base = ASPEED26_SOC_SPI2_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = true,
|
||||
.features = ASPEED_SMC_FEATURE_DMA |
|
||||
ASPEED_SMC_FEATURE_DMA_GRANT,
|
||||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x3FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_2600_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_2600_smc_reg_to_segment,
|
||||
.dma_ctrl = aspeed_2600_smc_dma_ctrl,
|
||||
},
|
||||
};
|
||||
|
||||
@ -999,11 +1020,11 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
addr == R_CE_CMD_CTRL ||
|
||||
addr == R_INTR_CTRL ||
|
||||
addr == R_DUMMY_DATA ||
|
||||
(s->ctrl->has_dma && addr == R_DMA_CTRL) ||
|
||||
(s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) ||
|
||||
(s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) ||
|
||||
(s->ctrl->has_dma && addr == R_DMA_LEN) ||
|
||||
(s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
|
||||
(aspeed_smc_has_dma(s) && addr == R_DMA_CTRL) ||
|
||||
(aspeed_smc_has_dma(s) && addr == R_DMA_FLASH_ADDR) ||
|
||||
(aspeed_smc_has_dma(s) && addr == R_DMA_DRAM_ADDR) ||
|
||||
(aspeed_smc_has_dma(s) && addr == R_DMA_LEN) ||
|
||||
(aspeed_smc_has_dma(s) && addr == R_DMA_CHECKSUM) ||
|
||||
(addr >= R_SEG_ADDR0 &&
|
||||
addr < R_SEG_ADDR0 + s->ctrl->max_peripherals) ||
|
||||
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_peripherals)) {
|
||||
@ -1236,7 +1257,7 @@ static void aspeed_smc_dma_done(AspeedSMCState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl)
|
||||
static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint32_t dma_ctrl)
|
||||
{
|
||||
if (!(dma_ctrl & DMA_CTRL_ENABLE)) {
|
||||
s->regs[R_DMA_CTRL] = dma_ctrl;
|
||||
@ -1261,6 +1282,46 @@ static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl)
|
||||
aspeed_smc_dma_done(s);
|
||||
}
|
||||
|
||||
static inline bool aspeed_smc_dma_granted(AspeedSMCState *s)
|
||||
{
|
||||
if (!(s->ctrl->features & ASPEED_SMC_FEATURE_DMA_GRANT)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(s->regs[R_DMA_CTRL] & DMA_CTRL_GRANT)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA not granted\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void aspeed_2600_smc_dma_ctrl(AspeedSMCState *s, uint32_t dma_ctrl)
|
||||
{
|
||||
/* Preserve DMA bits */
|
||||
dma_ctrl |= s->regs[R_DMA_CTRL] & (DMA_CTRL_REQUEST | DMA_CTRL_GRANT);
|
||||
|
||||
if (dma_ctrl == 0xAEED0000) {
|
||||
/* automatically grant request */
|
||||
s->regs[R_DMA_CTRL] |= (DMA_CTRL_REQUEST | DMA_CTRL_GRANT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear request */
|
||||
if (dma_ctrl == 0xDEEA0000) {
|
||||
s->regs[R_DMA_CTRL] &= ~(DMA_CTRL_REQUEST | DMA_CTRL_GRANT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aspeed_smc_dma_granted(s)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA not granted\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
aspeed_smc_dma_ctrl(s, dma_ctrl);
|
||||
s->regs[R_DMA_CTRL] &= ~(DMA_CTRL_REQUEST | DMA_CTRL_GRANT);
|
||||
}
|
||||
|
||||
static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned int size)
|
||||
{
|
||||
@ -1292,13 +1353,16 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
s->regs[addr] = value & 0xff;
|
||||
} else if (addr == R_INTR_CTRL) {
|
||||
s->regs[addr] = value;
|
||||
} else if (s->ctrl->has_dma && addr == R_DMA_CTRL) {
|
||||
aspeed_smc_dma_ctrl(s, value);
|
||||
} else if (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) {
|
||||
} else if (aspeed_smc_has_dma(s) && addr == R_DMA_CTRL) {
|
||||
s->ctrl->dma_ctrl(s, value);
|
||||
} else if (aspeed_smc_has_dma(s) && addr == R_DMA_DRAM_ADDR &&
|
||||
aspeed_smc_dma_granted(s)) {
|
||||
s->regs[addr] = DMA_DRAM_ADDR(s, value);
|
||||
} else if (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) {
|
||||
} else if (aspeed_smc_has_dma(s) && addr == R_DMA_FLASH_ADDR &&
|
||||
aspeed_smc_dma_granted(s)) {
|
||||
s->regs[addr] = DMA_FLASH_ADDR(s, value);
|
||||
} else if (s->ctrl->has_dma && addr == R_DMA_LEN) {
|
||||
} else if (aspeed_smc_has_dma(s) && addr == R_DMA_LEN &&
|
||||
aspeed_smc_dma_granted(s)) {
|
||||
s->regs[addr] = DMA_LENGTH(value);
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
|
||||
@ -1386,7 +1450,9 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
|
||||
memory_region_init_io(&s->mmio_flash, OBJECT(s),
|
||||
&aspeed_smc_flash_default_ops, s, name,
|
||||
s->ctrl->flash_window_size);
|
||||
sysbus_init_mmio(sbd, &s->mmio_flash);
|
||||
memory_region_init_alias(&s->mmio_flash_alias, OBJECT(s), name,
|
||||
&s->mmio_flash, 0, s->ctrl->flash_window_size);
|
||||
sysbus_init_mmio(sbd, &s->mmio_flash_alias);
|
||||
|
||||
s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_peripherals);
|
||||
|
||||
@ -1412,7 +1478,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
/* DMA support */
|
||||
if (s->ctrl->has_dma) {
|
||||
if (aspeed_smc_has_dma(s)) {
|
||||
aspeed_smc_dma_setup(s, errp);
|
||||
}
|
||||
}
|
||||
@ -1432,7 +1498,6 @@ static const VMStateDescription vmstate_aspeed_smc = {
|
||||
static Property aspeed_smc_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
|
||||
DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false),
|
||||
DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
|
||||
DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr,
|
||||
TYPE_MEMORY_REGION, MemoryRegion *),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "hw/rtc/aspeed_rtc.h"
|
||||
#include "hw/i2c/aspeed_i2c.h"
|
||||
#include "hw/ssi/aspeed_smc.h"
|
||||
#include "hw/misc/aspeed_hace.h"
|
||||
#include "hw/watchdog/wdt_aspeed.h"
|
||||
#include "hw/net/ftgmac100.h"
|
||||
#include "target/arm/cpu.h"
|
||||
@ -50,6 +51,7 @@ struct AspeedSoCState {
|
||||
AspeedTimerCtrlState timerctrl;
|
||||
AspeedI2CState i2c;
|
||||
AspeedSCUState scu;
|
||||
AspeedHACEState hace;
|
||||
AspeedXDMAState xdma;
|
||||
AspeedSMCState fmc;
|
||||
AspeedSMCState spi[ASPEED_SPIS_NUM];
|
||||
@ -133,6 +135,7 @@ enum {
|
||||
ASPEED_DEV_XDMA,
|
||||
ASPEED_DEV_EMMC,
|
||||
ASPEED_DEV_KCS,
|
||||
ASPEED_DEV_HACE,
|
||||
};
|
||||
|
||||
#endif /* ASPEED_SOC_H */
|
||||
|
43
include/hw/misc/aspeed_hace.h
Normal file
43
include/hw/misc/aspeed_hace.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* ASPEED Hash and Crypto Engine
|
||||
*
|
||||
* Copyright (C) 2021 IBM Corp.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ASPEED_HACE_H
|
||||
#define ASPEED_HACE_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ASPEED_HACE "aspeed.hace"
|
||||
#define TYPE_ASPEED_AST2400_HACE TYPE_ASPEED_HACE "-ast2400"
|
||||
#define TYPE_ASPEED_AST2500_HACE TYPE_ASPEED_HACE "-ast2500"
|
||||
#define TYPE_ASPEED_AST2600_HACE TYPE_ASPEED_HACE "-ast2600"
|
||||
OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE)
|
||||
|
||||
#define ASPEED_HACE_NR_REGS (0x64 >> 2)
|
||||
|
||||
struct AspeedHACEState {
|
||||
SysBusDevice parent;
|
||||
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t regs[ASPEED_HACE_NR_REGS];
|
||||
|
||||
MemoryRegion *dram_mr;
|
||||
AddressSpace dram_as;
|
||||
};
|
||||
|
||||
|
||||
struct AspeedHACEClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint32_t src_mask;
|
||||
uint32_t dest_mask;
|
||||
uint32_t hash_mask;
|
||||
};
|
||||
|
||||
#endif /* _ASPEED_HACE_H_ */
|
@ -13,7 +13,10 @@
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_ASPEED_XDMA "aspeed.xdma"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(AspeedXDMAState, ASPEED_XDMA)
|
||||
#define TYPE_ASPEED_2400_XDMA TYPE_ASPEED_XDMA "-ast2400"
|
||||
#define TYPE_ASPEED_2500_XDMA TYPE_ASPEED_XDMA "-ast2500"
|
||||
#define TYPE_ASPEED_2600_XDMA TYPE_ASPEED_XDMA "-ast2600"
|
||||
OBJECT_DECLARE_TYPE(AspeedXDMAState, AspeedXDMAClass, ASPEED_XDMA)
|
||||
|
||||
#define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / sizeof(uint32_t))
|
||||
#define ASPEED_XDMA_REG_SIZE 0x7C
|
||||
@ -28,4 +31,16 @@ struct AspeedXDMAState {
|
||||
uint32_t regs[ASPEED_XDMA_NUM_REGS];
|
||||
};
|
||||
|
||||
struct AspeedXDMAClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint8_t cmdq_endp;
|
||||
uint8_t cmdq_wrp;
|
||||
uint8_t cmdq_rdp;
|
||||
uint8_t intr_ctrl;
|
||||
uint32_t intr_ctrl_mask;
|
||||
uint8_t intr_status;
|
||||
uint32_t intr_complete;
|
||||
};
|
||||
|
||||
#endif /* ASPEED_XDMA_H */
|
||||
|
@ -47,7 +47,7 @@ typedef struct AspeedSMCController {
|
||||
const AspeedSegments *segments;
|
||||
hwaddr flash_window_base;
|
||||
uint32_t flash_window_size;
|
||||
bool has_dma;
|
||||
uint32_t features;
|
||||
hwaddr dma_flash_mask;
|
||||
hwaddr dma_dram_mask;
|
||||
uint32_t nregs;
|
||||
@ -55,6 +55,7 @@ typedef struct AspeedSMCController {
|
||||
const AspeedSegments *seg);
|
||||
void (*reg_to_segment)(const struct AspeedSMCState *s, uint32_t reg,
|
||||
AspeedSegments *seg);
|
||||
void (*dma_ctrl)(struct AspeedSMCState *s, uint32_t value);
|
||||
} AspeedSMCController;
|
||||
|
||||
typedef struct AspeedSMCFlash {
|
||||
@ -84,6 +85,7 @@ struct AspeedSMCState {
|
||||
|
||||
MemoryRegion mmio;
|
||||
MemoryRegion mmio_flash;
|
||||
MemoryRegion mmio_flash_alias;
|
||||
|
||||
qemu_irq irq;
|
||||
int irqline;
|
||||
@ -103,9 +105,6 @@ struct AspeedSMCState {
|
||||
uint8_t r_timings;
|
||||
uint8_t conf_enable_w0;
|
||||
|
||||
/* for DMA support */
|
||||
uint64_t sdram_base;
|
||||
|
||||
AddressSpace flash_as;
|
||||
MemoryRegion *dram_mr;
|
||||
AddressSpace dram_as;
|
||||
|
@ -1010,6 +1010,74 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
self.vm.add_args('-dtb', self.workdir + '/day16/vexpress-v2p-ca9.dtb')
|
||||
self.do_test_advcal_2018('16', tar_hash, 'winter.zImage')
|
||||
|
||||
def test_arm_ast2400_palmetto_openbmc_v2_9_0(self):
|
||||
"""
|
||||
:avocado: tags=arch:arm
|
||||
:avocado: tags=machine:palmetto-bmc
|
||||
"""
|
||||
|
||||
image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
|
||||
'obmc-phosphor-image-palmetto.static.mtd')
|
||||
image_hash = ('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d')
|
||||
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
|
||||
algorithm='sha256')
|
||||
|
||||
self.do_test_arm_aspeed(image_path)
|
||||
|
||||
def test_arm_ast2500_romulus_openbmc_v2_9_0(self):
|
||||
"""
|
||||
:avocado: tags=arch:arm
|
||||
:avocado: tags=machine:romulus-bmc
|
||||
"""
|
||||
|
||||
image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
|
||||
'obmc-phosphor-image-romulus.static.mtd')
|
||||
image_hash = ('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25')
|
||||
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
|
||||
algorithm='sha256')
|
||||
|
||||
self.do_test_arm_aspeed(image_path)
|
||||
|
||||
def do_test_arm_aspeed(self, image):
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
|
||||
'-net', 'nic')
|
||||
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 test_arm_ast2600_debian(self):
|
||||
"""
|
||||
:avocado: tags=arch:arm
|
||||
:avocado: tags=machine:tacoma-bmc
|
||||
"""
|
||||
deb_url = ('http://snapshot.debian.org/archive/debian/'
|
||||
'20210302T203551Z/'
|
||||
'pool/main/l/linux/'
|
||||
'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb')
|
||||
deb_hash = 'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash,
|
||||
algorithm='sha256')
|
||||
kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.10.0-3-armmp')
|
||||
dtb_path = self.extract_from_deb(deb_path,
|
||||
'/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.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")
|
||||
|
||||
def test_m68k_mcf5208evb(self):
|
||||
"""
|
||||
:avocado: tags=arch:m68k
|
||||
|
469
tests/qtest/aspeed_hace-test.c
Normal file
469
tests/qtest/aspeed_hace-test.c
Normal file
@ -0,0 +1,469 @@
|
||||
/*
|
||||
* QTest testcase for the ASPEED Hash and Crypto Engine
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2021 IBM Corp.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "libqos/libqtest.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
#define HACE_CMD 0x10
|
||||
#define HACE_SHA_BE_EN BIT(3)
|
||||
#define HACE_MD5_LE_EN BIT(2)
|
||||
#define HACE_ALGO_MD5 0
|
||||
#define HACE_ALGO_SHA1 BIT(5)
|
||||
#define HACE_ALGO_SHA224 BIT(6)
|
||||
#define HACE_ALGO_SHA256 (BIT(4) | BIT(6))
|
||||
#define HACE_ALGO_SHA512 (BIT(5) | BIT(6))
|
||||
#define HACE_ALGO_SHA384 (BIT(5) | BIT(6) | BIT(10))
|
||||
#define HACE_SG_EN BIT(18)
|
||||
|
||||
#define HACE_STS 0x1c
|
||||
#define HACE_RSA_ISR BIT(13)
|
||||
#define HACE_CRYPTO_ISR BIT(12)
|
||||
#define HACE_HASH_ISR BIT(9)
|
||||
#define HACE_RSA_BUSY BIT(2)
|
||||
#define HACE_CRYPTO_BUSY BIT(1)
|
||||
#define HACE_HASH_BUSY BIT(0)
|
||||
#define HACE_HASH_SRC 0x20
|
||||
#define HACE_HASH_DIGEST 0x24
|
||||
#define HACE_HASH_KEY_BUFF 0x28
|
||||
#define HACE_HASH_DATA_LEN 0x2c
|
||||
#define HACE_HASH_CMD 0x30
|
||||
/* Scatter-Gather Hash */
|
||||
#define SG_LIST_LEN_LAST BIT(31)
|
||||
struct AspeedSgList {
|
||||
uint32_t len;
|
||||
uint32_t addr;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/*
|
||||
* Test vector is the ascii "abc"
|
||||
*
|
||||
* Expected results were generated using command line utitiles:
|
||||
*
|
||||
* echo -n -e 'abc' | dd of=/tmp/test
|
||||
* for hash in sha512sum sha256sum md5sum; do $hash /tmp/test; done
|
||||
*
|
||||
*/
|
||||
static const uint8_t test_vector[] = {0x61, 0x62, 0x63};
|
||||
|
||||
static const uint8_t test_result_sha512[] = {
|
||||
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49,
|
||||
0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
|
||||
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
|
||||
0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
|
||||
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f,
|
||||
0xa5, 0x4c, 0xa4, 0x9f};
|
||||
|
||||
static const uint8_t test_result_sha256[] = {
|
||||
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
|
||||
0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
|
||||
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad};
|
||||
|
||||
static const uint8_t test_result_md5[] = {
|
||||
0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d,
|
||||
0x28, 0xe1, 0x7f, 0x72};
|
||||
|
||||
/*
|
||||
* The Scatter-Gather Test vector is the ascii "abc" "def" "ghi", broken
|
||||
* into blocks of 3 characters as shown
|
||||
*
|
||||
* Expected results were generated using command line utitiles:
|
||||
*
|
||||
* echo -n -e 'abcdefghijkl' | dd of=/tmp/test
|
||||
* for hash in sha512sum sha256sum; do $hash /tmp/test; done
|
||||
*
|
||||
*/
|
||||
static const uint8_t test_vector_sg1[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
|
||||
static const uint8_t test_vector_sg2[] = {0x67, 0x68, 0x69};
|
||||
static const uint8_t test_vector_sg3[] = {0x6a, 0x6b, 0x6c};
|
||||
|
||||
static const uint8_t test_result_sg_sha512[] = {
|
||||
0x17, 0x80, 0x7c, 0x72, 0x8e, 0xe3, 0xba, 0x35, 0xe7, 0xcf, 0x7a, 0xf8,
|
||||
0x23, 0x11, 0x6d, 0x26, 0xe4, 0x1e, 0x5d, 0x4d, 0x6c, 0x2f, 0xf1, 0xf3,
|
||||
0x72, 0x0d, 0x3d, 0x96, 0xaa, 0xcb, 0x6f, 0x69, 0xde, 0x64, 0x2e, 0x63,
|
||||
0xd5, 0xb7, 0x3f, 0xc3, 0x96, 0xc1, 0x2b, 0xe3, 0x8b, 0x2b, 0xd5, 0xd8,
|
||||
0x84, 0x25, 0x7c, 0x32, 0xc8, 0xf6, 0xd0, 0x85, 0x4a, 0xe6, 0xb5, 0x40,
|
||||
0xf8, 0x6d, 0xda, 0x2e};
|
||||
|
||||
static const uint8_t test_result_sg_sha256[] = {
|
||||
0xd6, 0x82, 0xed, 0x4c, 0xa4, 0xd9, 0x89, 0xc1, 0x34, 0xec, 0x94, 0xf1,
|
||||
0x55, 0x1e, 0x1e, 0xc5, 0x80, 0xdd, 0x6d, 0x5a, 0x6e, 0xcd, 0xe9, 0xf3,
|
||||
0xd3, 0x5e, 0x6e, 0x4a, 0x71, 0x7f, 0xbd, 0xe4};
|
||||
|
||||
|
||||
static void write_regs(QTestState *s, uint32_t base, uint32_t src,
|
||||
uint32_t length, uint32_t out, uint32_t method)
|
||||
{
|
||||
qtest_writel(s, base + HACE_HASH_SRC, src);
|
||||
qtest_writel(s, base + HACE_HASH_DIGEST, out);
|
||||
qtest_writel(s, base + HACE_HASH_DATA_LEN, length);
|
||||
qtest_writel(s, base + HACE_HASH_CMD, HACE_SHA_BE_EN | method);
|
||||
}
|
||||
|
||||
static void test_md5(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
|
||||
uint32_t digest_addr = src_addr + 0x01000000;
|
||||
uint8_t digest[16] = {0};
|
||||
|
||||
/* Check engine is idle, no busy or irq bits set */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Write test vector into memory */
|
||||
qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));
|
||||
|
||||
write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_MD5);
|
||||
|
||||
/* Check hash IRQ status is asserted */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
|
||||
|
||||
/* Clear IRQ status and check status is deasserted */
|
||||
qtest_writel(s, base + HACE_STS, 0x00000200);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Read computed digest from memory */
|
||||
qtest_memread(s, digest_addr, digest, sizeof(digest));
|
||||
|
||||
/* Check result of computation */
|
||||
g_assert_cmpmem(digest, sizeof(digest),
|
||||
test_result_md5, sizeof(digest));
|
||||
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
static void test_sha256(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
|
||||
const uint32_t digest_addr = src_addr + 0x1000000;
|
||||
uint8_t digest[32] = {0};
|
||||
|
||||
/* Check engine is idle, no busy or irq bits set */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Write test vector into memory */
|
||||
qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));
|
||||
|
||||
write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_SHA256);
|
||||
|
||||
/* Check hash IRQ status is asserted */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
|
||||
|
||||
/* Clear IRQ status and check status is deasserted */
|
||||
qtest_writel(s, base + HACE_STS, 0x00000200);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Read computed digest from memory */
|
||||
qtest_memread(s, digest_addr, digest, sizeof(digest));
|
||||
|
||||
/* Check result of computation */
|
||||
g_assert_cmpmem(digest, sizeof(digest),
|
||||
test_result_sha256, sizeof(digest));
|
||||
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
static void test_sha512(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
|
||||
const uint32_t digest_addr = src_addr + 0x1000000;
|
||||
uint8_t digest[64] = {0};
|
||||
|
||||
/* Check engine is idle, no busy or irq bits set */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Write test vector into memory */
|
||||
qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));
|
||||
|
||||
write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_SHA512);
|
||||
|
||||
/* Check hash IRQ status is asserted */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
|
||||
|
||||
/* Clear IRQ status and check status is deasserted */
|
||||
qtest_writel(s, base + HACE_STS, 0x00000200);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Read computed digest from memory */
|
||||
qtest_memread(s, digest_addr, digest, sizeof(digest));
|
||||
|
||||
/* Check result of computation */
|
||||
g_assert_cmpmem(digest, sizeof(digest),
|
||||
test_result_sha512, sizeof(digest));
|
||||
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
static void test_sha256_sg(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
|
||||
const uint32_t src_addr_1 = src_addr + 0x1000000;
|
||||
const uint32_t src_addr_2 = src_addr + 0x2000000;
|
||||
const uint32_t src_addr_3 = src_addr + 0x3000000;
|
||||
const uint32_t digest_addr = src_addr + 0x4000000;
|
||||
uint8_t digest[32] = {0};
|
||||
struct AspeedSgList array[] = {
|
||||
{ cpu_to_le32(sizeof(test_vector_sg1)),
|
||||
cpu_to_le32(src_addr_1) },
|
||||
{ cpu_to_le32(sizeof(test_vector_sg2)),
|
||||
cpu_to_le32(src_addr_2) },
|
||||
{ cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST),
|
||||
cpu_to_le32(src_addr_3) },
|
||||
};
|
||||
|
||||
/* Check engine is idle, no busy or irq bits set */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Write test vector into memory */
|
||||
qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1));
|
||||
qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2));
|
||||
qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3));
|
||||
qtest_memwrite(s, src_addr, array, sizeof(array));
|
||||
|
||||
write_regs(s, base, src_addr,
|
||||
(sizeof(test_vector_sg1)
|
||||
+ sizeof(test_vector_sg2)
|
||||
+ sizeof(test_vector_sg3)),
|
||||
digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN);
|
||||
|
||||
/* Check hash IRQ status is asserted */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
|
||||
|
||||
/* Clear IRQ status and check status is deasserted */
|
||||
qtest_writel(s, base + HACE_STS, 0x00000200);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Read computed digest from memory */
|
||||
qtest_memread(s, digest_addr, digest, sizeof(digest));
|
||||
|
||||
/* Check result of computation */
|
||||
g_assert_cmpmem(digest, sizeof(digest),
|
||||
test_result_sg_sha256, sizeof(digest));
|
||||
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
static void test_sha512_sg(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
|
||||
const uint32_t src_addr_1 = src_addr + 0x1000000;
|
||||
const uint32_t src_addr_2 = src_addr + 0x2000000;
|
||||
const uint32_t src_addr_3 = src_addr + 0x3000000;
|
||||
const uint32_t digest_addr = src_addr + 0x4000000;
|
||||
uint8_t digest[64] = {0};
|
||||
struct AspeedSgList array[] = {
|
||||
{ cpu_to_le32(sizeof(test_vector_sg1)),
|
||||
cpu_to_le32(src_addr_1) },
|
||||
{ cpu_to_le32(sizeof(test_vector_sg2)),
|
||||
cpu_to_le32(src_addr_2) },
|
||||
{ cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST),
|
||||
cpu_to_le32(src_addr_3) },
|
||||
};
|
||||
|
||||
/* Check engine is idle, no busy or irq bits set */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Write test vector into memory */
|
||||
qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1));
|
||||
qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2));
|
||||
qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3));
|
||||
qtest_memwrite(s, src_addr, array, sizeof(array));
|
||||
|
||||
write_regs(s, base, src_addr,
|
||||
(sizeof(test_vector_sg1)
|
||||
+ sizeof(test_vector_sg2)
|
||||
+ sizeof(test_vector_sg3)),
|
||||
digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN);
|
||||
|
||||
/* Check hash IRQ status is asserted */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
|
||||
|
||||
/* Clear IRQ status and check status is deasserted */
|
||||
qtest_writel(s, base + HACE_STS, 0x00000200);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
|
||||
|
||||
/* Read computed digest from memory */
|
||||
qtest_memread(s, digest_addr, digest, sizeof(digest));
|
||||
|
||||
/* Check result of computation */
|
||||
g_assert_cmpmem(digest, sizeof(digest),
|
||||
test_result_sg_sha512, sizeof(digest));
|
||||
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
struct masks {
|
||||
uint32_t src;
|
||||
uint32_t dest;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
static const struct masks ast2600_masks = {
|
||||
.src = 0x7fffffff,
|
||||
.dest = 0x7ffffff8,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static const struct masks ast2500_masks = {
|
||||
.src = 0x3fffffff,
|
||||
.dest = 0x3ffffff8,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static const struct masks ast2400_masks = {
|
||||
.src = 0x0fffffff,
|
||||
.dest = 0x0ffffff8,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static void test_addresses(const char *machine, const uint32_t base,
|
||||
const struct masks *expected)
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
|
||||
/*
|
||||
* Check command mode is zero, meaning engine is in direct access mode,
|
||||
* as this affects the masking behavior of the HASH_SRC register.
|
||||
*/
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_CMD), ==, 0);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0);
|
||||
|
||||
|
||||
/* Check that the address masking is correct */
|
||||
qtest_writel(s, base + HACE_HASH_SRC, 0xffffffff);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, expected->src);
|
||||
|
||||
qtest_writel(s, base + HACE_HASH_DIGEST, 0xffffffff);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, expected->dest);
|
||||
|
||||
qtest_writel(s, base + HACE_HASH_DATA_LEN, 0xffffffff);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, expected->len);
|
||||
|
||||
/* Reset to zero */
|
||||
qtest_writel(s, base + HACE_HASH_SRC, 0);
|
||||
qtest_writel(s, base + HACE_HASH_DIGEST, 0);
|
||||
qtest_writel(s, base + HACE_HASH_DATA_LEN, 0);
|
||||
|
||||
/* Check that all bits are now zero */
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0);
|
||||
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
/* ast2600 */
|
||||
static void test_md5_ast2600(void)
|
||||
{
|
||||
test_md5("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_sha256_ast2600(void)
|
||||
{
|
||||
test_sha256("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_sha256_sg_ast2600(void)
|
||||
{
|
||||
test_sha256_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_sha512_ast2600(void)
|
||||
{
|
||||
test_sha512("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_sha512_sg_ast2600(void)
|
||||
{
|
||||
test_sha512_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_addresses_ast2600(void)
|
||||
{
|
||||
test_addresses("-machine ast2600-evb", 0x1e6d0000, &ast2600_masks);
|
||||
}
|
||||
|
||||
/* ast2500 */
|
||||
static void test_md5_ast2500(void)
|
||||
{
|
||||
test_md5("-machine ast2500-evb", 0x1e6e3000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_sha256_ast2500(void)
|
||||
{
|
||||
test_sha256("-machine ast2500-evb", 0x1e6e3000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_sha512_ast2500(void)
|
||||
{
|
||||
test_sha512("-machine ast2500-evb", 0x1e6e3000, 0x80000000);
|
||||
}
|
||||
|
||||
static void test_addresses_ast2500(void)
|
||||
{
|
||||
test_addresses("-machine ast2500-evb", 0x1e6e3000, &ast2500_masks);
|
||||
}
|
||||
|
||||
/* ast2400 */
|
||||
static void test_md5_ast2400(void)
|
||||
{
|
||||
test_md5("-machine palmetto-bmc", 0x1e6e3000, 0x40000000);
|
||||
}
|
||||
|
||||
static void test_sha256_ast2400(void)
|
||||
{
|
||||
test_sha256("-machine palmetto-bmc", 0x1e6e3000, 0x40000000);
|
||||
}
|
||||
|
||||
static void test_sha512_ast2400(void)
|
||||
{
|
||||
test_sha512("-machine palmetto-bmc", 0x1e6e3000, 0x40000000);
|
||||
}
|
||||
|
||||
static void test_addresses_ast2400(void)
|
||||
{
|
||||
test_addresses("-machine palmetto-bmc", 0x1e6e3000, &ast2400_masks);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
qtest_add_func("ast2600/hace/addresses", test_addresses_ast2600);
|
||||
qtest_add_func("ast2600/hace/sha512", test_sha512_ast2600);
|
||||
qtest_add_func("ast2600/hace/sha256", test_sha256_ast2600);
|
||||
qtest_add_func("ast2600/hace/md5", test_md5_ast2600);
|
||||
|
||||
qtest_add_func("ast2600/hace/sha512_sg", test_sha512_sg_ast2600);
|
||||
qtest_add_func("ast2600/hace/sha256_sg", test_sha256_sg_ast2600);
|
||||
|
||||
qtest_add_func("ast2500/hace/addresses", test_addresses_ast2500);
|
||||
qtest_add_func("ast2500/hace/sha512", test_sha512_ast2500);
|
||||
qtest_add_func("ast2500/hace/sha256", test_sha256_ast2500);
|
||||
qtest_add_func("ast2500/hace/md5", test_md5_ast2500);
|
||||
|
||||
qtest_add_func("ast2400/hace/addresses", test_addresses_ast2400);
|
||||
qtest_add_func("ast2400/hace/sha512", test_sha512_ast2400);
|
||||
qtest_add_func("ast2400/hace/sha256", test_sha256_ast2400);
|
||||
qtest_add_func("ast2400/hace/md5", test_md5_ast2400);
|
||||
|
||||
return g_test_run();
|
||||
}
|
@ -367,12 +367,12 @@ int main(int argc, char **argv)
|
||||
"-drive file=%s,format=raw,if=mtd",
|
||||
tmp_path);
|
||||
|
||||
qtest_add_func("/m25p80/read_jedec", test_read_jedec);
|
||||
qtest_add_func("/m25p80/erase_sector", test_erase_sector);
|
||||
qtest_add_func("/m25p80/erase_all", test_erase_all);
|
||||
qtest_add_func("/m25p80/write_page", test_write_page);
|
||||
qtest_add_func("/m25p80/read_page_mem", test_read_page_mem);
|
||||
qtest_add_func("/m25p80/write_page_mem", test_write_page_mem);
|
||||
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);
|
||||
|
||||
ret = g_test_run();
|
||||
|
@ -161,16 +161,19 @@ qtests_npcm7xx = \
|
||||
'npcm7xx_timer-test',
|
||||
'npcm7xx_watchdog_timer-test'] + \
|
||||
(slirp.found() ? ['npcm7xx_emc-test'] : [])
|
||||
qtests_aspeed = \
|
||||
['aspeed_hace-test',
|
||||
'aspeed_smc-test']
|
||||
qtests_arm = \
|
||||
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed : []) + \
|
||||
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
|
||||
['arm-cpu-features',
|
||||
'microbit-test',
|
||||
'm25p80-test',
|
||||
'test-arm-mptimer',
|
||||
'boot-serial-test',
|
||||
'hexloader-test']
|
||||
|
Loading…
Reference in New Issue
Block a user