159 changes: 111 additions & 48 deletions hw/arm/aspeed.c
Expand Up @@ -241,12 +241,9 @@ static void aspeed_reset_secondary(ARMCPU *cpu,
cpu_set_pc(cs, info->smp_loader_start);
}

#define FIRMWARE_ADDR 0x0

static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size,
Error **errp)
{
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
g_autofree void *storage = NULL;
int64_t size;

Expand All @@ -272,6 +269,22 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
}

/*
* Create a ROM and copy the flash contents at the expected address
* (0x0). Boots faster than execute-in-place.
*/
static void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk,
uint64_t rom_size)
{
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);

memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", rom_size,
&error_abort);
memory_region_add_subregion_overlap(&soc->spi_boot_container, 0,
boot_rom, 1);
write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, &error_abort);
}

void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
unsigned int count, int unit0)
{
Expand All @@ -293,7 +306,7 @@ void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal);

cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
qdev_connect_gpio_out_named(DEVICE(s), "cs", i, cs_line);
}
}

Expand Down Expand Up @@ -332,7 +345,6 @@ static void aspeed_machine_init(MachineState *machine)
AspeedMachineState *bmc = ASPEED_MACHINE(machine);
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
AspeedSoCClass *sc;
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
int i;
NICInfo *nd = &nd_table[0];

Expand Down Expand Up @@ -382,32 +394,6 @@ static void aspeed_machine_init(MachineState *machine)
bmc->spi_model ? bmc->spi_model : amc->spi_model,
1, amc->num_cs);

/* Install first FMC flash content as a boot rom. */
if (drive0) {
AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0];
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
uint64_t size = memory_region_size(&fl->mmio);

/*
* create a ROM region using the default mapping window size of
* the flash module. The window size is 64MB for the AST2400
* SoC and 128MB for the AST2500 SoC, which is twice as big as
* needed by the flash modules of the Aspeed machines.
*/
if (ASPEED_MACHINE(machine)->mmio_exec) {
memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
&fl->mmio, 0, size);
memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
boot_rom);
} else {
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
size, &error_abort);
memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
boot_rom);
write_boot_rom(drive0, FIRMWARE_ADDR, size, &error_abort);
}
}

if (machine->kernel_filename && sc->num_cpus > 1) {
/* With no u-boot we must set up a boot stub for the secondary CPU */
MemoryRegion *smpboot = g_new(MemoryRegion, 1);
Expand Down Expand Up @@ -438,6 +424,16 @@ static void aspeed_machine_init(MachineState *machine)
drive_get(IF_SD, 0, bmc->soc.sdhci.num_slots));
}

if (!bmc->mmio_exec) {
DriveInfo *mtd0 = drive_get(IF_MTD, 0, 0);

if (mtd0) {
uint64_t rom_size = memory_region_size(&bmc->soc.spi_boot);
aspeed_install_boot_rom(&bmc->soc, blk_by_legacy_dinfo(mtd0),
rom_size);
}
}

arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
}

Expand Down Expand Up @@ -521,6 +517,15 @@ static void ast2600_evb_i2c_init(AspeedMachineState *bmc)
TYPE_TMP105, 0x4d);
}

static void yosemitev2_bmc_i2c_init(AspeedMachineState *bmc)
{
AspeedSoCState *soc = &bmc->soc;

at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 4), 0x51, 128 * KiB);
at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 128 * KiB,
yosemitev2_bmc_fruid, yosemitev2_bmc_fruid_len);
}

static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
{
AspeedSoCState *soc = &bmc->soc;
Expand All @@ -530,6 +535,15 @@ static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
}

static void tiogapass_bmc_i2c_init(AspeedMachineState *bmc)
{
AspeedSoCState *soc = &bmc->soc;

at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 4), 0x54, 128 * KiB);
at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 6), 0x54, 128 * KiB,
tiogapass_bmc_fruid, tiogapass_bmc_fruid_len);
}

static void create_pca9552(AspeedSoCState *soc, int bus_id, int addr)
{
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, bus_id),
Expand Down Expand Up @@ -840,42 +854,46 @@ static void fuji_bmc_i2c_init(AspeedMachineState *bmc)
i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4c);
i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4d);

