aspeed queue:
* fix for the Aspeed I2C slave mode * a new I2C echo device from Klaus and its associated test in avocado. * initial SoC cleanups to allow the use of block devices instead of drives on the command line. * new facebook machines and eeprom fixes for the Fuji * readline fix -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmQAnrQACgkQUaNDx8/7 7KGIvQ//Te2eSxlZNxAXHb3HSVFRaBW+2EkJzNlalX75olFSzCLe8BnAHK5xPlYv JjU0aPjWaPohPLdbNbAsJY2B8AwMGbUTjSv+ORRWF6s97LTVD9WcAYHgOTCz6d2X ZrArJ5msEQAFEySOLmBqTcuyW3t4w8XeII+B09HZIS8Gn3F9kX5+4JCw9E4sX8fS n9ayclMmrXCPbkGA4bfwJp3KI1Tc/WXNRyG0AmPEmepid7ECr5tVvQoXRMF1Sy/D 10qbHEcmQXvZDy85M2ED1niOac4oU+EY8Wvjzkgc36uXcjqf0jIUfw56cwGSNVkW MhPXSMiH4tEjgxmtzld3LeA6TGfrFcCvRXYiCuYWHjBS3gptlqY6Q0580vxoQVXL lTYui57LB1YStNLcLG9toP0d4/fRfeqEx7ddCQKlopnW/K392eoJo0aYoVGVJhIC 3QhN525EFUwMm4FDpdSW29Gfbk/ytpf0u4hQ6JPeBl8psirRKqCGuwr5NOnPYTaN yErlsq2eL83t9kLo+2YIqgWic85wNP3kqAjIaE6lminqX7sWFH3V1g9HqUQZVG1g msatZMiCCvwSFuz3DPkSfnuhqwaHuhvCATZloCtguCmnbUK9qUVVzvodKw62sZrd GdS2XvRNyoOwezz0tDEvPipyZ7RpcaatryHNuzGwRsE5Lvr73dg= =ExnJ -----END PGP SIGNATURE----- Merge tag 'pull-aspeed-20230302' of https://github.com/legoater/qemu into staging aspeed queue: * fix for the Aspeed I2C slave mode * a new I2C echo device from Klaus and its associated test in avocado. * initial SoC cleanups to allow the use of block devices instead of drives on the command line. * new facebook machines and eeprom fixes for the Fuji * readline fix # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmQAnrQACgkQUaNDx8/7 # 7KGIvQ//Te2eSxlZNxAXHb3HSVFRaBW+2EkJzNlalX75olFSzCLe8BnAHK5xPlYv # JjU0aPjWaPohPLdbNbAsJY2B8AwMGbUTjSv+ORRWF6s97LTVD9WcAYHgOTCz6d2X # ZrArJ5msEQAFEySOLmBqTcuyW3t4w8XeII+B09HZIS8Gn3F9kX5+4JCw9E4sX8fS # n9ayclMmrXCPbkGA4bfwJp3KI1Tc/WXNRyG0AmPEmepid7ECr5tVvQoXRMF1Sy/D # 10qbHEcmQXvZDy85M2ED1niOac4oU+EY8Wvjzkgc36uXcjqf0jIUfw56cwGSNVkW # MhPXSMiH4tEjgxmtzld3LeA6TGfrFcCvRXYiCuYWHjBS3gptlqY6Q0580vxoQVXL # lTYui57LB1YStNLcLG9toP0d4/fRfeqEx7ddCQKlopnW/K392eoJo0aYoVGVJhIC # 3QhN525EFUwMm4FDpdSW29Gfbk/ytpf0u4hQ6JPeBl8psirRKqCGuwr5NOnPYTaN # yErlsq2eL83t9kLo+2YIqgWic85wNP3kqAjIaE6lminqX7sWFH3V1g9HqUQZVG1g # msatZMiCCvwSFuz3DPkSfnuhqwaHuhvCATZloCtguCmnbUK9qUVVzvodKw62sZrd # GdS2XvRNyoOwezz0tDEvPipyZ7RpcaatryHNuzGwRsE5Lvr73dg= # =ExnJ # -----END PGP SIGNATURE----- # gpg: Signature made Thu 02 Mar 2023 13:03:48 GMT # 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 * tag 'pull-aspeed-20230302' of https://github.com/legoater/qemu: aspeed/smc: Replace SysBus IRQs with GPIO lines aspeed: Add a boot_rom overlap region in the SoC spi_boot container aspeed: Introduce a spi_boot region under the SoC aspeed/fuji : correct the eeprom size hw/at24c : modify at24c to support 1 byte address mode hw/arm/aspeed: Adding new machine Tiogapass in QEMU hw/arm/aspeed: Adding new machine Yosemitev2 in QEMU tests/avocado/machine_aspeed.py: Add an I2C slave test hw/misc: add a toy i2c echo device hw/i2c: only schedule pending master when bus is idle readline: fix hmp completion issue Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
cad8db9865
@ -24,6 +24,8 @@ AST2500 SoC based machines :
|
|||||||
- ``sonorapass-bmc`` OCP SonoraPass BMC
|
- ``sonorapass-bmc`` OCP SonoraPass BMC
|
||||||
- ``fp5280g2-bmc`` Inspur FP5280G2 BMC
|
- ``fp5280g2-bmc`` Inspur FP5280G2 BMC
|
||||||
- ``g220a-bmc`` Bytedance G220A BMC
|
- ``g220a-bmc`` Bytedance G220A BMC
|
||||||
|
- ``yosemitev2-bmc`` Facebook YosemiteV2 BMC
|
||||||
|
- ``tiogapass-bmc`` Facebook Tiogapass BMC
|
||||||
|
|
||||||
AST2600 SoC based machines :
|
AST2600 SoC based machines :
|
||||||
|
|
||||||
|
159
hw/arm/aspeed.c
159
hw/arm/aspeed.c
@ -241,12 +241,9 @@ static void aspeed_reset_secondary(ARMCPU *cpu,
|
|||||||
cpu_set_pc(cs, info->smp_loader_start);
|
cpu_set_pc(cs, info->smp_loader_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FIRMWARE_ADDR 0x0
|
static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size,
|
||||||
|
|
||||||
static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
|
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
|
|
||||||
g_autofree void *storage = NULL;
|
g_autofree void *storage = NULL;
|
||||||
int64_t size;
|
int64_t size;
|
||||||
|
|
||||||
@ -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);
|
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,
|
void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
|
||||||
unsigned int count, int unit0)
|
unsigned int count, int unit0)
|
||||||
{
|
{
|
||||||
@ -293,7 +306,7 @@ void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
|
|||||||
qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal);
|
qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal);
|
||||||
|
|
||||||
cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +345,6 @@ static void aspeed_machine_init(MachineState *machine)
|
|||||||
AspeedMachineState *bmc = ASPEED_MACHINE(machine);
|
AspeedMachineState *bmc = ASPEED_MACHINE(machine);
|
||||||
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
|
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
|
||||||
AspeedSoCClass *sc;
|
AspeedSoCClass *sc;
|
||||||
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
|
|
||||||
int i;
|
int i;
|
||||||
NICInfo *nd = &nd_table[0];
|
NICInfo *nd = &nd_table[0];
|
||||||
|
|
||||||
@ -382,32 +394,6 @@ static void aspeed_machine_init(MachineState *machine)
|
|||||||
bmc->spi_model ? bmc->spi_model : amc->spi_model,
|
bmc->spi_model ? bmc->spi_model : amc->spi_model,
|
||||||
1, amc->num_cs);
|
1, amc->num_cs);
|
||||||
|
|
||||||
/* 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) {
|
if (machine->kernel_filename && sc->num_cpus > 1) {
|
||||||
/* With no u-boot we must set up a boot stub for the secondary CPU */
|
/* With no u-boot we must set up a boot stub for the secondary CPU */
|
||||||
MemoryRegion *smpboot = g_new(MemoryRegion, 1);
|
MemoryRegion *smpboot = g_new(MemoryRegion, 1);
|
||||||
@ -438,6 +424,16 @@ static void aspeed_machine_init(MachineState *machine)
|
|||||||
drive_get(IF_SD, 0, bmc->soc.sdhci.num_slots));
|
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);
|
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,6 +517,15 @@ static void ast2600_evb_i2c_init(AspeedMachineState *bmc)
|
|||||||
TYPE_TMP105, 0x4d);
|
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)
|
static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
|
||||||
{
|
{
|
||||||
AspeedSoCState *soc = &bmc->soc;
|
AspeedSoCState *soc = &bmc->soc;
|
||||||
@ -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);
|
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)
|
static void create_pca9552(AspeedSoCState *soc, int bus_id, int addr)
|
||||||
{
|
{
|
||||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, bus_id),
|
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, bus_id),
|
||||||
@ -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, 0x4c);
|
||||||
i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4d);
|
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);
|
* EEPROM 24c64 size is 64Kbits or 8 Kbytes
|
||||||
at24c_eeprom_init(i2c[22], 0x52, 2 * KiB);
|
* 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, 0x48);
|
||||||
i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x49);
|
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_LM75, 0x4a);
|
||||||
i2c_slave_create_simple(i2c[3], TYPE_TMP422, 0x4c);
|
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[8], TYPE_LM75, 0x4a);
|
||||||
|
|
||||||
i2c_slave_create_simple(i2c[50], TYPE_LM75, 0x4c);
|
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[51], TYPE_TMP75, 0x48);
|
||||||
i2c_slave_create_simple(i2c[52], TYPE_TMP75, 0x49);
|
i2c_slave_create_simple(i2c[52], TYPE_TMP75, 0x49);
|
||||||
|
|
||||||
i2c_slave_create_simple(i2c[59], TYPE_TMP75, 0x48);
|
i2c_slave_create_simple(i2c[59], TYPE_TMP75, 0x48);
|
||||||
i2c_slave_create_simple(i2c[60], TYPE_TMP75, 0x49);
|
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, 0x49);
|
||||||
i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x48);
|
i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x48);
|
||||||
at24c_eeprom_init(i2c[68], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[68], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[69], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[69], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[70], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[70], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[71], 0x52, 64 * 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, 0x49);
|
||||||
i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x48);
|
i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x48);
|
||||||
at24c_eeprom_init(i2c[76], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[76], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[77], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[77], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[78], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[78], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[79], 0x52, 64 * KiB);
|
at24c_eeprom_init(i2c[79], 0x52, 8 * KiB);
|
||||||
at24c_eeprom_init(i2c[28], 0x50, 2 * KiB);
|
at24c_eeprom_init(i2c[28], 0x50, 256);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
at24c_eeprom_init(i2c[81 + i * 8], 0x56, 64 * KiB);
|
at24c_eeprom_init(i2c[81 + i * 8], 0x56, 64 * KiB);
|
||||||
@ -1174,6 +1192,24 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
|
|||||||
aspeed_soc_num_cpus(amc->soc_name);
|
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)
|
static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
@ -1191,6 +1227,25 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
|
|||||||
aspeed_soc_num_cpus(amc->soc_name);
|
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)
|
static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
@ -1562,10 +1617,18 @@ static const TypeInfo aspeed_machine_types[] = {
|
|||||||
.name = MACHINE_TYPE_NAME("ast2600-evb"),
|
.name = MACHINE_TYPE_NAME("ast2600-evb"),
|
||||||
.parent = TYPE_ASPEED_MACHINE,
|
.parent = TYPE_ASPEED_MACHINE,
|
||||||
.class_init = aspeed_machine_ast2600_evb_class_init,
|
.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"),
|
.name = MACHINE_TYPE_NAME("tacoma-bmc"),
|
||||||
.parent = TYPE_ASPEED_MACHINE,
|
.parent = TYPE_ASPEED_MACHINE,
|
||||||
.class_init = aspeed_machine_tacoma_class_init,
|
.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"),
|
.name = MACHINE_TYPE_NAME("g220a-bmc"),
|
||||||
.parent = TYPE_ASPEED_MACHINE,
|
.parent = TYPE_ASPEED_MACHINE,
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define ASPEED_SOC_DPMCU_SIZE 0x00040000
|
#define ASPEED_SOC_DPMCU_SIZE 0x00040000
|
||||||
|
|
||||||
static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
||||||
|
[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR,
|
||||||
[ASPEED_DEV_SRAM] = 0x10000000,
|
[ASPEED_DEV_SRAM] = 0x10000000,
|
||||||
[ASPEED_DEV_DPMCU] = 0x18000000,
|
[ASPEED_DEV_DPMCU] = 0x18000000,
|
||||||
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
|
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
|
||||||
@ -282,6 +283,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
|||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
g_autofree char *sram_name = 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 */
|
/* IO space */
|
||||||
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
|
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
|
||||||
sc->memmap[ASPEED_DEV_IOMEM],
|
sc->memmap[ASPEED_DEV_IOMEM],
|
||||||
@ -431,6 +438,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
|
||||||
aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
|
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 */
|
/* SPI */
|
||||||
for (i = 0; i < sc->spis_num; i++) {
|
for (i = 0; i < sc->spis_num; i++) {
|
||||||
object_property_set_link(OBJECT(&s->spi[i]), "dram",
|
object_property_set_link(OBJECT(&s->spi[i]), "dram",
|
||||||
|
@ -6,6 +6,27 @@
|
|||||||
|
|
||||||
#include "aspeed_eeprom.h"
|
#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[] = {
|
const uint8_t fby35_nic_fruid[] = {
|
||||||
0x01, 0x00, 0x00, 0x01, 0x0f, 0x20, 0x00, 0xcf, 0x01, 0x0e, 0x19, 0xd7,
|
0x01, 0x00, 0x00, 0x01, 0x0f, 0x20, 0x00, 0xcf, 0x01, 0x0e, 0x19, 0xd7,
|
||||||
0x5e, 0xcf, 0xc8, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xdd,
|
0x5e, 0xcf, 0xc8, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xdd,
|
||||||
@ -77,6 +98,30 @@ const uint8_t fby35_bmc_fruid[] = {
|
|||||||
0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45,
|
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_nic_fruid_len = sizeof(fby35_nic_fruid);
|
||||||
const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid);
|
const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid);
|
||||||
const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid);
|
const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid);
|
||||||
|
|
||||||
|
const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid);
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#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_nic_fruid[];
|
||||||
extern const uint8_t fby35_bb_fruid[];
|
extern const uint8_t fby35_bb_fruid[];
|
||||||
extern const uint8_t fby35_bmc_fruid[];
|
extern const uint8_t fby35_bmc_fruid[];
|
||||||
@ -16,4 +19,7 @@ extern const size_t fby35_nic_fruid_len;
|
|||||||
extern const size_t fby35_bb_fruid_len;
|
extern const size_t fby35_bb_fruid_len;
|
||||||
extern const size_t fby35_bmc_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
|
#endif
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
|
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
|
||||||
|
|
||||||
static const hwaddr aspeed_soc_ast2400_memmap[] = {
|
static const hwaddr aspeed_soc_ast2400_memmap[] = {
|
||||||
|
[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR,
|
||||||
[ASPEED_DEV_IOMEM] = 0x1E600000,
|
[ASPEED_DEV_IOMEM] = 0x1E600000,
|
||||||
[ASPEED_DEV_FMC] = 0x1E620000,
|
[ASPEED_DEV_FMC] = 0x1E620000,
|
||||||
[ASPEED_DEV_SPI1] = 0x1E630000,
|
[ASPEED_DEV_SPI1] = 0x1E630000,
|
||||||
@ -59,6 +60,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const hwaddr aspeed_soc_ast2500_memmap[] = {
|
static const hwaddr aspeed_soc_ast2500_memmap[] = {
|
||||||
|
[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR,
|
||||||
[ASPEED_DEV_IOMEM] = 0x1E600000,
|
[ASPEED_DEV_IOMEM] = 0x1E600000,
|
||||||
[ASPEED_DEV_FMC] = 0x1E620000,
|
[ASPEED_DEV_FMC] = 0x1E620000,
|
||||||
[ASPEED_DEV_SPI1] = 0x1E630000,
|
[ASPEED_DEV_SPI1] = 0x1E630000,
|
||||||
@ -245,6 +247,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
g_autofree char *sram_name = 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 */
|
/* IO space */
|
||||||
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
|
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
|
||||||
sc->memmap[ASPEED_DEV_IOMEM],
|
sc->memmap[ASPEED_DEV_IOMEM],
|
||||||
@ -354,6 +362,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
|
||||||
aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
|
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 */
|
/* SPI */
|
||||||
for (i = 0; i < sc->spis_num; i++) {
|
for (i = 0; i < sc->spis_num; i++) {
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
|
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
|
||||||
|
@ -100,13 +100,7 @@ static void fby35_bmc_init(Fby35State *s)
|
|||||||
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
|
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
|
||||||
uint64_t size = memory_region_size(&fl->mmio);
|
uint64_t size = memory_region_size(&fl->mmio);
|
||||||
|
|
||||||
if (s->mmio_exec) {
|
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 {
|
|
||||||
|
|
||||||
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
|
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
|
||||||
size, &error_abort);
|
size, &error_abort);
|
||||||
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
|
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
|
||||||
|
@ -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);
|
SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_STOP_CMD, 0);
|
||||||
aspeed_i2c_set_state(bus, I2CD_IDLE);
|
aspeed_i2c_set_state(bus, I2CD_IDLE);
|
||||||
|
|
||||||
|
i2c_schedule_pending_master(bus->bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aspeed_i2c_bus_pkt_mode_en(bus)) {
|
if (aspeed_i2c_bus_pkt_mode_en(bus)) {
|
||||||
|
@ -185,22 +185,39 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, bool is_recv)
|
|||||||
|
|
||||||
void i2c_bus_master(I2CBus *bus, QEMUBH *bh)
|
void i2c_bus_master(I2CBus *bus, QEMUBH *bh)
|
||||||
{
|
{
|
||||||
if (i2c_bus_busy(bus)) {
|
|
||||||
I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1);
|
I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1);
|
||||||
node->bh = bh;
|
node->bh = bh;
|
||||||
|
|
||||||
QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry);
|
QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_schedule_pending_master(I2CBus *bus)
|
||||||
|
{
|
||||||
|
I2CPendingMaster *node;
|
||||||
|
|
||||||
|
if (i2c_bus_busy(bus)) {
|
||||||
|
/* someone is already controlling the bus; wait for it to release it */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus->bh = bh;
|
if (QSIMPLEQ_EMPTY(&bus->pending_masters)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
qemu_bh_schedule(bus->bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_bus_release(I2CBus *bus)
|
void i2c_bus_release(I2CBus *bus)
|
||||||
{
|
{
|
||||||
bus->bh = NULL;
|
bus->bh = NULL;
|
||||||
|
|
||||||
|
i2c_schedule_pending_master(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_start_recv(I2CBus *bus, uint8_t address)
|
int i2c_start_recv(I2CBus *bus, uint8_t address)
|
||||||
@ -234,16 +251,6 @@ void i2c_end_transfer(I2CBus *bus)
|
|||||||
g_free(node);
|
g_free(node);
|
||||||
}
|
}
|
||||||
bus->broadcast = false;
|
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)
|
int i2c_send(I2CBus *bus, uint8_t data)
|
||||||
|
156
hw/misc/i2c-echo.c
Normal file
156
hw/misc/i2c-echo.c
Normal file
@ -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);
|
@ -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_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_AVR_POWER', if_true: files('avr_power.c'))
|
||||||
|
|
||||||
specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c'))
|
specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c'))
|
||||||
|
@ -41,6 +41,13 @@ struct EEPROMState {
|
|||||||
uint16_t cur;
|
uint16_t cur;
|
||||||
/* total size in bytes */
|
/* total size in bytes */
|
||||||
uint32_t rsize;
|
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;
|
bool writable;
|
||||||
/* cells changed since last START? */
|
/* cells changed since last START? */
|
||||||
bool changed;
|
bool changed;
|
||||||
@ -91,7 +98,11 @@ uint8_t at24c_eeprom_recv(I2CSlave *s)
|
|||||||
EEPROMState *ee = AT24C_EE(s);
|
EEPROMState *ee = AT24C_EE(s);
|
||||||
uint8_t ret;
|
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;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,11 +119,11 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data)
|
|||||||
{
|
{
|
||||||
EEPROMState *ee = AT24C_EE(s);
|
EEPROMState *ee = AT24C_EE(s);
|
||||||
|
|
||||||
if (ee->haveaddr < 2) {
|
if (ee->haveaddr < ee->asize) {
|
||||||
ee->cur <<= 8;
|
ee->cur <<= 8;
|
||||||
ee->cur |= data;
|
ee->cur |= data;
|
||||||
ee->haveaddr++;
|
ee->haveaddr++;
|
||||||
if (ee->haveaddr == 2) {
|
if (ee->haveaddr == ee->asize) {
|
||||||
ee->cur %= ee->rsize;
|
ee->cur %= ee->rsize;
|
||||||
DPRINTK("Set pointer %04x\n", ee->cur);
|
DPRINTK("Set pointer %04x\n", ee->cur);
|
||||||
}
|
}
|
||||||
@ -199,6 +210,18 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
DPRINTK("Reset read backing file\n");
|
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
|
static
|
||||||
@ -213,6 +236,7 @@ void at24c_eeprom_reset(DeviceState *state)
|
|||||||
|
|
||||||
static Property at24c_eeprom_props[] = {
|
static Property at24c_eeprom_props[] = {
|
||||||
DEFINE_PROP_UINT32("rom-size", EEPROMState, rsize, 0),
|
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_BOOL("writable", EEPROMState, writable, true),
|
||||||
DEFINE_PROP_DRIVE("drive", EEPROMState, blk),
|
DEFINE_PROP_DRIVE("drive", EEPROMState, blk),
|
||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
|
@ -1134,10 +1134,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
/* Setup cs_lines for peripherals */
|
/* Setup cs_lines for peripherals */
|
||||||
s->cs_lines = g_new0(qemu_irq, asc->cs_num_max);
|
s->cs_lines = g_new0(qemu_irq, asc->cs_num_max);
|
||||||
|
qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", asc->cs_num_max);
|
||||||
for (i = 0; i < asc->cs_num_max; ++i) {
|
|
||||||
sysbus_init_irq(sbd, &s->cs_lines[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The memory region for the controller registers */
|
/* The memory region for the controller registers */
|
||||||
memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
|
memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
|
||||||
|
@ -58,6 +58,8 @@ struct AspeedSoCState {
|
|||||||
MemoryRegion *dram_mr;
|
MemoryRegion *dram_mr;
|
||||||
MemoryRegion dram_container;
|
MemoryRegion dram_container;
|
||||||
MemoryRegion sram;
|
MemoryRegion sram;
|
||||||
|
MemoryRegion spi_boot_container;
|
||||||
|
MemoryRegion spi_boot;
|
||||||
AspeedVICState vic;
|
AspeedVICState vic;
|
||||||
AspeedRtcState rtc;
|
AspeedRtcState rtc;
|
||||||
AspeedTimerCtrlState timerctrl;
|
AspeedTimerCtrlState timerctrl;
|
||||||
@ -120,6 +122,7 @@ struct AspeedSoCClass {
|
|||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
ASPEED_DEV_SPI_BOOT,
|
||||||
ASPEED_DEV_IOMEM,
|
ASPEED_DEV_IOMEM,
|
||||||
ASPEED_DEV_UART1,
|
ASPEED_DEV_UART1,
|
||||||
ASPEED_DEV_UART2,
|
ASPEED_DEV_UART2,
|
||||||
@ -190,6 +193,8 @@ enum {
|
|||||||
ASPEED_DEV_JTAG1,
|
ASPEED_DEV_JTAG1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
|
||||||
|
|
||||||
qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
|
qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
|
||||||
bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
|
bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
|
||||||
void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
|
void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
|
||||||
|
@ -141,6 +141,8 @@ int i2c_start_send(I2CBus *bus, uint8_t address);
|
|||||||
*/
|
*/
|
||||||
int i2c_start_send_async(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_end_transfer(I2CBus *bus);
|
||||||
void i2c_nack(I2CBus *bus);
|
void i2c_nack(I2CBus *bus);
|
||||||
void i2c_ack(I2CBus *bus);
|
void i2c_ack(I2CBus *bus);
|
||||||
|
@ -199,6 +199,8 @@ class AST2x00Machine(QemuSystemTest):
|
|||||||
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
|
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
|
||||||
self.vm.add_args('-device',
|
self.vm.add_args('-device',
|
||||||
'ds1338,bus=aspeed.i2c.bus.3,address=0x32');
|
'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')
|
self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00')
|
||||||
|
|
||||||
exec_command_and_wait_for_pattern(self,
|
exec_command_and_wait_for_pattern(self,
|
||||||
@ -217,6 +219,14 @@ class AST2x00Machine(QemuSystemTest):
|
|||||||
year = time.strftime("%Y")
|
year = time.strftime("%Y")
|
||||||
exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year);
|
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()
|
self.do_test_arm_aspeed_buildroot_poweroff()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user