]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
hw/arm/ast27x0: Share single SCU instance across PSP, SSP, and TSP
authorJamin Lin <jamin_lin@aspeedtech.com>
Wed, 15 Oct 2025 06:22:00 +0000 (14:22 +0800)
committerCédric Le Goater <clg@redhat.com>
Wed, 22 Oct 2025 06:14:08 +0000 (08:14 +0200)
AST2700 has a single SCU hardware block, memory-mapped at
0x12C02000–0x12C03FFF from the perspective of the main CA35 processor (PSP).
The SSP and TSP coprocessors access this same SCU block at different
addresses: 0x72C02000–0x72C03FFF.

Previously, each subsystem (PSP, SSP, and TSP) instantiated its own SCU
device, resulting in three independent SCU instances in the QEMU model.
In real hardware, however, only a single SCU exists and is shared among
all processors.

This commit reworks the SCU model to correctly reflect the hardware
behavior by allowing SSP and TSP to reference the PSP’s SCU instance.
The following changes are introduced:

- Add a scu property to AspeedCoprocessorState for linking the
  coprocessor to the PSP’s SCU instance.
- Replace per-coprocessor SCU instantiation with a shared SCU link.
- Add "MemoryRegion scu_alias" to model address remapping for SSP and TSP.
- Create SCU alias regions in both SSP and TSP coprocessors and map
  them at 0x72C02000 to mirror the PSP’s SCU registers.
- Ensure the SCU device in PSP is realized before SSP/TSP alias setup.

With this change, PSP, SSP, and TSP now share a consistent SCU state,
matching the single-SCU hardware design of AST2700.

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20251015062210.3128710-6-jamin_lin@aspeedtech.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
hw/arm/aspeed_ast27x0-fc.c
hw/arm/aspeed_ast27x0-ssp.c
hw/arm/aspeed_ast27x0-tsp.c
hw/arm/aspeed_coprocessor_common.c
include/hw/arm/aspeed_coprocessor.h

index dfac7d1e17b84154dc22ec75a03fa690c4848ed0..ba43a4620760c825124f3d74d39a2d7606e9c6d2 100644 (file)
@@ -138,6 +138,8 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
                             sc->uarts_num, serial_hd(1));
     object_property_set_link(OBJECT(&s->ssp), "sram",
                              OBJECT(&psp->sram), &error_abort);
+    object_property_set_link(OBJECT(&s->ssp), "scu",
+                             OBJECT(&psp->scu), &error_abort);
     if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) {
         return false;
     }
@@ -170,6 +172,8 @@ static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
                             sc->uarts_num, serial_hd(2));
     object_property_set_link(OBJECT(&s->tsp), "sram",
                              OBJECT(&psp->sram), &error_abort);
+    object_property_set_link(OBJECT(&s->tsp), "scu",
+                             OBJECT(&psp->scu), &error_abort);
     if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) {
         return false;
     }
index 66c4ef6d1b748996da97876bee8d66f0f0889bdf..577a3379c6c02fed6a73c9be152877fe5f37c3e7 100644 (file)
@@ -137,9 +137,7 @@ static void aspeed_soc_ast27x0ssp_init(Object *obj)
     int i;
 
     object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
-    object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCU);
     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
-    qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev);
 
     for (i = 0; i < sc->uarts_num; i++) {
         object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
@@ -203,11 +201,11 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
                                 &s->sram_alias);
 
     /* SCU */
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
-        return;
-    }
-    aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
-                    sc->memmap[ASPEED_DEV_SCU]);
+    memory_region_init_alias(&s->scu_alias, OBJECT(s), "scu.alias",
+                             &s->scu->iomem, 0,
+                             memory_region_size(&s->scu->iomem));
+    memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCU],
+                                &s->scu_alias);
 
     /* INTC */
     if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
@@ -285,7 +283,6 @@ static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
     dc->realize = aspeed_soc_ast27x0ssp_realize;
 
     sc->valid_cpu_types = valid_cpu_types;
-    sc->silicon_rev = AST2700_A1_SILICON_REV;
     sc->uarts_num = 13;
     sc->uarts_base = ASPEED_DEV_UART0;
     sc->irqmap = aspeed_soc_ast27x0ssp_irqmap;
index 56b68adf541ba80db50666a5d06bd6dc09e1e845..a7c141678fc28577cce6392a9ce1d18f38371c28 100644 (file)
@@ -137,9 +137,7 @@ static void aspeed_soc_ast27x0tsp_init(Object *obj)
     int i;
 
     object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
-    object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCU);
     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
-    qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev);
 
     for (i = 0; i < sc->uarts_num; i++) {
         object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
@@ -203,11 +201,11 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
                                 &s->sram_alias);
 
     /* SCU */
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
-        return;
-    }
-    aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
-                    sc->memmap[ASPEED_DEV_SCU]);
+    memory_region_init_alias(&s->scu_alias, OBJECT(s), "scu.alias",
+                             &s->scu->iomem, 0,
+                             memory_region_size(&s->scu->iomem));
+    memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCU],
+                                &s->scu_alias);
 
     /* INTC */
     if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
@@ -285,7 +283,6 @@ static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
     dc->realize = aspeed_soc_ast27x0tsp_realize;
 
     sc->valid_cpu_types = valid_cpu_types;
-    sc->silicon_rev = AST2700_A1_SILICON_REV;
     sc->uarts_num = 13;
     sc->uarts_base = ASPEED_DEV_UART0;
     sc->irqmap = aspeed_soc_ast27x0tsp_irqmap;
index 8322ad5eb544a3ce48deffed294c71beaac79796..14e26bbe234ed5001a754be3430e704aeb5c3777 100644 (file)
@@ -27,6 +27,8 @@ static const Property aspeed_coprocessor_properties[] = {
                      TYPE_MEMORY_REGION, MemoryRegion *),
     DEFINE_PROP_LINK("sram", AspeedCoprocessorState, sram, TYPE_MEMORY_REGION,
                      MemoryRegion *),
+    DEFINE_PROP_LINK("scu", AspeedCoprocessorState, scu, TYPE_ASPEED_SCU,
+                     AspeedSCUState *),
 };
 
 static void aspeed_coprocessor_class_init(ObjectClass *oc, const void *data)
index d9a5f517d7c78afdf483c1f6584d087ef986741c..c1f2c549c323ffb9ad69136128f703aceaf3187d 100644 (file)
@@ -19,9 +19,10 @@ struct AspeedCoprocessorState {
     MemoryRegion sdram;
     MemoryRegion *sram;
     MemoryRegion sram_alias;
+    MemoryRegion scu_alias;
     Clock *sysclk;
 
-    AspeedSCUState scu;
+    AspeedSCUState *scu;
     AspeedSCUState scuio;
     AspeedTimerCtrlState timerctrl;
     SerialMM uart[ASPEED_UARTS_NUM];
@@ -36,7 +37,6 @@ struct AspeedCoprocessorClass {
 
     /** valid_cpu_types: NULL terminated array of a single CPU type. */
     const char * const *valid_cpu_types;
-    uint32_t silicon_rev;
     const hwaddr *memmap;
     const int *irqmap;
     int uarts_base;