at24c_eeprom_init(i2c[19], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[20], 0x50, 2 * KiB);
at24c_eeprom_init(i2c[22], 0x52, 2 * KiB);
/*
* EEPROM 24c64 size is 64Kbits or 8 Kbytes
* 24c02 size is 2Kbits or 256 bytes
*/
at24c_eeprom_init(i2c[19], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[20], 0x50, 256);
at24c_eeprom_init(i2c[22], 0x52, 256);

i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x48);
i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x49);
i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x4a);
i2c_slave_create_simple(i2c[3], TYPE_TMP422, 0x4c);

at24c_eeprom_init(i2c[8], 0x51, 64 * KiB);
at24c_eeprom_init(i2c[8], 0x51, 8 * KiB);
i2c_slave_create_simple(i2c[8], TYPE_LM75, 0x4a);

i2c_slave_create_simple(i2c[50], TYPE_LM75, 0x4c);
at24c_eeprom_init(i2c[50], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[50], 0x52, 8 * KiB);
i2c_slave_create_simple(i2c[51], TYPE_TMP75, 0x48);
i2c_slave_create_simple(i2c[52], TYPE_TMP75, 0x49);

i2c_slave_create_simple(i2c[59], TYPE_TMP75, 0x48);
i2c_slave_create_simple(i2c[60], TYPE_TMP75, 0x49);

at24c_eeprom_init(i2c[65], 0x53, 64 * KiB);
at24c_eeprom_init(i2c[65], 0x53, 8 * KiB);
i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x49);
i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x48);
at24c_eeprom_init(i2c[68], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[69], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[70], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[71], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[68], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[69], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[70], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[71], 0x52, 8 * KiB);

at24c_eeprom_init(i2c[73], 0x53, 64 * KiB);
at24c_eeprom_init(i2c[73], 0x53, 8 * KiB);
i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x49);
i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x48);
at24c_eeprom_init(i2c[76], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[77], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[78], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[79], 0x52, 64 * KiB);
at24c_eeprom_init(i2c[28], 0x50, 2 * KiB);
at24c_eeprom_init(i2c[76], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[77], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[78], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[79], 0x52, 8 * KiB);
at24c_eeprom_init(i2c[28], 0x50, 256);

for (int i = 0; i < 8; i++) {
at24c_eeprom_init(i2c[81 + i * 8], 0x56, 64 * KiB);
Expand Down Expand Up @@ -1174,6 +1192,24 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
aspeed_soc_num_cpus(amc->soc_name);
};

static void aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);

mc->desc = "Facebook YosemiteV2 BMC (ARM1176)";
amc->soc_name = "ast2500-a1";
amc->hw_strap1 = AST2500_EVB_HW_STRAP1;
amc->hw_strap2 = 0;
amc->fmc_model = "n25q256a";
amc->spi_model = "mx25l25635e";
amc->num_cs = 2;
amc->i2c_init = yosemitev2_bmc_i2c_init;
mc->default_ram_size = 512 * MiB;
mc->default_cpus = mc->min_cpus = mc->max_cpus =
aspeed_soc_num_cpus(amc->soc_name);
};

static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
Expand All @@ -1191,6 +1227,25 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
aspeed_soc_num_cpus(amc->soc_name);
};

static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);

mc->desc = "Facebook Tiogapass BMC (ARM1176)";
amc->soc_name = "ast2500-a1";
amc->hw_strap1 = AST2500_EVB_HW_STRAP1;
amc->hw_strap2 = 0;
amc->fmc_model = "n25q256a";
amc->spi_model = "mx25l25635e";
amc->num_cs = 2;
amc->i2c_init = tiogapass_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);
aspeed_soc_num_cpus(amc->soc_name);
};

static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
Expand Down Expand Up @@ -1562,10 +1617,18 @@ static const TypeInfo aspeed_machine_types[] = {
.name = MACHINE_TYPE_NAME("ast2600-evb"),
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_ast2600_evb_class_init,
}, {
.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,
.class_init = aspeed_machine_tiogapass_class_init,
}, {
.name = MACHINE_TYPE_NAME("g220a-bmc"),
.parent = TYPE_ASPEED_MACHINE,
Expand Down
13 changes: 13 additions & 0 deletions hw/arm/aspeed_ast2600.c
Expand Up @@ -21,6 +21,7 @@
#define ASPEED_SOC_DPMCU_SIZE 0x00040000

static const hwaddr aspeed_soc_ast2600_memmap[] = {
[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR,
[ASPEED_DEV_SRAM] = 0x10000000,
[ASPEED_DEV_DPMCU] = 0x18000000,
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
Expand Down Expand Up @@ -282,6 +283,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
qemu_irq irq;
g_autofree char *sram_name = NULL;

/* Default boot region (SPI memory or ROMs) */
memory_region_init(&s->spi_boot_container, OBJECT(s),
"aspeed.spi_boot_container", 0x10000000);
memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SPI_BOOT],
&s->spi_boot_container);

/* IO space */
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
sc->memmap[ASPEED_DEV_IOMEM],
Expand Down Expand Up @@ -431,6 +438,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_FMC));

