]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
hw/arm/ast27x0: Share single UART set across PSP, SSP, and TSP
authorJamin Lin <jamin_lin@aspeedtech.com>
Wed, 15 Oct 2025 06:22:01 +0000 (14:22 +0800)
committerCédric Le Goater <clg@redhat.com>
Wed, 22 Oct 2025 06:14:08 +0000 (08:14 +0200)
In the original model, each subsystem (PSP, SSP, and TSP) created its own
set of 13 UART devices, resulting in a total of 39 UART instances. However,
on real AST2700 hardware, there is only one set of 13 UARTs shared among
all processors.

This commit reworks the UART handling to correctly model the shared
hardware design. The PSP now creates the full set of 13 UART instances,
while the SSP and TSP link to the corresponding shared UART device
through object properties.

Changes include:
- Add "DEFINE_PROP_LINK("uart", ...)" and "DEFINE_PROP_INT32("uart-dev", ...)"
  to allow each coprocessor to reference a specific shared UART instance.
- Modify SSP to link to PSP’s UART4, and TSP to link to PSP’s UART7.
- Introduce "uart_alias" to remap the UART’s MMIO region into the coprocessor’s
  memory space.
- Redirect the UART interrupt to the coprocessor’s NVIC, replacing the
  default routing to the PSP’s GIC.

With this change, only one set of 13 UART devices is instantiated by the PSP,
while the SSP and TSP reuse them via aliasing and shared interrupt routing,
matching the real AST2700 hardware behavior.

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-7-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 ba43a4620760c825124f3d74d39a2d7606e9c6d2..99af87dbd7bd5bda4e3398a73f3fa93a7a45306c 100644 (file)
@@ -93,6 +93,10 @@ static bool ast2700fc_ca35_init(MachineState *machine, Error **errp)
                             AST2700FC_HW_STRAP2, &error_abort);
     aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART12, sc->uarts_base,
                             sc->uarts_num, serial_hd(0));
+    aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART4, sc->uarts_base,
+                            sc->uarts_num, serial_hd(1));
+    aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART7, sc->uarts_base,
+                            sc->uarts_num, serial_hd(2));
     if (!qdev_realize(DEVICE(&s->ca35), NULL, errp)) {
         return false;
     }
@@ -115,8 +119,6 @@ static bool ast2700fc_ca35_init(MachineState *machine, Error **errp)
 
 static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
 {
-    AspeedCoprocessorState *soc;
-    AspeedCoprocessorClass *sc;
     Ast2700FCState *s = AST2700A1FC(machine);
     AspeedSoCState *psp = ASPEED_SOC(&s->ca35);
 
@@ -132,10 +134,10 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
     object_property_set_link(OBJECT(&s->ssp), "memory",
                              OBJECT(&s->ssp_memory), &error_abort);
 
-    soc = ASPEED_COPROCESSOR(&s->ssp);
-    sc = ASPEED_COPROCESSOR_GET_CLASS(soc);
-    aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART4, sc->uarts_base,
-                            sc->uarts_num, serial_hd(1));
+    object_property_set_link(OBJECT(&s->ssp), "uart",
+                             OBJECT(&psp->uart[4]), &error_abort);
+    object_property_set_int(OBJECT(&s->ssp), "uart-dev", ASPEED_DEV_UART4,
+                            &error_abort);
     object_property_set_link(OBJECT(&s->ssp), "sram",
                              OBJECT(&psp->sram), &error_abort);
     object_property_set_link(OBJECT(&s->ssp), "scu",
@@ -149,8 +151,6 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
 
 static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
 {
-    AspeedCoprocessorState *soc;
-    AspeedCoprocessorClass *sc;
     Ast2700FCState *s = AST2700A1FC(machine);
     AspeedSoCState *psp = ASPEED_SOC(&s->ca35);
 
@@ -166,10 +166,10 @@ static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
     object_property_set_link(OBJECT(&s->tsp), "memory",
                              OBJECT(&s->tsp_memory), &error_abort);
 
-    soc = ASPEED_COPROCESSOR(&s->tsp);
-    sc = ASPEED_COPROCESSOR_GET_CLASS(soc);
-    aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART7, sc->uarts_base,
-                            sc->uarts_num, serial_hd(2));
+    object_property_set_link(OBJECT(&s->tsp), "uart",
+                             OBJECT(&psp->uart[7]), &error_abort);
+    object_property_set_int(OBJECT(&s->tsp), "uart-dev", ASPEED_DEV_UART7,
+                            &error_abort);
     object_property_set_link(OBJECT(&s->tsp), "sram",
                              OBJECT(&psp->sram), &error_abort);
     object_property_set_link(OBJECT(&s->tsp), "scu",
index 577a3379c6c02fed6a73c9be152877fe5f37c3e7..d12a9b8459c23235108859be2af8801f084a8d1d 100644 (file)
@@ -133,16 +133,10 @@ static void aspeed_soc_ast27x0ssp_init(Object *obj)
 {
     Aspeed27x0CoprocessorState *a = ASPEED27X0SSP_COPROCESSOR(obj);
     AspeedCoprocessorState *s = ASPEED_COPROCESSOR(obj);
-    AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
-    int i;
 
     object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
 
-    for (i = 0; i < sc->uarts_num; i++) {
-        object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
-    }
-
     object_initialize_child(obj, "intc0", &a->intc[0],
                             TYPE_ASPEED_2700SSP_INTC);
     object_initialize_child(obj, "intc1", &a->intc[1],
@@ -165,7 +159,6 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
     AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
     DeviceState *armv7m;
     g_autofree char *sdram_name = NULL;
-    int uart;
     int i;
 
     if (!clock_has_source(s->sysclk)) {
@@ -244,15 +237,19 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
         sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc[1]), i,
                         qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), i));
     }
