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>
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;
}
static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
{
- AspeedCoprocessorState *soc;
- AspeedCoprocessorClass *sc;
Ast2700FCState *s = AST2700A1FC(machine);
AspeedSoCState *psp = ASPEED_SOC(&s->ca35);
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",
static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
{
- AspeedCoprocessorState *soc;
- AspeedCoprocessorClass *sc;
Ast2700FCState *s = AST2700A1FC(machine);
AspeedSoCState *psp = ASPEED_SOC(&s->ca35);
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",
{
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],
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)) {
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",
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;
}
{
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],
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)) {
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",
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;
}
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)
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"
const char * const *valid_cpu_types;
const hwaddr *memmap;
const int *irqmap;
- int uarts_base;
- int uarts_num;
};
struct Aspeed27x0CoprocessorState {