/* Set up an alias on the FMC CE0 region (boot default) */
MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
memory_region_init_alias(&s->spi_boot, OBJECT(s), "aspeed.spi_boot",
fmc0_mmio, 0, memory_region_size(fmc0_mmio));
memory_region_add_subregion(&s->spi_boot_container, 0x0, &s->spi_boot);

/* SPI */
for (i = 0; i < sc->spis_num; i++) {
object_property_set_link(OBJECT(&s->spi[i]), "dram",
Expand Down
45 changes: 45 additions & 0 deletions hw/arm/aspeed_eeprom.c
Expand Up @@ -6,6 +6,27 @@

#include "aspeed_eeprom.h"

/* Tiogapass BMC FRU */
const uint8_t tiogapass_bmc_fruid[] = {
0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x00, 0x36,
0xe6, 0xd0, 0xc6, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x42, 0x4d,
0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x4d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0xcd, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e,
0x30, 0xc9, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc1, 0x39, 0x01, 0x0c, 0x00, 0xc6,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x54, 0x69, 0x6f, 0x67, 0x61,
0x20, 0x50, 0x61, 0x73, 0x73, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65,
0x32, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0xc4, 0x58, 0x58, 0x58, 0x32, 0xcd, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc7,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e, 0x30, 0xc9,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc8, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45,
};

const uint8_t fby35_nic_fruid[] = {
0x01, 0x00, 0x00, 0x01, 0x0f, 0x20, 0x00, 0xcf, 0x01, 0x0e, 0x19, 0xd7,
0x5e, 0xcf, 0xc8, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xdd,
Expand Down Expand Up @@ -77,6 +98,30 @@ const uint8_t fby35_bmc_fruid[] = {
0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45,
};

/* Yosemite V2 BMC FRU */
const uint8_t yosemitev2_bmc_fruid[] = {
0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x00, 0x36,
0xe6, 0xd0, 0xc6, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x42, 0x4d,
0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x4d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0xcd, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e,
0x30, 0xc9, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc1, 0x39, 0x01, 0x0c, 0x00, 0xc6,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x59, 0x6f, 0x73, 0x65, 0x6d,
0x69, 0x74, 0x65, 0x20, 0x56, 0x32, 0x2e, 0x30, 0x20, 0x45, 0x56, 0x54,
0x32, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0xc4, 0x45, 0x56, 0x54, 0x32, 0xcd, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc7,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e, 0x30, 0xc9,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc8, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45,
};

const size_t tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid);
const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid);
const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid);
const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid);

const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid);
6 changes: 6 additions & 0 deletions hw/arm/aspeed_eeprom.h
Expand Up @@ -9,11 +9,17 @@

#include "qemu/osdep.h"

extern const uint8_t tiogapass_bmc_fruid[];
extern const size_t tiogapass_bmc_fruid_len;

extern const uint8_t fby35_nic_fruid[];
extern const uint8_t fby35_bb_fruid[];
extern const uint8_t fby35_bmc_fruid[];
extern const size_t fby35_nic_fruid_len;
extern const size_t fby35_bb_fruid_len;
extern const size_t fby35_bmc_fruid_len;

extern const uint8_t yosemitev2_bmc_fruid[];
extern const size_t yosemitev2_bmc_fruid_len;

#endif
14 changes: 14 additions & 0 deletions hw/arm/aspeed_soc.c
Expand Up @@ -25,6 +25,7 @@
#define ASPEED_SOC_IOMEM_SIZE 0x00200000

