diff options
Diffstat (limited to 'hw/arm')
| -rw-r--r-- | hw/arm/Kconfig | 3 | ||||
| -rw-r--r-- | hw/arm/aspeed.c | 107 | ||||
| -rw-r--r-- | hw/arm/aspeed_ast10x0.c | 2 | ||||
| -rw-r--r-- | hw/arm/aspeed_ast2600.c | 76 | ||||
| -rw-r--r-- | hw/arm/aspeed_ast27x0-fc.c | 77 | ||||
| -rw-r--r-- | hw/arm/aspeed_ast27x0.c | 74 | ||||
| -rw-r--r-- | hw/arm/aspeed_soc_common.c | 96 |
7 files changed, 288 insertions, 147 deletions
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 3baa6c6c74..b44b85f436 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -541,6 +541,7 @@ config ASPEED_SOC bool default y depends on TCG && ARM + imply PCI_DEVICES select DS1338 select FTGMAC100 select I2C @@ -561,6 +562,8 @@ config ASPEED_SOC select MAX31785 select FSI_APB2OPB_ASPEED select AT24C + select PCI_EXPRESS + select PCI_EXPRESS_ASPEED config MPS2 bool diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index c31bbe7701..6046ec0bb2 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -26,9 +26,7 @@ #include "hw/qdev-properties.h" #include "system/block-backend.h" #include "system/reset.h" -#include "hw/loader.h" #include "qemu/error-report.h" -#include "qemu/datadir.h" #include "qemu/units.h" #include "hw/qdev-clock.h" #include "system/system.h" @@ -263,102 +261,6 @@ static void aspeed_reset_secondary(ARMCPU *cpu, cpu_set_pc(cs, info->smp_loader_start); } -static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size, - Error **errp) -{ - g_autofree void *storage = NULL; - int64_t size; - - /* - * The block backend size should have already been 'validated' by - * the creation of the m25p80 object. - */ - size = blk_getlength(blk); - if (size <= 0) { - error_setg(errp, "failed to get flash size"); - return; - } - - if (rom_size > size) { - rom_size = size; - } - - storage = g_malloc0(rom_size); - if (blk_pread(blk, 0, rom_size, storage, 0) < 0) { - error_setg(errp, "failed to read the initial flash content"); - return; - } - - 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(AspeedMachineState *bmc, BlockBackend *blk, - uint64_t rom_size) -{ - AspeedSoCState *soc = bmc->soc; - AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc); - - memory_region_init_rom(&bmc->boot_rom, NULL, "aspeed.boot_rom", rom_size, - &error_abort); - memory_region_add_subregion_overlap(&soc->spi_boot_container, 0, - &bmc->boot_rom, 1); - write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT], - rom_size, &error_abort); -} - -#define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" - -/* - * This function locates the vbootrom image file specified via the command line - * using the -bios option. It loads the specified image into the vbootrom - * memory region and handles errors if the file cannot be found or loaded. - */ -static void aspeed_load_vbootrom(AspeedMachineState *bmc, const char *bios_name, - Error **errp) -{ - g_autofree char *filename = NULL; - AspeedSoCState *soc = bmc->soc; - int ret; - - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (!filename) { - error_setg(errp, "Could not find vbootrom image '%s'", bios_name); - return; - } - - ret = load_image_mr(filename, &soc->vbootrom); - if (ret < 0) { - error_setg(errp, "Failed to load vbootrom image '%s'", bios_name); - return; - } -} - -void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, - unsigned int count, int unit0) -{ - int i; - - if (!flashtype) { - return; - } - - for (i = 0; i < count; ++i) { - DriveInfo *dinfo = drive_get(IF_MTD, 0, unit0 + i); - DeviceState *dev; - - dev = qdev_new(flashtype); - if (dinfo) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); - } - qdev_prop_set_uint8(dev, "cs", i); - qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal); - } -} - static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo, bool emmc, bool boot_emmc) { @@ -511,15 +413,16 @@ static void aspeed_machine_init(MachineState *machine) if (fmc0 && !boot_emmc) { uint64_t rom_size = memory_region_size(&bmc->soc->spi_boot); - aspeed_install_boot_rom(bmc, fmc0, rom_size); + aspeed_install_boot_rom(bmc->soc, fmc0, &bmc->boot_rom, rom_size); } else if (emmc0) { - aspeed_install_boot_rom(bmc, blk_by_legacy_dinfo(emmc0), 64 * KiB); + aspeed_install_boot_rom(bmc->soc, blk_by_legacy_dinfo(emmc0), + &bmc->boot_rom, 64 * KiB); } } if (amc->vbootrom) { bios_name = machine->firmware ?: VBOOTROM_FILE_NAME; - aspeed_load_vbootrom(bmc, bios_name, &error_abort); + aspeed_load_vbootrom(bmc->soc, bios_name, &error_abort); } arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo); @@ -1995,7 +1898,6 @@ static void aspeed_machine_ast2700a0_evb_class_init(ObjectClass *oc, MachineClass *mc = MACHINE_CLASS(oc); AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); - mc->alias = "ast2700-evb"; mc->desc = "Aspeed AST2700 A0 EVB (Cortex-A35)"; amc->soc_name = "ast2700-a0"; amc->hw_strap1 = AST2700_EVB_HW_STRAP1; @@ -2018,6 +1920,7 @@ static void aspeed_machine_ast2700a1_evb_class_init(ObjectClass *oc, MachineClass *mc = MACHINE_CLASS(oc); AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + mc->alias = "ast2700-evb"; mc->desc = "Aspeed AST2700 A1 EVB (Cortex-A35)"; amc->soc_name = "ast2700-a1"; amc->hw_strap1 = AST2700_EVB_HW_STRAP1; diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index e6e1ee63c1..c446e70b24 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -154,7 +154,7 @@ static void aspeed_soc_ast1030_init(Object *obj) object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); - object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_SBC); + object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_AST10X0_SBC); for (i = 0; i < sc->wdts_num; i++) { snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index d12707f0ab..03e5df96bb 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -48,11 +48,13 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_ADC] = 0x1E6E9000, [ASPEED_DEV_DP] = 0x1E6EB000, + [ASPEED_DEV_PCIE_PHY1] = 0x1E6ED200, [ASPEED_DEV_SBC] = 0x1E6F2000, [ASPEED_DEV_EMMC_BC] = 0x1E6f5000, [ASPEED_DEV_VIDEO] = 0x1E700000, [ASPEED_DEV_SDHCI] = 0x1E740000, [ASPEED_DEV_EMMC] = 0x1E750000, + [ASPEED_DEV_PCIE0] = 0x1E770000, [ASPEED_DEV_GPIO] = 0x1E780000, [ASPEED_DEV_GPIO_1_8V] = 0x1E780800, [ASPEED_DEV_RTC] = 0x1E781000, @@ -79,6 +81,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_FSI1] = 0x1E79B000, [ASPEED_DEV_FSI2] = 0x1E79B100, [ASPEED_DEV_I3C] = 0x1E7A0000, + [ASPEED_DEV_PCIE_MMIO1] = 0x70000000, [ASPEED_DEV_SDRAM] = 0x80000000, }; @@ -127,6 +130,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_LPC] = 35, [ASPEED_DEV_IBT] = 143, [ASPEED_DEV_I2C] = 110, /* 110 -> 125 */ + [ASPEED_DEV_PCIE0] = 168, [ASPEED_DEV_PECI] = 38, [ASPEED_DEV_ETH1] = 2, [ASPEED_DEV_ETH2] = 3, @@ -191,6 +195,10 @@ static void aspeed_soc_ast2600_init(Object *obj) snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname); object_initialize_child(obj, "i2c", &s->i2c, typename); + object_initialize_child(obj, "pcie-cfg", &s->pcie[0], TYPE_ASPEED_PCIE_CFG); + object_initialize_child(obj, "pcie-phy[*]", &s->pcie_phy[0], + TYPE_ASPEED_PCIE_PHY); + object_initialize_child(obj, "peci", &s->peci, TYPE_ASPEED_PECI); snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname); @@ -261,7 +269,7 @@ static void aspeed_soc_ast2600_init(Object *obj) object_initialize_child(obj, "i3c", &s->i3c, TYPE_ASPEED_I3C); - object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_SBC); + object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_AST2600_SBC); object_initialize_child(obj, "iomem", &s->iomem, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "video", &s->video, TYPE_UNIMPLEMENTED_DEVICE); @@ -285,6 +293,67 @@ static uint64_t aspeed_calc_affinity(int cpu) return (0xf << ARM_AFF1_SHIFT) | cpu; } +/* + * PCIe Root Complex (RC) + * + * H2X register space (single block 0x00-0xFF): + * 0x00-0x7F : shared by RC_L (PCIe0) and RC_H (PCIe1) + * 0x80-0xBF : RC_L only + * 0xC0-0xFF : RC_H only + * + * Model scope / limitations: + * - Firmware supports RC_H only; this QEMU model does not support RC_L. + * - RC_H uses PHY1 and the MMIO window [0x70000000, 0x80000000] + * (aka MMIO1). + * + * Indexing convention (this model): + * - Expose a single logical instance at index 0. + * - pcie[0] -> hardware RC_H (PCIe1) + * - phy[0] -> hardware PHY1 + * - mmio.0 -> guest address range MMIO1: 0x70000000-0x80000000 + * - RC_L / PCIe0 is not created and mapped. + */ +static bool aspeed_soc_ast2600_pcie_realize(DeviceState *dev, Error **errp) +{ + Aspeed2600SoCState *a = ASPEED2600_SOC(dev); + AspeedSoCState *s = ASPEED_SOC(dev); + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + MemoryRegion *mmio_mr = NULL; + qemu_irq irq; + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy[0]), errp)) { + return false; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie_phy[0]), 0, + sc->memmap[ASPEED_DEV_PCIE_PHY1]); + + object_property_set_int(OBJECT(&s->pcie[0]), "dram-base", + sc->memmap[ASPEED_DEV_SDRAM], + &error_abort); + object_property_set_link(OBJECT(&s->pcie[0]), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie[0]), errp)) { + return false; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie[0]), 0, + sc->memmap[ASPEED_DEV_PCIE0]); + + irq = qdev_get_gpio_in(DEVICE(&a->a7mpcore), + sc->irqmap[ASPEED_DEV_PCIE0]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie[0].rc), 0, irq); + + mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pcie[0].rc), 1); + memory_region_init_alias(&s->pcie_mmio_alias[0], OBJECT(&s->pcie[0].rc), + "aspeed.pcie-mmio", mmio_mr, + sc->memmap[ASPEED_DEV_PCIE_MMIO1], + 0x10000000); + memory_region_add_subregion(s->memory, + sc->memmap[ASPEED_DEV_PCIE_MMIO1], + &s->pcie_mmio_alias[0]); + + return true; +} + static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) { int i; @@ -438,6 +507,11 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0, aspeed_soc_get_irq(s, ASPEED_DEV_PECI)); + /* PCIe Root Complex (RC) */ + if (!aspeed_soc_ast2600_pcie_realize(dev, errp)) { + return; + } + /* 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); diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c index 7087be4288..2e16a0340a 100644 --- a/hw/arm/aspeed_ast27x0-fc.c +++ b/hw/arm/aspeed_ast27x0-fc.c @@ -56,7 +56,7 @@ struct Ast2700FCState { #define AST2700FC_FMC_MODEL "w25q01jvq" #define AST2700FC_SPI_MODEL "w25q512jv" -static void ast2700fc_ca35_init(MachineState *machine) +static bool ast2700fc_ca35_init(MachineState *machine, Error **errp) { Ast2700FCState *s = AST2700A1FC(machine); AspeedSoCState *soc; @@ -71,22 +71,15 @@ static void ast2700fc_ca35_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), 0, &s->ca35_memory); if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram", - AST2700FC_BMC_RAM_SIZE, &error_abort)) { - return; - } - if (!object_property_set_link(OBJECT(&s->ca35), "memory", - OBJECT(&s->ca35_memory), - &error_abort)) { - return; - }; - if (!object_property_set_link(OBJECT(&s->ca35), "dram", - OBJECT(&s->ca35_dram), &error_abort)) { - return; - } - if (!object_property_set_int(OBJECT(&s->ca35), "ram-size", - AST2700FC_BMC_RAM_SIZE, &error_abort)) { - return; + AST2700FC_BMC_RAM_SIZE, errp)) { + return false; } + object_property_set_link(OBJECT(&s->ca35), "memory", + OBJECT(&s->ca35_memory), &error_abort); + object_property_set_link(OBJECT(&s->ca35), "dram", OBJECT(&s->ca35_dram), + &error_abort); + object_property_set_int(OBJECT(&s->ca35), "ram-size", + AST2700FC_BMC_RAM_SIZE, &error_abort); for (int i = 0; i < sc->macs_num; i++) { if (!qemu_configure_nic_device(DEVICE(&soc->ftgmac100[i]), @@ -94,17 +87,13 @@ static void ast2700fc_ca35_init(MachineState *machine) break; } } - if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap1", - AST2700FC_HW_STRAP1, &error_abort)) { - return; - } - if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap2", - AST2700FC_HW_STRAP2, &error_abort)) { - return; - } + object_property_set_int(OBJECT(&s->ca35), "hw-strap1", + AST2700FC_HW_STRAP1, &error_abort); + object_property_set_int(OBJECT(&s->ca35), "hw-strap2", + AST2700FC_HW_STRAP2, &error_abort); aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART12, serial_hd(0)); - if (!qdev_realize(DEVICE(&s->ca35), NULL, &error_abort)) { - return; + if (!qdev_realize(DEVICE(&s->ca35), NULL, errp)) { + return false; } /* @@ -119,9 +108,11 @@ static void ast2700fc_ca35_init(MachineState *machine) ast2700fc_board_info.loader_start = sc->memmap[ASPEED_DEV_SDRAM]; arm_load_kernel(ARM_CPU(first_cpu), machine, &ast2700fc_board_info); + + return true; } -static void ast2700fc_ssp_init(MachineState *machine) +static bool ast2700fc_ssp_init(MachineState *machine, Error **errp) { AspeedSoCState *soc; Ast2700FCState *s = AST2700A1FC(machine); @@ -133,19 +124,19 @@ static void ast2700fc_ssp_init(MachineState *machine) UINT64_MAX); qdev_connect_clock_in(DEVICE(&s->ssp), "sysclk", s->ssp_sysclk); - if (!object_property_set_link(OBJECT(&s->ssp), "memory", - OBJECT(&s->ssp_memory), &error_abort)) { - return; - } + object_property_set_link(OBJECT(&s->ssp), "memory", + OBJECT(&s->ssp_memory), &error_abort); soc = ASPEED_SOC(&s->ssp); aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART4, serial_hd(1)); - if (!qdev_realize(DEVICE(&s->ssp), NULL, &error_abort)) { - return; + if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) { + return false; } + + return true; } -static void ast2700fc_tsp_init(MachineState *machine) +static bool ast2700fc_tsp_init(MachineState *machine, Error **errp) { AspeedSoCState *soc; Ast2700FCState *s = AST2700A1FC(machine); @@ -157,23 +148,23 @@ static void ast2700fc_tsp_init(MachineState *machine) UINT64_MAX); qdev_connect_clock_in(DEVICE(&s->tsp), "sysclk", s->tsp_sysclk); - if (!object_property_set_link(OBJECT(&s->tsp), "memory", - OBJECT(&s->tsp_memory), &error_abort)) { - return; - } + object_property_set_link(OBJECT(&s->tsp), "memory", + OBJECT(&s->tsp_memory), &error_abort); soc = ASPEED_SOC(&s->tsp); aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART7, serial_hd(2)); - if (!qdev_realize(DEVICE(&s->tsp), NULL, &error_abort)) { - return; + if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) { + return false; } + + return true; } static void ast2700fc_init(MachineState *machine) { - ast2700fc_ca35_init(machine); - ast2700fc_ssp_init(machine); - ast2700fc_tsp_init(machine); + ast2700fc_ca35_init(machine, &error_abort); + ast2700fc_ssp_init(machine, &error_abort); + ast2700fc_tsp_init(machine, &error_abort); } static void ast2700fc_class_init(ObjectClass *oc, const void *data) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index 6aa3841b69..853339119f 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -38,6 +38,8 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_EHCI2] = 0x12063000, [ASPEED_DEV_HACE] = 0x12070000, [ASPEED_DEV_EMMC] = 0x12090000, + [ASPEED_DEV_PCIE0] = 0x120E0000, + [ASPEED_DEV_PCIE1] = 0x120F0000, [ASPEED_DEV_INTC] = 0x12100000, [ASPEED_GIC_DIST] = 0x12200000, [ASPEED_GIC_REDIST] = 0x12280000, @@ -45,6 +47,8 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_SCU] = 0x12C02000, [ASPEED_DEV_RTC] = 0x12C0F000, [ASPEED_DEV_TIMER1] = 0x12C10000, + [ASPEED_DEV_PCIE_PHY0] = 0x12C15000, + [ASPEED_DEV_PCIE_PHY1] = 0x12C15800, [ASPEED_DEV_SLI] = 0x12C17000, [ASPEED_DEV_UART4] = 0x12C1A000, [ASPEED_DEV_IOMEM1] = 0x14000000, @@ -59,6 +63,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_ETH2] = 0x14060000, [ASPEED_DEV_ETH3] = 0x14070000, [ASPEED_DEV_SDHCI] = 0x14080000, + [ASPEED_DEV_PCIE2] = 0x140D0000, [ASPEED_DEV_EHCI3] = 0x14121000, [ASPEED_DEV_EHCI4] = 0x14123000, [ASPEED_DEV_ADC] = 0x14C00000, @@ -66,6 +71,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_GPIO] = 0x14C0B000, [ASPEED_DEV_I2C] = 0x14C0F000, [ASPEED_DEV_INTCIO] = 0x14C18000, + [ASPEED_DEV_PCIE_PHY2] = 0x14C1C000, [ASPEED_DEV_SLIIO] = 0x14C1E000, [ASPEED_DEV_VUART] = 0x14C30000, [ASPEED_DEV_UART0] = 0x14C33000, @@ -81,6 +87,9 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_UART11] = 0x14C33A00, [ASPEED_DEV_UART12] = 0x14C33B00, [ASPEED_DEV_WDT] = 0x14C37000, + [ASPEED_DEV_PCIE_MMIO0] = 0x60000000, + [ASPEED_DEV_PCIE_MMIO1] = 0x80000000, + [ASPEED_DEV_PCIE_MMIO2] = 0xA0000000, [ASPEED_DEV_SPI_BOOT] = 0x100000000, [ASPEED_DEV_LTPI] = 0x300000000, [ASPEED_DEV_SDRAM] = 0x400000000, @@ -156,6 +165,8 @@ static const int aspeed_soc_ast2700a1_irqmap[] = { [ASPEED_DEV_DP] = 28, [ASPEED_DEV_EHCI1] = 33, [ASPEED_DEV_EHCI2] = 37, + [ASPEED_DEV_PCIE0] = 56, + [ASPEED_DEV_PCIE1] = 57, [ASPEED_DEV_LPC] = 192, [ASPEED_DEV_IBT] = 192, [ASPEED_DEV_KCS] = 192, @@ -166,6 +177,7 @@ static const int aspeed_soc_ast2700a1_irqmap[] = { [ASPEED_DEV_WDT] = 195, [ASPEED_DEV_PWM] = 195, [ASPEED_DEV_I3C] = 195, + [ASPEED_DEV_PCIE2] = 196, [ASPEED_DEV_UART0] = 196, [ASPEED_DEV_UART1] = 196, [ASPEED_DEV_UART2] = 196, @@ -233,6 +245,7 @@ static const int ast2700_gic132_gic196_intcmap[] = { [ASPEED_DEV_UART12] = 18, [ASPEED_DEV_EHCI3] = 28, [ASPEED_DEV_EHCI4] = 29, + [ASPEED_DEV_PCIE2] = 31, }; /* GICINT 133 */ @@ -519,6 +532,17 @@ static void aspeed_soc_ast2700_init(Object *obj) snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname); object_initialize_child(obj, "hace", &s->hace, typename); + + for (i = 0; i < sc->pcie_num; i++) { + snprintf(typename, sizeof(typename), "aspeed.pcie-phy-%s", socname); + object_initialize_child(obj, "pcie-phy[*]", &s->pcie_phy[i], typename); + object_property_set_int(OBJECT(&s->pcie_phy[i]), "id", i, &error_abort); + + snprintf(typename, sizeof(typename), "aspeed.pcie-cfg-%s", socname); + object_initialize_child(obj, "pcie-cfg[*]", &s->pcie[i], typename); + object_property_set_int(OBJECT(&s->pcie[i]), "id", i, &error_abort); + } + object_initialize_child(obj, "dpmcu", &s->dpmcu, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "ltpi", &s->ltpi, @@ -610,6 +634,49 @@ static bool aspeed_soc_ast2700_gic_realize(DeviceState *dev, Error **errp) return true; } +static bool aspeed_soc_ast2700_pcie_realize(DeviceState *dev, Error **errp) +{ + AspeedSoCState *s = ASPEED_SOC(dev); + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + MemoryRegion *mmio_mr = NULL; + char name[64]; + qemu_irq irq; + int i; + + for (i = 0; i < sc->pcie_num; i++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy[i]), errp)) { + return false; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie_phy[i]), 0, + sc->memmap[ASPEED_DEV_PCIE_PHY0 + i]); + + object_property_set_int(OBJECT(&s->pcie[i]), "dram-base", + sc->memmap[ASPEED_DEV_SDRAM], + &error_abort); + object_property_set_link(OBJECT(&s->pcie[i]), "dram", + OBJECT(s->dram_mr), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie[i]), errp)) { + return false; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie[i]), 0, + sc->memmap[ASPEED_DEV_PCIE0 + i]); + irq = aspeed_soc_get_irq(s, ASPEED_DEV_PCIE0 + i); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie[i].rc), 0, irq); + + mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pcie[i].rc), 1); + snprintf(name, sizeof(name), "aspeed.pcie-mmio.%d", i); + memory_region_init_alias(&s->pcie_mmio_alias[i], OBJECT(&s->pcie[i].rc), + name, mmio_mr, + sc->memmap[ASPEED_DEV_PCIE_MMIO0 + i], + 0x20000000); + memory_region_add_subregion(s->memory, + sc->memmap[ASPEED_DEV_PCIE_MMIO0 + i], + &s->pcie_mmio_alias[i]); + } + + return true; +} + static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) { int i; @@ -936,6 +1003,11 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0, aspeed_soc_get_irq(s, ASPEED_DEV_HACE)); + /* PCIe Root Complex (RC) */ + if (!aspeed_soc_ast2700_pcie_realize(dev, errp)) { + return; + } + aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->dpmcu), "aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU], @@ -974,6 +1046,7 @@ static void aspeed_soc_ast2700a0_class_init(ObjectClass *oc, const void *data) sc->valid_cpu_types = valid_cpu_types; sc->silicon_rev = AST2700_A0_SILICON_REV; sc->sram_size = 0x20000; + sc->pcie_num = 0; sc->spis_num = 3; sc->ehcis_num = 2; sc->wdts_num = 8; @@ -1002,6 +1075,7 @@ static void aspeed_soc_ast2700a1_class_init(ObjectClass *oc, const void *data) sc->valid_cpu_types = valid_cpu_types; sc->silicon_rev = AST2700_A1_SILICON_REV; sc->sram_size = 0x20000; + sc->pcie_num = 3; sc->spis_num = 3; sc->ehcis_num = 4; sc->wdts_num = 8; diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c index 1c4ac93a0f..bc70e864fb 100644 --- a/hw/arm/aspeed_soc_common.c +++ b/hw/arm/aspeed_soc_common.c @@ -16,6 +16,10 @@ #include "hw/misc/unimp.h" #include "hw/arm/aspeed_soc.h" #include "hw/char/serial-mm.h" +#include "system/blockdev.h" +#include "system/block-backend.h" +#include "hw/loader.h" +#include "qemu/datadir.h" const char *aspeed_soc_cpu_type(AspeedSoCClass *sc) @@ -124,6 +128,98 @@ void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev, sysbus_mmio_get_region(dev, 0), -1000); } +void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, + unsigned int count, int unit0) +{ + int i; + + if (!flashtype) { + return; + } + + for (i = 0; i < count; ++i) { + DriveInfo *dinfo = drive_get(IF_MTD, 0, unit0 + i); + DeviceState *dev; + + dev = qdev_new(flashtype); + if (dinfo) { + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); + } + qdev_prop_set_uint8(dev, "cs", i); + qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal); + } +} + +void aspeed_write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size, + Error **errp) +{ + g_autofree void *storage = NULL; + int64_t size; + + /* + * The block backend size should have already been 'validated' by + * the creation of the m25p80 object. + */ + size = blk_getlength(blk); + if (size <= 0) { + error_setg(errp, "failed to get flash size"); + return; + } + + if (rom_size > size) { + rom_size = size; + } + + storage = g_malloc0(rom_size); + if (blk_pread(blk, 0, rom_size, storage, 0) < 0) { + error_setg(errp, "failed to read the initial flash content"); + return; + } + + 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. + */ +void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk, + MemoryRegion *boot_rom, uint64_t rom_size) +{ + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc); + + 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); + aspeed_write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT], rom_size, + &error_abort); +} + +/* + * This function locates the vbootrom image file specified via the command line + * using the -bios option. It loads the specified image into the vbootrom + * memory region and handles errors if the file cannot be found or loaded. + */ +void aspeed_load_vbootrom(AspeedSoCState *soc, const char *bios_name, + Error **errp) +{ + g_autofree char *filename = NULL; + int ret; + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!filename) { + error_setg(errp, "Could not find vbootrom image '%s'", bios_name); + return; + } + + ret = load_image_mr(filename, &soc->vbootrom); + if (ret < 0) { + error_setg(errp, "Failed to load vbootrom image '%s'", bios_name); + return; + } +} + static void aspeed_soc_realize(DeviceState *dev, Error **errp) { AspeedSoCState *s = ASPEED_SOC(dev); |