+
     /* UART */
-    for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
-        if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
-                                     sc->memmap[uart], errp)) {
-            return;
-        }
-        sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
-                           aspeed_soc_ast27x0ssp_get_irq(s, uart));
-    }
+    memory_region_init_alias(&s->uart_alias, OBJECT(s), "uart.alias",
+                             &s->uart->serial.io, 0,
+                             memory_region_size(&s->uart->serial.io));
+    memory_region_add_subregion(s->memory, sc->memmap[s->uart_dev],
+                                &s->uart_alias);
+    /*
+     * Redirect the UART interrupt to the NVIC, replacing the default routing
+     * to the PSP's GIC.
+     */
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->uart), 0,
+                       aspeed_soc_ast27x0ssp_get_irq(s, s->uart_dev));
 
     aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->timerctrl),
                                   "aspeed.timerctrl",
@@ -283,8 +280,6 @@ static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
     dc->realize = aspeed_soc_ast27x0ssp_realize;
 
     sc->valid_cpu_types = valid_cpu_types;
-    sc->uarts_num = 13;
-    sc->uarts_base = ASPEED_DEV_UART0;
     sc->irqmap = aspeed_soc_ast27x0ssp_irqmap;
     sc->memmap = aspeed_soc_ast27x0ssp_memmap;
 }
index a7c141678fc28577cce6392a9ce1d18f38371c28..5b75e14206399f48b10ef9c93fab5e7c00d31715 100644 (file)
@@ -133,16 +133,10 @@ static void aspeed_soc_ast27x0tsp_init(Object *obj)
 {
     Aspeed27x0CoprocessorState *a = ASPEED27X0TSP_COPROCESSOR(obj);
     AspeedCoprocessorState *s = ASPEED_COPROCESSOR(obj);
-    AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
-    int i;
 
     object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
 
-    for (i = 0; i < sc->uarts_num; i++) {
-        object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
-    }
-
     object_initialize_child(obj, "intc0", &a->intc[0],
                             TYPE_ASPEED_2700TSP_INTC);
     object_initialize_child(obj, "intc1", &a->intc[1],
@@ -165,7 +159,6 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
     AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
     DeviceState *armv7m;
     g_autofree char *sdram_name = NULL;
-    int uart;
     int i;
 
     if (!clock_has_source(s->sysclk)) {
@@ -244,15 +237,19 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
         sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc[1]), i,
                         qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), i));
     }
+
     /* UART */
-    for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
-        if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
-                                     sc->memmap[uart], errp)) {
-            return;
-        }
-        sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
-                           aspeed_soc_ast27x0tsp_get_irq(s, uart));
-    }
+    memory_region_init_alias(&s->uart_alias, OBJECT(s), "uart.alias",
+                             &s->uart->serial.io, 0,
+                             memory_region_size(&s->uart->serial.io));
+    memory_region_add_subregion(s->memory, sc->memmap[s->uart_dev],
+                                &s->uart_alias);
+    /*
+     * Redirect the UART interrupt to the NVIC, replacing the default routing
+     * to the PSP's GIC.
+     */
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->uart), 0,
+                       aspeed_soc_ast27x0tsp_get_irq(s, s->uart_dev));
 
     aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->timerctrl),
                                   "aspeed.timerctrl",
@@ -283,8 +280,6 @@ static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
     dc->realize = aspeed_soc_ast27x0tsp_realize;
 
     sc->valid_cpu_types = valid_cpu_types;
-    sc->uarts_num = 13;
-    sc->uarts_base = ASPEED_DEV_UART0;
     sc->irqmap = aspeed_soc_ast27x0tsp_irqmap;
     sc->memmap = aspeed_soc_ast27x0tsp_memmap;
 }
index 14e26bbe234ed5001a754be3430e704aeb5c3777..f037d5b573fd419c1ce33320cc8bdb3b416d0acf 100644 (file)
@@ -29,6 +29,9 @@ static const Property aspeed_coprocessor_properties[] = {
                      MemoryRegion *),
     DEFINE_PROP_LINK("scu", AspeedCoprocessorState, scu, TYPE_ASPEED_SCU,
                      AspeedSCUState *),
+    DEFINE_PROP_LINK("uart", AspeedCoprocessorState, uart, TYPE_SERIAL_MM,
+                     SerialMM *),
+    DEFINE_PROP_INT32("uart-dev", AspeedCoprocessorState, uart_dev, 0),
 };
 
 static void aspeed_coprocessor_class_init(ObjectClass *oc, const void *data)
index c1f2c549c323ffb9ad69136128f703aceaf3187d..4a50f688ecdcd3dc6797c60afd6a7f97c23a30cf 100644 (file)
@@ -19,13 +19,15 @@ struct AspeedCoprocessorState {
     MemoryRegion sdram;
     MemoryRegion *sram;
     MemoryRegion sram_alias;
+    MemoryRegion uart_alias;
     MemoryRegion scu_alias;
     Clock *sysclk;
 
     AspeedSCUState *scu;
     AspeedSCUState scuio;
     AspeedTimerCtrlState timerctrl;
-    SerialMM uart[ASPEED_UARTS_NUM];
+    SerialMM *uart;
+    int uart_dev;
 };
 
 #define TYPE_ASPEED_COPROCESSOR "aspeed-coprocessor"
@@ -39,8 +41,6 @@ struct AspeedCoprocessorClass {
     const char * const *valid_cpu_types;
     const hwaddr *memmap;
     const int *irqmap;
-    int uarts_base;
-    int uarts_num;
 };
 
 struct Aspeed27x0CoprocessorState {