static const hwaddr aspeed_soc_ast2400_memmap[] = {
[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR,
[ASPEED_DEV_IOMEM] = 0x1E600000,
[ASPEED_DEV_FMC] = 0x1E620000,
[ASPEED_DEV_SPI1] = 0x1E630000,
Expand Down Expand Up @@ -59,6 +60,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
};

static const hwaddr aspeed_soc_ast2500_memmap[] = {
[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR,
[ASPEED_DEV_IOMEM] = 0x1E600000,
[ASPEED_DEV_FMC] = 0x1E620000,
[ASPEED_DEV_SPI1] = 0x1E630000,
Expand Down Expand Up @@ -245,6 +247,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
Error *err = NULL;
g_autofree char *sram_name = NULL;

/* Default boot region (SPI memory or ROMs) */
memory_region_init(&s->spi_boot_container, OBJECT(s),
"aspeed.spi_boot_container", 0x10000000);
memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SPI_BOOT],
&s->spi_boot_container);

/* IO space */
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
sc->memmap[ASPEED_DEV_IOMEM],
Expand Down Expand Up @@ -354,6 +362,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_FMC));

/* Set up an alias on the FMC CE0 region (boot default) */
MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
memory_region_init_alias(&s->spi_boot, OBJECT(s), "aspeed.spi_boot",
fmc0_mmio, 0, memory_region_size(fmc0_mmio));
memory_region_add_subregion(&s->spi_boot_container, 0x0, &s->spi_boot);

/* SPI */
for (i = 0; i < sc->spis_num; i++) {
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
Expand Down
8 changes: 1 addition & 7 deletions hw/arm/fby35.c
Expand Up @@ -100,13 +100,7 @@ static void fby35_bmc_init(Fby35State *s)
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
uint64_t size = memory_region_size(&fl->mmio);

if (s->mmio_exec) {
memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
&fl->mmio, 0, size);
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
boot_rom);
} else {

if (!s->mmio_exec) {
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
size, &error_abort);
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
Expand Down
2 changes: 2 additions & 0 deletions hw/i2c/aspeed_i2c.c
Expand Up @@ -550,6 +550,8 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
}
SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_STOP_CMD, 0);
aspeed_i2c_set_state(bus, I2CD_IDLE);

i2c_schedule_pending_master(bus->bus);
}

if (aspeed_i2c_bus_pkt_mode_en(bus)) {
Expand Down
37 changes: 22 additions & 15 deletions hw/i2c/core.c
Expand Up @@ -185,22 +185,39 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, bool is_recv)

void i2c_bus_master(I2CBus *bus, QEMUBH *bh)
{
if (i2c_bus_busy(bus)) {
I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1);
node->bh = bh;
I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1);
node->bh = bh;

QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry);
}

void i2c_schedule_pending_master(I2CBus *bus)
{
I2CPendingMaster *node;

QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry);
if (i2c_bus_busy(bus)) {
/* someone is already controlling the bus; wait for it to release it */
return;
}

if (QSIMPLEQ_EMPTY(&bus->pending_masters)) {
return;
}

bus->bh = bh;
node = QSIMPLEQ_FIRST(&bus->pending_masters);
bus->bh = node->bh;

QSIMPLEQ_REMOVE_HEAD(&bus->pending_masters, entry);
g_free(node);

qemu_bh_schedule(bus->bh);
}

void i2c_bus_release(I2CBus *bus)
{
bus->bh = NULL;

i2c_schedule_pending_master(bus);
}

int i2c_start_recv(I2CBus *bus, uint8_t address)
Expand Down Expand Up @@ -234,16 +251,6 @@ void i2c_end_transfer(I2CBus *bus)
g_free(node);
}
bus->broadcast = false;

if (!QSIMPLEQ_EMPTY(&bus->pending_masters)) {
I2CPendingMaster *node = QSIMPLEQ_FIRST(&bus->pending_masters);
bus->bh = node->bh;

QSIMPLEQ_REMOVE_HEAD(&bus->pending_masters, entry);
g_free(node);

qemu_bh_schedule(bus->bh);
}
}

int i2c_send(I2CBus *bus, uint8_t data)
Expand Down
3 changes: 2 additions & 1 deletion hw/loongarch/acpi-build.c
Expand Up @@ -260,6 +260,7 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
AML_SYSTEM_MEMORY,
VIRT_GED_MEM_ADDR);
}
acpi_dsdt_add_power_button(dsdt);
}

