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 <steven_lee@aspeedtech.com>
---
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
© 2016 - 2026 Red Hat, Inc.