Initial definitions for a simple machine using an AST2600 SoC (Cortex CPU).
Differences with the AST2400 and the AST2500 SoCs are handled using the ASPEED_IS_AST2600() macro. This is not optimal but it is not too invasive either. We could modify the model to add custom instance_init and realize handlers in the future. Signed-off-by: Cédric Le Goater <c...@kaod.org> --- include/hw/arm/aspeed_soc.h | 4 + include/hw/misc/aspeed_scu.h | 1 + hw/arm/aspeed.c | 18 ++++ hw/arm/aspeed_soc.c | 189 ++++++++++++++++++++++++++++++++--- 4 files changed, 197 insertions(+), 15 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index b427f2668a8a..74db48374531 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -12,6 +12,7 @@ #ifndef ASPEED_SOC_H #define ASPEED_SOC_H +#include "hw/cpu/a15mpcore.h" #include "hw/intc/aspeed_vic.h" #include "hw/misc/aspeed_scu.h" #include "hw/misc/aspeed_sdmc.h" @@ -38,6 +39,7 @@ typedef struct AspeedSoCState { /*< public >*/ ARMCPU cpu[ASPEED_CPUS_NUM]; uint32_t num_cpus; + A15MPPrivState a7mpcore; MemoryRegion sram; AspeedVICState vic; AspeedRtcState rtc; @@ -51,6 +53,7 @@ typedef struct AspeedSoCState { AspeedWDTState wdt[ASPEED_WDTS_NUM]; FTGMAC100State ftgmac100[ASPEED_MACS_NUM]; AspeedGPIOState gpio; + AspeedGPIOState gpio_1_8v; AspeedSDHCIState sdhci; } AspeedSoCState; @@ -97,6 +100,7 @@ enum { ASPEED_SRAM, ASPEED_SDHCI, ASPEED_GPIO, + ASPEED_GPIO_1_8V, ASPEED_RTC, ASPEED_TIMER1, ASPEED_TIMER2, diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h index 1d7f7ffc1598..670804e85f28 100644 --- a/include/hw/misc/aspeed_scu.h +++ b/include/hw/misc/aspeed_scu.h @@ -43,6 +43,7 @@ typedef struct AspeedSCUState { #define AST2600_A0_SILICON_REV 0x05000303U #define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04) +#define ASPEED_IS_AST2600(si_rev) ((((si_rev) >> 24) & 0xff) == 0x05) extern bool is_supported_silicon_rev(uint32_t silicon_rev); diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 03cc0952e8f3..f4f1dd29b011 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -88,6 +88,9 @@ struct AspeedBoardState { /* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */ #define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1 +/* AST2600 evb hardware value: (QEMU prototype) */ +#define AST2600_EVB_HW_STRAP1 AST2500_EVB_HW_STRAP1 + /* * The max ram region is for firmwares that scan the address space * with load/store to guess how much RAM the SoC has. @@ -294,6 +297,12 @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc) i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32); } +static void ast2600_evb_i2c_init(AspeedBoardState *bmc) +{ + /* Start with some devices on our I2C busses */ + ast2500_evb_i2c_init(bmc); +} + static void romulus_bmc_i2c_init(AspeedBoardState *bmc) { AspeedSoCState *soc = &bmc->soc; @@ -441,6 +450,15 @@ static const AspeedBoardConfig aspeed_boards[] = { .num_cs = 2, .i2c_init = witherspoon_bmc_i2c_init, .ram = 512 * MiB, + }, { + .name = MACHINE_TYPE_NAME("ast2600-evb"), + .desc = "Aspeed AST2600 EVB (Cortex A7)", + .soc_name = "ast2600-a0", + .hw_strap1 = AST2600_EVB_HW_STRAP1, + .fmc_model = "mx25l25635e", + .spi_model = "mx25l25635e", + .num_cs = 1, + .i2c_init = ast2600_evb_i2c_init, }, }; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 5c5fcb810944..80d7f206004c 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -81,6 +81,38 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_SDRAM] = 0x80000000, }; +static const hwaddr aspeed_soc_ast2600_memmap[] = { + [ASPEED_SRAM] = 0x10000000, + /* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */ + [ASPEED_IOMEM] = 0x1E600000, + [ASPEED_PWM] = 0x1E610000, + [ASPEED_FMC] = 0x1E620000, + [ASPEED_SPI1] = 0x1E630000, + [ASPEED_SPI2] = 0x1E641000, + [ASPEED_ETH1] = 0x1E660000, + [ASPEED_ETH2] = 0x1E680000, + [ASPEED_VIC] = 0x1E6C0000, + [ASPEED_SDMC] = 0x1E6E0000, + [ASPEED_SCU] = 0x1E6E2000, + [ASPEED_XDMA] = 0x1E6E7000, + [ASPEED_ADC] = 0x1E6E9000, + [ASPEED_SDHCI] = 0x1E740000, + [ASPEED_GPIO] = 0x1E780000, + [ASPEED_GPIO_1_8V] = 0x1E780800, + [ASPEED_RTC] = 0x1E781000, + [ASPEED_TIMER1] = 0x1E782000, + [ASPEED_WDT] = 0x1E785000, + [ASPEED_LPC] = 0x1E789000, + [ASPEED_IBT] = 0x1E789140, + [ASPEED_I2C] = 0x1E78A000, + [ASPEED_UART1] = 0x1E783000, + [ASPEED_UART5] = 0x1E784000, + [ASPEED_VUART] = 0x1E787000, + [ASPEED_SDRAM] = 0x80000000, +}; + +#define ASPEED_A7MPCORE_ADDR 0x40460000 + static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_UART1] = 9, [ASPEED_UART2] = 32, @@ -115,6 +147,41 @@ static const int aspeed_soc_ast2400_irqmap[] = { #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap +#define ASPEED_SOC_AST2600_MAX_IRQ 128 + +static const int aspeed_soc_ast2600_irqmap[] = { + [ASPEED_UART1] = 47, + [ASPEED_UART2] = 48, + [ASPEED_UART3] = 49, + [ASPEED_UART4] = 50, + [ASPEED_UART5] = 8, + [ASPEED_VUART] = 8, + [ASPEED_FMC] = 39, + [ASPEED_SDMC] = 0, + [ASPEED_SCU] = 12, + [ASPEED_XDMA] = 6, + [ASPEED_ADC] = 46, + [ASPEED_SDHCI] = 43, + [ASPEED_GPIO] = 40, + [ASPEED_GPIO_1_8V] = 11, + [ASPEED_RTC] = 13, + [ASPEED_TIMER1] = 16, + [ASPEED_TIMER2] = 17, + [ASPEED_TIMER3] = 18, + [ASPEED_TIMER4] = 19, + [ASPEED_TIMER5] = 20, + [ASPEED_TIMER6] = 21, + [ASPEED_TIMER7] = 22, + [ASPEED_TIMER8] = 23, + [ASPEED_WDT] = 24, + [ASPEED_PWM] = 44, + [ASPEED_LPC] = 35, + [ASPEED_IBT] = 35, /* LPC */ + [ASPEED_I2C] = 110, /* 110 -> 125 */ + [ASPEED_ETH1] = 2, + [ASPEED_ETH2] = 3, +}; + static const AspeedSoCInfo aspeed_socs[] = { { .name = "ast2400-a1", @@ -136,14 +203,26 @@ static const AspeedSoCInfo aspeed_socs[] = { .irqmap = aspeed_soc_ast2500_irqmap, .memmap = aspeed_soc_ast2500_memmap, .num_cpus = 1, + }, { + .name = "ast2600-a0", + .cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"), + .silicon_rev = AST2600_A0_SILICON_REV, + .sram_size = 0x10000, + .spis_num = 2, + .wdts_num = 4, + .irqmap = aspeed_soc_ast2600_irqmap, + .memmap = aspeed_soc_ast2600_memmap, + .num_cpus = 2, }, }; static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) { AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + DeviceState *intc = ASPEED_IS_AST2600(sc->info->silicon_rev) ? + DEVICE(&s->a7mpcore) : DEVICE(&s->vic); - return qdev_get_gpio_in(DEVICE(&s->vic), sc->info->irqmap[ctrl]); + return qdev_get_gpio_in(intc, sc->info->irqmap[ctrl]); } static void aspeed_soc_init(Object *obj) @@ -176,8 +255,13 @@ static void aspeed_soc_init(Object *obj) object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), "hw-prot-key", &error_abort); - sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic), - TYPE_ASPEED_VIC); + if (ASPEED_IS_AST2600(sc->info->silicon_rev)) { + sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, + sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV); + } else { + sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic), + TYPE_ASPEED_VIC); + } sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc), TYPE_ASPEED_RTC); @@ -233,6 +317,12 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio), typename); + if (ASPEED_IS_AST2600(sc->info->silicon_rev)) { + snprintf(typename, sizeof(typename), "aspeed.gpio-%s-1_8v", socname); + sysbus_init_child_obj(obj, "gpio_1_8v", OBJECT(&s->gpio_1_8v), + sizeof(s->gpio_1_8v), typename); + } + sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci), TYPE_ASPEED_SDHCI); @@ -243,6 +333,16 @@ static void aspeed_soc_init(Object *obj) } } +/* + * ASPEED ast2600 has 0xf as cluster ID + * + * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0388e/CIHEBGFG.html + */ +static uint64_t aspeed_calc_affinity(int cpu) +{ + return (0xf << ARM_AFF1_SHIFT) | cpu; +} + static void aspeed_soc_realize(DeviceState *dev, Error **errp) { int i; @@ -262,6 +362,23 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) /* CPU */ for (i = 0; i < s->num_cpus; i++) { + if (ASPEED_IS_AST2600(sc->info->silicon_rev)) { + object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC, + "psci-conduit", &error_abort); + if (s->num_cpus > 1) { + object_property_set_int(OBJECT(&s->cpu[i]), + ASPEED_A7MPCORE_ADDR, + "reset-cbar", &error_abort); + } + object_property_set_int(OBJECT(&s->cpu[i]), aspeed_calc_affinity(i), + "mp-affinity", &error_abort); + + /* + * TODO: the secondary CPUs are started and a boot helper + * is needed when using -kernel + */ + } + object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); if (err) { error_propagate(errp, err); @@ -269,6 +386,48 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) } } + /* A7MPCORE */ + if (ASPEED_IS_AST2600(sc->info->silicon_rev)) { + qemu_irq irq; + + object_property_set_int(OBJECT(&s->a7mpcore), s->num_cpus, "num-cpu", + &error_abort); + object_property_set_int(OBJECT(&s->a7mpcore), + ASPEED_SOC_AST2600_MAX_IRQ + GIC_INTERNAL, + "num-irq", &error_abort); + + object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized", + &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, ASPEED_A7MPCORE_ADDR); + + for (i = 0; i < s->num_cpus; i++) { + SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore); + DeviceState *d = DEVICE(qemu_get_cpu(i)); + + irq = qdev_get_gpio_in(d, ARM_CPU_IRQ); + sysbus_connect_irq(sbd, i, irq); + irq = qdev_get_gpio_in(d, ARM_CPU_FIQ); + sysbus_connect_irq(sbd, i + s->num_cpus, irq); + irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ); + sysbus_connect_irq(sbd, i + 2 * s->num_cpus, irq); + irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ); + sysbus_connect_irq(sbd, i + 3 * s->num_cpus, irq); + } + } else { + /* VIC */ + object_property_set_bool(OBJECT(&s->vic), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, + sc->info->memmap[ASPEED_VIC]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0, + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1, + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); + } + /* SRAM */ memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram", sc->info->sram_size, &err); @@ -287,18 +446,6 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->info->memmap[ASPEED_SCU]); - /* VIC */ - object_property_set_bool(OBJECT(&s->vic), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, sc->info->memmap[ASPEED_VIC]); - sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0, - qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ)); - sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1, - qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); - /* RTC */ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err); if (err) { @@ -433,6 +580,18 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, aspeed_soc_get_irq(s, ASPEED_GPIO)); + if (ASPEED_IS_AST2600(sc->info->silicon_rev)) { + object_property_set_bool(OBJECT(&s->gpio_1_8v), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio_1_8v), 0, + sc->info->memmap[ASPEED_GPIO_1_8V]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio_1_8v), 0, + aspeed_soc_get_irq(s, ASPEED_GPIO_1_8V)); + } + /* SDHCI */ object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); if (err) { -- 2.21.0