static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams)
Expand All @@ -271,7 +272,7 @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams)
.pio.size = VIRT_PCI_IO_SIZE,
.ecam.base = VIRT_PCI_CFG_BASE,
.ecam.size = VIRT_PCI_CFG_SIZE,
.irq = PCH_PIC_IRQ_OFFSET + VIRT_DEVICE_IRQS,
.irq = VIRT_GSI_BASE + VIRT_DEVICE_IRQS,
.bus = lams->pci_bus,
};

Expand Down
20 changes: 16 additions & 4 deletions hw/loongarch/virt.c
Expand Up @@ -316,6 +316,14 @@ static void virt_machine_done(Notifier *notifier, void *data)
loongarch_acpi_setup(lams);
}

static void virt_powerdown_req(Notifier *notifier, void *opaque)
{
LoongArchMachineState *s = container_of(notifier,
LoongArchMachineState, powerdown_notifier);

acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS);
}

struct memmap_entry {
uint64_t address;
uint64_t length;
Expand Down Expand Up @@ -432,7 +440,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, LoongArchMachineState
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR);

sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - PCH_PIC_IRQ_OFFSET));
qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - VIRT_GSI_BASE));
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
return dev;
}
Expand All @@ -452,7 +460,7 @@ static DeviceState *create_platform_bus(DeviceState *pch_pic)

sysbus = SYS_BUS_DEVICE(dev);
for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) {
irq = VIRT_PLATFORM_BUS_IRQ - PCH_PIC_IRQ_OFFSET + i;
irq = VIRT_PLATFORM_BUS_IRQ - VIRT_GSI_BASE + i;
sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(pch_pic, irq));
}

Expand Down Expand Up @@ -509,7 +517,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *

serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0,
qdev_get_gpio_in(pch_pic,
VIRT_UART_IRQ - PCH_PIC_IRQ_OFFSET),
VIRT_UART_IRQ - VIRT_GSI_BASE),
115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
fdt_add_uart_node(lams);

Expand All @@ -531,7 +539,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE,
qdev_get_gpio_in(pch_pic,
VIRT_RTC_IRQ - PCH_PIC_IRQ_OFFSET));
VIRT_RTC_IRQ - VIRT_GSI_BASE));
fdt_add_rtc_node(lams);

pm_mem = g_new(MemoryRegion, 1);
Expand Down Expand Up @@ -859,6 +867,10 @@ static void loongarch_init(MachineState *machine)
VIRT_PLATFORM_BUS_IRQ);
lams->machine_done.notify = virt_machine_done;
qemu_add_machine_init_done_notifier(&lams->machine_done);
/* connect powerdown request */
lams->powerdown_notifier.notify = virt_powerdown_req;
qemu_register_powerdown_notifier(&lams->powerdown_notifier);

