Instantiate the Caliptra mailbox in the AST1040 SoC and map its SRAM and CSR windows at the guest-visible MCI addresses.
Add the 4 KiB MCI aperture controlled by the AST1040 SCU CPTRA page register, switch the SoC to the AST1040 SCU model, and expose a machine option that links an external mailbox peer after machine initialization. Signed-off-by: Steven Lee <[email protected]> --- include/hw/arm/aspeed_soc.h | 11 ++++++ hw/arm/aspeed_ast1040.c | 60 ++++++++++++++++++++++++++++-- hw/arm/aspeed_ast1040_evb.c | 74 ++++++++++++++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 5 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 3aac144cd4..9fad3bc082 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -46,6 +46,7 @@ #include "hw/intc/arm_gicv3.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/arm/aspeed_ast1700.h" +#include "hw/misc/aspeed_cptra_mbox.h" #define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" @@ -165,6 +166,16 @@ struct Aspeed10x0SoCState { #define TYPE_ASPEED10X0_SOC "aspeed10x0-soc" OBJECT_DECLARE_SIMPLE_TYPE(Aspeed10x0SoCState, ASPEED10X0_SOC) +struct Aspeed1040SoCState { + Aspeed10x0SoCState parent; + + AspeedCptraMboxState cptra_mbox; + MemoryRegion cptra_mci_window; +}; + +#define TYPE_ASPEED1040_SOC "ast1040-a0" +OBJECT_DECLARE_SIMPLE_TYPE(Aspeed1040SoCState, ASPEED1040_SOC) + struct AspeedSoCClass { DeviceClass parent_class; diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index 8efcdad8f6..c597982bc5 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -8,12 +8,17 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "system/address-spaces.h" #include "system/system.h" #include "hw/core/qdev-clock.h" #include "hw/misc/unimp.h" +#include "hw/misc/aspeed_cptra_mbox.h" #include "hw/arm/aspeed_soc.h" +#define AST1040_CPTRA_MCI_WINDOW_BASE 0x74200000 +#define AST1040_CPTRA_MCI_WINDOW_SIZE 0x1000 +#define AST1040_CPTRA_MBOX_SRAM_BASE 0x21400000 +#define AST1040_CPTRA_MBOX_CSR_BASE 0x21600000 + static const hwaddr aspeed_soc_ast1040_memmap[] = { [ASPEED_DEV_SRAM1] = 0x00000000, /* Hyper RAM */ [ASPEED_DEV_FMC] = 0x74000000, @@ -88,6 +93,7 @@ static qemu_irq aspeed_soc_ast1040_get_irq(AspeedSoCState *s, int dev) static void aspeed_soc_ast1040_init(Object *obj) { + Aspeed1040SoCState *a1040 = ASPEED1040_SOC(obj); Aspeed10x0SoCState *a = ASPEED10X0_SOC(obj); AspeedSoCState *s = ASPEED_SOC(obj); AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); @@ -96,12 +102,13 @@ static void aspeed_soc_ast1040_init(Object *obj) s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0); - /* AST1040 uses the AST2700 SCUIO model */ - object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCUIO); + object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_1040_SCU); qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev); object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), "hw-strap1"); object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), "hw-strap2"); + object_initialize_child(obj, "cptra-mbox", &a1040->cptra_mbox, + TYPE_ASPEED_CPTRA_MBOX); for (i = 0; i < sc->uarts_num; i++) { object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM); @@ -120,8 +127,31 @@ static void aspeed_soc_ast1040_init(Object *obj) TYPE_UNIMPLEMENTED_DEVICE); } +static bool aspeed_soc_ast1040_realize_cptra_mbox(Aspeed1040SoCState *a1040, + Error **errp) +{ + AspeedSoCState *s = ASPEED_SOC(a1040); + DeviceState *mbox = DEVICE(&a1040->cptra_mbox); + + /* + * Caliptra is an AST1040 integrated RoT IP. The external peer is + * optional; without a peer, the mailbox registers remain present and + * EXECUTE completes with CMD_FAILURE. + */ + if (!sysbus_realize(SYS_BUS_DEVICE(mbox), errp)) { + return false; + } + + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(mbox), 0, + AST1040_CPTRA_MBOX_SRAM_BASE); + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(mbox), 1, + AST1040_CPTRA_MBOX_CSR_BASE); + return true; +} + static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) { + Aspeed1040SoCState *a1040 = ASPEED1040_SOC(dev_soc); Aspeed10x0SoCState *a = ASPEED10X0_SOC(dev_soc); AspeedSoCState *s = ASPEED_SOC(dev_soc); AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); @@ -171,6 +201,27 @@ static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SRAM1], &s->sram[1]); + if (!aspeed_soc_ast1040_realize_cptra_mbox(a1040, errp)) { + return; + } + + /* + * The Caliptra MCI aperture is a 4 KiB alias whose target is selected by + * AST1040_SCU_CPTRA_PAGE_REG0. Firmware commonly switches it between + * mailbox SRAM (0x21400000) and mailbox CSR (0x21600000), then accesses + * the selected page through 0x74200000. + */ + memory_region_init_alias(&a1040->cptra_mci_window, OBJECT(s), + "aspeed.ast1040.cptra-mci-window", s->memory, + 0, AST1040_CPTRA_MCI_WINDOW_SIZE); + memory_region_add_subregion(s->memory, AST1040_CPTRA_MCI_WINDOW_BASE, + &a1040->cptra_mci_window); + /* The SCU drives the aperture's target offset via SCU_CPTRA_PAGE_REG0. */ + object_property_set_link(OBJECT(&s->scu), "cptra-page-window", + OBJECT(&a1040->cptra_mci_window), &error_abort); + object_property_set_uint(OBJECT(&s->scu), "cptra-page-window-base", + AST1040_CPTRA_MCI_WINDOW_BASE, &error_abort); + /* SCU */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; @@ -244,8 +295,9 @@ static void aspeed_soc_ast1040_class_init(ObjectClass *klass, const void *data) static const TypeInfo aspeed_soc_ast1040_types[] = { { - .name = "ast1040-a0", + .name = TYPE_ASPEED1040_SOC, .parent = TYPE_ASPEED10X0_SOC, + .instance_size = sizeof(Aspeed1040SoCState), .instance_init = aspeed_soc_ast1040_init, .class_init = aspeed_soc_ast1040_class_init, } diff --git a/hw/arm/aspeed_ast1040_evb.c b/hw/arm/aspeed_ast1040_evb.c index 1d9b55247f..eb325a1095 100644 --- a/hw/arm/aspeed_ast1040_evb.c +++ b/hw/arm/aspeed_ast1040_evb.c @@ -8,17 +8,59 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "hw/arm/boot.h" #include "hw/arm/machines-qom.h" #include "hw/arm/aspeed.h" #include "hw/arm/aspeed_soc.h" #include "hw/core/qdev-clock.h" +#include "hw/misc/aspeed_cptra_mbox.h" #include "system/system.h" #define AST1040_INTERNAL_FLASH_SIZE (4 * MiB) /* Main SYSCLK frequency in Hz (400MHz) */ #define SYSCLK_FRQ 400000000ULL +#define TYPE_AST1040_EVB_MACHINE MACHINE_TYPE_NAME("ast1040-evb") +OBJECT_DECLARE_SIMPLE_TYPE(Ast1040EvbMachineState, AST1040_EVB_MACHINE) + +struct Ast1040EvbMachineState { + AspeedMachineState parent_obj; + + char *cptra_peer; + Notifier machine_done; +}; + +static void aspeed_bic_machine_done(Notifier *notifier, void *data) +{ + Ast1040EvbMachineState *m = container_of(notifier, + Ast1040EvbMachineState, + machine_done); + AspeedMachineState *bmc = ASPEED_MACHINE(m); + Aspeed1040SoCState *a1040 = ASPEED1040_SOC(bmc->soc); + bool ambiguous = false; + Object *peer; + Error *err = NULL; + + if (!m->cptra_peer) { + return; + } + + peer = object_resolve_path_type(m->cptra_peer, TYPE_CPTRA_MBOX_PEER, + &ambiguous); + if (!peer || ambiguous) { + error_report("cptra-peer: peer '%s' not found%s", + m->cptra_peer, ambiguous ? " (ambiguous)" : ""); + exit(1); + } + + if (!aspeed_cptra_mbox_set_peer(&a1040->cptra_mbox, + CPTRA_MBOX_PEER(peer), &err)) { + error_report_err(err); + exit(1); + } +} + static void aspeed_bic_machine_init(MachineState *machine) { AspeedMachineState *bmc = ASPEED_MACHINE(machine); @@ -38,12 +80,35 @@ static void aspeed_bic_machine_init(MachineState *machine) aspeed_connect_serial_hds_to_uarts(bmc); qdev_realize(DEVICE(bmc->soc), NULL, &error_abort); + if (AST1040_EVB_MACHINE(machine)->cptra_peer) { + AST1040_EVB_MACHINE(machine)->machine_done.notify = + aspeed_bic_machine_done; + qemu_add_machine_init_done_notifier( + &AST1040_EVB_MACHINE(machine)->machine_done); + } + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0, AST1040_INTERNAL_FLASH_SIZE); } +static char *aspeed_bic_get_cptra_peer(Object *obj, Error **errp) +{ + Ast1040EvbMachineState *m = AST1040_EVB_MACHINE(obj); + + return g_strdup(m->cptra_peer); +} + +static void aspeed_bic_set_cptra_peer(Object *obj, const char *value, + Error **errp) +{ + Ast1040EvbMachineState *m = AST1040_EVB_MACHINE(obj); + + g_free(m->cptra_peer); + m->cptra_peer = g_strdup(value); +} + static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, const void *data) { @@ -59,12 +124,19 @@ static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, amc->macs_mask = 0; amc->uart_default = ASPEED_DEV_UART12; aspeed_machine_class_init_cpus_defaults(mc); + + object_class_property_add_str(oc, "cptra-peer", + aspeed_bic_get_cptra_peer, + aspeed_bic_set_cptra_peer); + object_class_property_set_description(oc, "cptra-peer", + "Caliptra mailbox peer object id"); } static const TypeInfo aspeed_ast1040_evb_types[] = { { - .name = MACHINE_TYPE_NAME("ast1040-evb"), + .name = TYPE_AST1040_EVB_MACHINE, .parent = TYPE_ASPEED_MACHINE, + .instance_size = sizeof(Ast1040EvbMachineState), .class_init = aspeed_machine_ast1040_evb_class_init, .interfaces = arm_machine_interfaces, } -- 2.43.0