fdt_add_pcie_node(lams);
/*
* Since lowmem region starts from 0 and Linux kernel legacy start address
Expand Down
156 changes: 156 additions & 0 deletions hw/misc/i2c-echo.c
@@ -0,0 +1,156 @@
#include "qemu/osdep.h"
#include "qemu/timer.h"
#include "qemu/main-loop.h"
#include "block/aio.h"
#include "hw/i2c/i2c.h"

#define TYPE_I2C_ECHO "i2c-echo"
OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO)

enum i2c_echo_state {
I2C_ECHO_STATE_IDLE,
I2C_ECHO_STATE_START_SEND,
I2C_ECHO_STATE_ACK,
};

typedef struct I2CEchoState {
I2CSlave parent_obj;

I2CBus *bus;

enum i2c_echo_state state;
QEMUBH *bh;

unsigned int pos;
uint8_t data[3];
} I2CEchoState;

static void i2c_echo_bh(void *opaque)
{
I2CEchoState *state = opaque;

switch (state->state) {
case I2C_ECHO_STATE_IDLE:
return;

case I2C_ECHO_STATE_START_SEND:
if (i2c_start_send_async(state->bus, state->data[0])) {
goto release_bus;
}

state->pos++;
state->state = I2C_ECHO_STATE_ACK;
return;

case I2C_ECHO_STATE_ACK:
if (state->pos > 2) {
break;
}

if (i2c_send_async(state->bus, state->data[state->pos++])) {
break;
}

return;
}


i2c_end_transfer(state->bus);
release_bus:
i2c_bus_release(state->bus);

state->state = I2C_ECHO_STATE_IDLE;
}

static int i2c_echo_event(I2CSlave *s, enum i2c_event event)
{
I2CEchoState *state = I2C_ECHO(s);

switch (event) {
case I2C_START_RECV:
state->pos = 0;

break;

case I2C_START_SEND:
state->pos = 0;

break;

case I2C_FINISH:
state->pos = 0;
state->state = I2C_ECHO_STATE_START_SEND;
i2c_bus_master(state->bus, state->bh);

break;

case I2C_NACK:
break;

default:
return -1;
}

return 0;
}

static uint8_t i2c_echo_recv(I2CSlave *s)
{
I2CEchoState *state = I2C_ECHO(s);

if (state->pos > 2) {
return 0xff;
}

return state->data[state->pos++];
}

static int i2c_echo_send(I2CSlave *s, uint8_t data)
{
I2CEchoState *state = I2C_ECHO(s);

if (state->pos > 2) {
return -1;
}

state->data[state->pos++] = data;

return 0;
}

static void i2c_echo_realize(DeviceState *dev, Error **errp)
{
I2CEchoState *state = I2C_ECHO(dev);
BusState *bus = qdev_get_parent_bus(dev);

state->bus = I2C_BUS(bus);
state->bh = qemu_bh_new(i2c_echo_bh, state);

return;
}

static void i2c_echo_class_init(ObjectClass *oc, void *data)
{
I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);

dc->realize = i2c_echo_realize;

sc->event = i2c_echo_event;
sc->recv = i2c_echo_recv;
sc->send = i2c_echo_send;
}

static const TypeInfo i2c_echo = {
.name = TYPE_I2C_ECHO,
.parent = TYPE_I2C_SLAVE,
.instance_size = sizeof(I2CEchoState),
.class_init = i2c_echo_class_init,
};

static void register_types(void)
{
type_register_static(&i2c_echo);
}

type_init(register_types);
2 changes: 2 additions & 0 deletions hw/misc/meson.build
Expand Up @@ -128,6 +128,8 @@ softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c'))

softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c'))

softmmu_ss.add(when: 'CONFIG_I2C', if_true: files('i2c-echo.c'))

specific_ss.add(when: 'CONFIG_AVR_POWER', if_true: files('avr_power.c'))

specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c'))
Expand Down
30 changes: 27 additions & 3 deletions hw/nvram/eeprom_at24c.c
Expand Up @@ -41,6 +41,13 @@ struct EEPROMState {
uint16_t cur;
/* total size in bytes */
uint32_t rsize;
/*
* address byte number
* for 24c01, 24c02 size <= 256 byte, use only 1 byte
* otherwise size > 256, use 2 byte
*/
uint8_t asize;

bool writable;
/* cells changed since last START? */
bool changed;
Expand Down Expand Up @@ -91,7 +98,11 @@ uint8_t at24c_eeprom_recv(I2CSlave *s)
EEPROMState *ee = AT24C_EE(s);
uint8_t ret;

if (ee->haveaddr == 1) {
/*
* If got the byte address but not completely with address size
* will return the invalid value
*/
if (ee->haveaddr > 0 && ee->haveaddr < ee->asize) {
return 0xff;
}

Expand All @@ -108,11 +119,11 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data)
{
EEPROMState *ee = AT24C_EE(s);

if (ee->haveaddr < 2) {
if (ee->haveaddr < ee->asize) {
ee->cur <<= 8;
ee->cur |= data;
ee->haveaddr++;
if (ee->haveaddr == 2) {
if (ee->haveaddr == ee->asize) {
ee->cur %= ee->rsize;
DPRINTK("Set pointer %04x\n", ee->cur);
}
Expand Down Expand Up @@ -199,6 +210,18 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp)
}
DPRINTK("Reset read backing file\n");
}

/*
* If address size didn't define with property set
* value is 0 as default, setting it by Rom size detecting.
*/
if (ee->asize == 0) {
if (ee->rsize <= 256) {
ee->asize = 1;
} else {
ee->asize = 2;
}
}
}

static
Expand All @@ -213,6 +236,7 @@ void at24c_eeprom_reset(DeviceState *state)

static Property at24c_eeprom_props[] = {
DEFINE_PROP_UINT32("rom-size", EEPROMState, rsize, 0),
DEFINE_PROP_UINT8("address-size", EEPROMState, asize, 0),
DEFINE_PROP_BOOL("writable", EEPROMState, writable, true),
DEFINE_PROP_DRIVE("drive", EEPROMState, blk),
DEFINE_PROP_END_OF_LIST()
Expand Down
5 changes: 1 addition & 4 deletions hw/ssi/aspeed_smc.c
Expand Up @@ -1134,10 +1134,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)

/* Setup cs_lines for peripherals */
s->cs_lines = g_new0(qemu_irq, asc->cs_num_max);

for (i = 0; i < asc->cs_num_max; ++i) {
sysbus_init_irq(sbd, &s->cs_lines[i]);
}
qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", asc->cs_num_max);

/* The memory region for the controller registers */
memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
Expand Down
5 changes: 5 additions & 0 deletions include/hw/arm/aspeed_soc.h
Expand Up @@ -58,6 +58,8 @@ struct AspeedSoCState {
MemoryRegion *dram_mr;
MemoryRegion dram_container;
MemoryRegion sram;
MemoryRegion spi_boot_container;
MemoryRegion spi_boot;
AspeedVICState vic;
AspeedRtcState rtc;
AspeedTimerCtrlState timerctrl;
Expand Down Expand Up @@ -120,6 +122,7 @@ struct AspeedSoCClass {


enum {
ASPEED_DEV_SPI_BOOT,
ASPEED_DEV_IOMEM,
ASPEED_DEV_UART1,
ASPEED_DEV_UART2,
Expand Down Expand Up @@ -190,6 +193,8 @@ enum {
ASPEED_DEV_JTAG1,
};

#define ASPEED_SOC_SPI_BOOT_ADDR 0x0

qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
Expand Down
2 changes: 2 additions & 0 deletions include/hw/i2c/i2c.h
Expand Up @@ -141,6 +141,8 @@ int i2c_start_send(I2CBus *bus, uint8_t address);
*/
int i2c_start_send_async(I2CBus *bus, uint8_t address);

void i2c_schedule_pending_master(I2CBus *bus);

void i2c_end_transfer(I2CBus *bus);
void i2c_nack(I2CBus *bus);
void i2c_ack(I2CBus *bus);
Expand Down
1 change: 1 addition & 0 deletions include/hw/loongarch/virt.h
Expand Up @@ -45,6 +45,7 @@ struct LoongArchMachineState {
/* State for other subsystems/APIs: */
FWCfgState *fw_cfg;
Notifier machine_done;
Notifier powerdown_notifier;
OnOffAuto acpi;
char *oem_id;
char *oem_table_id;
Expand Down
17 changes: 9 additions & 8 deletions include/hw/pci-host/ls7a.h
Expand Up @@ -26,24 +26,25 @@
#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL

/*
* According to the kernel pch irq start from 64 offset
* 0 ~ 16 irqs used for non-pci device while 16 ~ 64 irqs
* used for pci device.
* GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot
* 0 - 15 GSI for ISA devices even if there is no ISA devices
* 16 - 63 GSI for CPU devices such as timers/perf monitor etc
* 64 - GSI for external devices
*/
#define VIRT_PCH_PIC_IRQ_NUM 32
#define PCH_PIC_IRQ_OFFSET 64
#define VIRT_GSI_BASE 64
#define VIRT_DEVICE_IRQS 16
#define VIRT_UART_IRQ (PCH_PIC_IRQ_OFFSET + 2)
#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2)
#define VIRT_UART_BASE 0x1fe001e0
#define VIRT_UART_SIZE 0X100
#define VIRT_RTC_IRQ (PCH_PIC_IRQ_OFFSET + 3)
#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 3)
#define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000)
#define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100)
#define VIRT_RTC_LEN 0x100
#define VIRT_SCI_IRQ (PCH_PIC_IRQ_OFFSET + 4)
#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 4)

#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000
#define VIRT_PLATFORM_BUS_SIZE 0x2000000
#define VIRT_PLATFORM_BUS_NUM_IRQS 2
#define VIRT_PLATFORM_BUS_IRQ 69
#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 5)
#endif
24 changes: 24 additions & 0 deletions migration/exec.c
Expand Up @@ -23,12 +23,31 @@
#include "migration.h"
#include "io/channel-command.h"
#include "trace.h"
#include "qemu/cutils.h"

#ifdef WIN32
const char *exec_get_cmd_path(void);
const char *exec_get_cmd_path(void)
{
g_autofree char *detected_path = g_new(char, MAX_PATH);
if (GetSystemDirectoryA(detected_path, MAX_PATH) == 0) {
warn_report("Could not detect cmd.exe path, using default.");
return "C:\\Windows\\System32\\cmd.exe";
}
pstrcat(detected_path, MAX_PATH, "\\cmd.exe");
return g_steal_pointer(&detected_path);
}
#endif

void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
QIOChannel *ioc;

#ifdef WIN32
const char *argv[] = { exec_get_cmd_path(), "/c", command, NULL };
#else
const char *argv[] = { "/bin/sh", "-c", command, NULL };
#endif

trace_migration_exec_outgoing(command);
ioc = QIO_CHANNEL(qio_channel_command_new_spawn(argv,
Expand All @@ -55,7 +74,12 @@ static gboolean exec_accept_incoming_migration(QIOChannel *ioc,
void exec_start_incoming_migration(const char *command, Error **errp)
{
QIOChannel *ioc;

#ifdef WIN32
const char *argv[] = { exec_get_cmd_path(), "/c", command, NULL };
#else
const char *argv[] = { "/bin/sh", "-c", command, NULL };
#endif

trace_migration_exec_incoming(command);
ioc = QIO_CHANNEL(qio_channel_command_new_spawn(argv,
Expand Down
2 changes: 1 addition & 1 deletion qemu-options.hx
Expand Up @@ -2585,7 +2585,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
" specify SMBIOS type 17 fields\n"
"-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n"
" specify SMBIOS type 41 fields\n",
QEMU_ARCH_I386 | QEMU_ARCH_ARM)
QEMU_ARCH_I386 | QEMU_ARCH_ARM | QEMU_ARCH_LOONGARCH)
SRST
``-smbios file=binary``
Load SMBIOS entry from binary file.
Expand Down
2 changes: 2 additions & 0 deletions target/loongarch/cpu.c
Expand Up @@ -546,6 +546,8 @@ static void loongarch_qemu_write(void *opaque, hwaddr addr,
static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
{
switch (addr) {
case VERSION_REG:
return 0x11ULL;
case FEATURE_REG:
return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
1ULL << IOCSRF_CSRIPI;
Expand Down
1 change: 1 addition & 0 deletions target/loongarch/cpu.h
Expand Up @@ -28,6 +28,7 @@
#define IOCSRF_GMOD 9
#define IOCSRF_VM 11

#define VERSION_REG 0x0
#define FEATURE_REG 0x8
#define VENDOR_REG 0x10
#define CPUNAME_REG 0x20
Expand Down
10 changes: 10 additions & 0 deletions tests/avocado/machine_aspeed.py
Expand Up @@ -199,6 +199,8 @@ def test_arm_ast2600_evb_buildroot(self):
'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')

exec_command_and_wait_for_pattern(self,
Expand All @@ -217,6 +219,14 @@ def test_arm_ast2600_evb_buildroot(self):
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(self, 'i2cset -y 3 0x42 0x64 0x00 0xaa i');
time.sleep(0.1)
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()


Expand Down
5 changes: 2 additions & 3 deletions tests/unit/test-vmstate.c
Expand Up @@ -1073,7 +1073,6 @@ static gboolean diff_tree(gpointer key, gpointer value, gpointer data)
struct match_node_data d = {tp->tree2, key, value};

g_tree_foreach(tp->tree2, tp->match_node, &d);
g_tree_remove(tp->tree1, key);
return false;
}

Expand All @@ -1082,9 +1081,9 @@ static void compare_trees(GTree *tree1, GTree *tree2,
{
struct tree_cmp_data tp = {tree1, tree2, function};

assert(g_tree_nnodes(tree1) == g_tree_nnodes(tree2));
g_tree_foreach(tree1, diff_tree, &tp);
assert(g_tree_nnodes(tree1) == 0);
assert(g_tree_nnodes(tree2) == 0);
g_tree_destroy(g_tree_ref(tree1));
}

static void diff_domain(TestGTreeDomain *d1, TestGTreeDomain *d2)
Expand Down