* [PATCH v3 1/9] hw/misc/aspeed_scu: Introduce Aspeed2700SCUState
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 2/9] hw/arm/aspeed: Use Aspeed2700SCUState for AST2700 users Jamin Lin
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
Introduce Aspeed2700SCUState as an AST2700-specific subclass of
AspeedSCUState.
Currently, AST1700 and AST2700 reuse the generic AspeedSCUState.
However, AST2700 requires SCU functionality that is specific to the
platform, particularly for interactions with its coprocessors.
Introduce a dedicated Aspeed2700SCUState to provide an extension point
for AST2700-specific functionality while keeping the generic
AspeedSCUState unchanged.
Subsequent patches will migrate AST2700 users to the new subclass and
move AST2700-specific code into it.
No functional change.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/misc/aspeed_scu.h | 5 +++++
hw/misc/aspeed_scu.c | 8 +++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index c30940ab76..904549465f 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -20,6 +20,7 @@ OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEED_SCU)
#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
#define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600"
#define TYPE_ASPEED_2700_SCU TYPE_ASPEED_SCU "-ast2700"
+OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2700SCUState, ASPEED_2700_SCU)
#define TYPE_ASPEED_2700_SCUIO TYPE_ASPEED_SCU "io" "-ast2700"
#define TYPE_ASPEED_1030_SCU TYPE_ASPEED_SCU "-ast1030"
@@ -41,6 +42,10 @@ struct AspeedSCUState {
uint32_t hw_prot_key;
};
+struct Aspeed2700SCUState {
+ AspeedSCUState parent_obj;
+};
+
#define AST2400_A1_SILICON_REV 0x02010303U
#define AST2500_A1_SILICON_REV 0x04010303U
#define AST2600_A3_SILICON_REV 0x05030303U
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 5dbf81c0ce..efe1d6315b 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -930,6 +930,11 @@ static void aspeed_ast2700_scu_reset_hold(Object *obj, ResetType type)
s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
}
+static void aspeed_2700_scu_realize(DeviceState *dev, Error **errp)
+{
+ aspeed_scu_realize(dev, errp);
+}
+
static void aspeed_2700_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -937,6 +942,7 @@ static void aspeed_2700_scu_class_init(ObjectClass *klass, const void *data)
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
dc->desc = "ASPEED 2700 System Control Unit";
+ dc->realize = aspeed_2700_scu_realize;
rc->phases.hold = aspeed_ast2700_scu_reset_hold;
asc->resets = ast2700_a0_resets;
asc->calc_hpll = aspeed_2600_scu_calc_hpll;
@@ -1161,7 +1167,7 @@ static const TypeInfo aspeed_scu_types[] = {
{
.name = TYPE_ASPEED_2700_SCU,
.parent = TYPE_ASPEED_SCU,
- .instance_size = sizeof(AspeedSCUState),
+ .instance_size = sizeof(Aspeed2700SCUState),
.class_init = aspeed_2700_scu_class_init,
},
{
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 2/9] hw/arm/aspeed: Use Aspeed2700SCUState for AST2700 users
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
2026-07-17 8:18 ` [PATCH v3 1/9] hw/misc/aspeed_scu: Introduce Aspeed2700SCUState Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 3/9] hw/arm/aspeed_ast27x0: Move SCU link into AST27x0 coprocessors Jamin Lin
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
Now that Aspeed2700SCUState has been introduced, update the AST1700 and
AST27x0 SoCs to instantiate the AST2700-specific SCU subclass instead of
the generic AspeedSCUState.
Also update the AST27x0 FC board to link the SSP/TSP coprocessors to the
AST2700 SCU instance.
This prepares the AST2700 platform for subsequent patches that move
AST2700-specific SCU functionality into the subclass.
No functional change.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/arm/aspeed_ast1700.h | 2 +-
include/hw/arm/aspeed_soc.h | 1 +
hw/arm/aspeed_ast27x0-fc.c | 4 ++--
hw/arm/aspeed_ast27x0.c | 16 ++++++++--------
4 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h
index f7bd4e8650..39c5977cf1 100644
--- a/include/hw/arm/aspeed_ast1700.h
+++ b/include/hw/arm/aspeed_ast1700.h
@@ -41,7 +41,7 @@ struct AspeedAST1700SoCState {
MemoryRegion sram;
AspeedSMCState spi;
AspeedADCState adc;
- AspeedSCUState scu;
+ Aspeed2700SCUState scu;
AspeedGPIOState gpio;
AspeedSGPIOState sgpiom[AST1700_SGPIO_NUM];
AspeedI2CState i2c;
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 41dc04e293..cd68c7f1ca 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -151,6 +151,7 @@ struct Aspeed27x0SoCState {
AspeedINTCState intcioexp[ASPEED_IOEXP_NUM];
GICv3State gic;
MemoryRegion dram_empty;
+ Aspeed2700SCUState scu;
};
#define TYPE_ASPEED27X0_SOC "aspeed27x0-soc"
diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index 7d9fade68d..8d49bb95d6 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -158,7 +158,7 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
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);
+ OBJECT(&s->ca35.scu), &error_abort);
if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) {
return false;
}
@@ -190,7 +190,7 @@ static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
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);
+ OBJECT(&s->ca35.scu), &error_abort);
if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) {
return false;
}
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 7c062580f2..6365dbd638 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -435,12 +435,12 @@ static void aspeed_soc_ast2700_init(Object *obj)
object_initialize_child(obj, "gic", &a->gic, gicv3_class_name());
- object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCU);
- qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
+ object_initialize_child(obj, "scu", &a->scu, TYPE_ASPEED_2700_SCU);
+ qdev_prop_set_uint32(DEVICE(&a->scu), "silicon-rev",
sc->silicon_rev);
- object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
+ object_property_add_alias(obj, "hw-strap1", OBJECT(&a->scu),
"hw-strap1");
- object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu),
+ object_property_add_alias(obj, "hw-prot-key", OBJECT(&a->scu),
"hw-prot-key");
object_initialize_child(obj, "scuio", &s->scuio, TYPE_ASPEED_2700_SCUIO);
@@ -808,10 +808,10 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sc->memmap[ASPEED_DEV_VBOOTROM], &s->vbootrom);
/* SCU */
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
+ if (!sysbus_realize(SYS_BUS_DEVICE(&a->scu), errp)) {
return;
}
- aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->scu), 0,
sc->memmap[ASPEED_DEV_SCU]);
/* SCU1 */
@@ -934,7 +934,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
hwaddr wdt_offset = sc->memmap[ASPEED_DEV_WDT] + i * awc->iosize;
- object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu),
+ object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&a->scu),
&error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
return;
@@ -1037,7 +1037,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_EMMC));
/* Timer */
- object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),
+ object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&a->scu),
&error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) {
return;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 3/9] hw/arm/aspeed_ast27x0: Move SCU link into AST27x0 coprocessors
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
2026-07-17 8:18 ` [PATCH v3 1/9] hw/misc/aspeed_scu: Introduce Aspeed2700SCUState Jamin Lin
2026-07-17 8:18 ` [PATCH v3 2/9] hw/arm/aspeed: Use Aspeed2700SCUState for AST2700 users Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 4/9] hw/misc/aspeed_scu: Add separate reset handler for AST2700 SCUIO Jamin Lin
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
The SCU link is only needed by the AST27x0 SSP/TSP coprocessors for their
AST2700-specific SCU alias window.
Move the link property from the common AspeedCoprocessorState into
Aspeed27x0CoprocessorState, so the generic coprocessor model no longer
contains an AST2700-specific dependency.
Also validate that the SCU link has been provided during device realize
before accessing it.
No functional change.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/arm/aspeed_coprocessor.h | 5 +++--
hw/arm/aspeed_ast27x0-ssp.c | 20 ++++++++++++++++----
hw/arm/aspeed_ast27x0-tsp.c | 20 ++++++++++++++++----
hw/arm/aspeed_coprocessor_common.c | 2 --
4 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h
index ac58a5f424..adfc3c4512 100644
--- a/include/hw/arm/aspeed_coprocessor.h
+++ b/include/hw/arm/aspeed_coprocessor.h
@@ -20,10 +20,8 @@ struct AspeedCoprocessorState {
MemoryRegion *sram;
MemoryRegion sram_alias;
MemoryRegion uart_alias;
- MemoryRegion scu_alias;
Clock *sysclk;
- AspeedSCUState *scu;
AspeedSCUState scuio;
AspeedTimerCtrlState timerctrl;
SerialMM *uart;
@@ -52,6 +50,9 @@ struct Aspeed27x0CoprocessorState {
UnimplementedDeviceState otp;
ARMv7MState armv7m;
+
+ MemoryRegion scu_alias;
+ Aspeed2700SCUState *scu;
};
#define TYPE_ASPEED27X0SSP_COPROCESSOR "aspeed27x0ssp-coprocessor"
diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c
index 68a8ab26f7..28bb59c8c5 100644
--- a/hw/arm/aspeed_ast27x0-ssp.c
+++ b/hw/arm/aspeed_ast27x0-ssp.c
@@ -167,6 +167,12 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
return;
}
+ if (!a->scu) {
+ error_setg(errp, TYPE_ASPEED27X0SSP_COPROCESSOR
+ ": 'scu' link is not set");
+ return;
+ }
+
/* AST27X0 SSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
@@ -195,11 +201,11 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
&s->sram_alias);
/* SCU */
- memory_region_init_alias(&s->scu_alias, OBJECT(s), "scu.alias",
- &s->scu->iomem, 0,
- memory_region_size(&s->scu->iomem));
+ memory_region_init_alias(&a->scu_alias, OBJECT(a), "scu.alias",
+ &a->scu->parent_obj.iomem, 0,
+ memory_region_size(&a->scu->parent_obj.iomem));
memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCU],
- &s->scu_alias);
+ &a->scu_alias);
/* INTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
@@ -275,6 +281,11 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
sc->memmap[ASPEED_DEV_OTP], 0x800);
}
+static const Property aspeed_27x0_coprocessor_properties[] = {
+ DEFINE_PROP_LINK("scu", Aspeed27x0CoprocessorState, scu,
+ TYPE_ASPEED_2700_SCU, Aspeed2700SCUState *),
+};
+
static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
const void *data)
{
@@ -288,6 +299,7 @@ static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
/* Reason: The Aspeed Coprocessor can only be instantiated from a board */
dc->user_creatable = false;
dc->realize = aspeed_soc_ast27x0ssp_realize;
+ device_class_set_props(dc, aspeed_27x0_coprocessor_properties);
sc->valid_cpu_types = valid_cpu_types;
sc->irqmap = aspeed_soc_ast27x0ssp_irqmap;
diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c
index b8a4f7c91d..f5c4a02161 100644
--- a/hw/arm/aspeed_ast27x0-tsp.c
+++ b/hw/arm/aspeed_ast27x0-tsp.c
@@ -167,6 +167,12 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
return;
}
+ if (!a->scu) {
+ error_setg(errp, TYPE_ASPEED27X0TSP_COPROCESSOR
+ ": 'scu' link is not set");
+ return;
+ }
+
/* AST27X0 TSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
@@ -195,11 +201,11 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
&s->sram_alias);
/* SCU */
- memory_region_init_alias(&s->scu_alias, OBJECT(s), "scu.alias",
- &s->scu->iomem, 0,
- memory_region_size(&s->scu->iomem));
+ memory_region_init_alias(&a->scu_alias, OBJECT(a), "scu.alias",
+ &a->scu->parent_obj.iomem, 0,
+ memory_region_size(&a->scu->parent_obj.iomem));
memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCU],
- &s->scu_alias);
+ &a->scu_alias);
/* INTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
@@ -275,6 +281,11 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
sc->memmap[ASPEED_DEV_OTP], 0x800);
}
+static const Property aspeed_27x0_coprocessor_properties[] = {
+ DEFINE_PROP_LINK("scu", Aspeed27x0CoprocessorState, scu,
+ TYPE_ASPEED_2700_SCU, Aspeed2700SCUState *),
+};
+
static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
const void *data)
{
@@ -288,6 +299,7 @@ static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
/* Reason: The Aspeed Coprocessor can only be instantiated from a board */
dc->user_creatable = false;
dc->realize = aspeed_soc_ast27x0tsp_realize;
+ device_class_set_props(dc, aspeed_27x0_coprocessor_properties);
sc->valid_cpu_types = valid_cpu_types;
sc->irqmap = aspeed_soc_ast27x0tsp_irqmap;
diff --git a/hw/arm/aspeed_coprocessor_common.c b/hw/arm/aspeed_coprocessor_common.c
index a0a4c73d08..43026d2a55 100644
--- a/hw/arm/aspeed_coprocessor_common.c
+++ b/hw/arm/aspeed_coprocessor_common.c
@@ -27,8 +27,6 @@ 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 *),
DEFINE_PROP_LINK("uart", AspeedCoprocessorState, uart, TYPE_SERIAL_MM,
SerialMM *),
DEFINE_PROP_INT32("uart-dev", AspeedCoprocessorState, uart_dev, 0),
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 4/9] hw/misc/aspeed_scu: Add separate reset handler for AST2700 SCUIO
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
` (2 preceding siblings ...)
2026-07-17 8:18 ` [PATCH v3 3/9] hw/arm/aspeed_ast27x0: Move SCU link into AST27x0 coprocessors Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 5/9] hw/arm/aspeed_ast27x0: Pass realized PSP SoC to SSP/TSP initialization Jamin Lin
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
Introduce a dedicated reset handler for SCUIO.
Previously, SCU and SCUIO shared the same reset handler. This no longer
fits the AST2700 design, where SCU uses the Aspeed2700SCUState subclass
and will handle coprocessor-related control in future changes.
Since these controls are defined in SCU (not SCUIO), SCU and SCUIO
should not share the same reset logic.
This change gives SCUIO its own reset handler and prepares for upcoming
SCU-specific functionality.
No functional change.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/misc/aspeed_scu.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index efe1d6315b..ca93c3699d 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -1069,6 +1069,16 @@ static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
[AST2700_SCUIO_FREQ_CNT_CTL] = 0x00000080,
};
+static void aspeed_ast2700_scuio_reset_hold(Object *obj, ResetType type)
+{
+ AspeedSCUState *s = ASPEED_SCU(obj);
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(obj);
+
+ memcpy(s->regs, asc->resets, asc->nr_regs * 4);
+ s->regs[AST2700_SILICON_REV] = s->silicon_rev;
+ s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
+}
+
static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1076,7 +1086,7 @@ static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data)
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
dc->desc = "ASPEED 2700 System Control Unit I/O";
- rc->phases.hold = aspeed_ast2700_scu_reset_hold;
+ rc->phases.hold = aspeed_ast2700_scuio_reset_hold;
asc->resets = ast2700_a0_resets_io;
asc->calc_hpll = aspeed_2600_scu_calc_hpll;
asc->get_apb = aspeed_2700_scuio_get_apb_freq;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 5/9] hw/arm/aspeed_ast27x0: Pass realized PSP SoC to SSP/TSP initialization
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
` (3 preceding siblings ...)
2026-07-17 8:18 ` [PATCH v3 4/9] hw/misc/aspeed_scu: Add separate reset handler for AST2700 SCUIO Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 6/9] hw/arm/ast27x0: Share single SCUIO instance across PSP, SSP, and TSP Jamin Lin
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
Pass the realized PSP SoC to the SSP/TSP initialization helpers instead
of retrieving it from the MachineState.
This makes the dependency explicit, since the SSP and TSP coprocessors
use resources owned by the PSP SoC, including the UARTs, SRAM, SCU and
SCUIO. The PSP SoC must therefore be realized before the coprocessors
are initialized.
No functional change.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/arm/aspeed_ast27x0-fc.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index 8d49bb95d6..58d0b4d7cd 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -134,11 +134,9 @@ static bool ast2700fc_ca35_init(MachineState *machine, Error **errp)
return true;
}
-static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
+static bool ast2700fc_ssp_init(Ast2700FCState *s, AspeedSoCState *psp,
+ Error **errp)
{
- Ast2700FCState *s = AST2700FC(machine);
- AspeedSoCState *psp = ASPEED_SOC(&s->ca35);
-
s->ssp_sysclk = clock_new(OBJECT(s), "SSP_SYSCLK");
clock_set_hz(s->ssp_sysclk, 200000000ULL);
@@ -166,11 +164,9 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
return true;
}
-static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
+static bool ast2700fc_tsp_init(Ast2700FCState *s, AspeedSoCState *psp,
+ Error **errp)
{
- Ast2700FCState *s = AST2700FC(machine);
- AspeedSoCState *psp = ASPEED_SOC(&s->ca35);
-
s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK");
clock_set_hz(s->tsp_sysclk, 200000000ULL);
@@ -200,9 +196,19 @@ static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
static void ast2700fc_init(MachineState *machine)
{
+ Ast2700FCState *s = AST2700FC(machine);
+ AspeedSoCState *psp;
+
ast2700fc_ca35_init(machine, &error_abort);
- ast2700fc_ssp_init(machine, &error_abort);
- ast2700fc_tsp_init(machine, &error_abort);
+
+ /*
+ * SSP and TSP use resources owned by the PSP SoC, such as UART,
+ * SRAM, SCU and SCUIO. Therefore the PSP SoC must be realized
+ * before the coprocessors are initialized.
+ */
+ psp = ASPEED_SOC(&s->ca35);
+ ast2700fc_ssp_init(s, psp, &error_abort);
+ ast2700fc_tsp_init(s, psp, &error_abort);
}
static void ast2700fc_class_init(ObjectClass *oc, const void *data)
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 6/9] hw/arm/ast27x0: Share single SCUIO instance across PSP, SSP, and TSP
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
` (4 preceding siblings ...)
2026-07-17 8:18 ` [PATCH v3 5/9] hw/arm/aspeed_ast27x0: Pass realized PSP SoC to SSP/TSP initialization Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 7/9] hw/arm/ast27x0: Share FMC controller with SSP " Jamin Lin
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
AST2700 has a single SCUIO hardware block, memory-mapped at
0x14C02000–0x14C03FFF from the perspective of the main CA35 processor (PSP).
The SSP and TSP coprocessors access this same SCUIO block at different
addresses: 0x74C02000–0x74C03FFF.
Previously, each subsystem (PSP, SSP, and TSP) instantiated its own SCUIO
device, resulting in three independent SCUIO instances in the QEMU model.
In real hardware, however, only a single SCUIO exists and is shared among
all processors.
This commit reworks the SCUIO model to correctly reflect the hardware
behavior by allowing SSP and TSP to reference the PSP’s SCUIO instance.
The following changes are introduced:
- Add a scuio property to Aspeed27x0CoprocessorState for linking the
coprocessor to the PSP’s SCUIO instance.
- Replace per-coprocessor SCUIO instantiation with a shared SCUIO link.
- Add "MemoryRegion scuio_alias" to model address remapping for SSP and TSP.
- Create SCUIO alias regions in both SSP and TSP coprocessors and map
them at 0x74C02000 to mirror the PSP’s SCUIO registers.
- Ensure the SCUIO device in PSP is realized before SSP/TSP alias setup.
With this change, PSP, SSP, and TSP now share a consistent SCUIO state,
matching the single-SCUIO hardware design of AST2700.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/arm/aspeed_coprocessor.h | 4 ++--
hw/arm/aspeed_ast27x0-fc.c | 4 ++++
hw/arm/aspeed_ast27x0-ssp.c | 20 +++++++++++++++-----
hw/arm/aspeed_ast27x0-tsp.c | 20 +++++++++++++++-----
4 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h
index adfc3c4512..b77ea06e7f 100644
--- a/include/hw/arm/aspeed_coprocessor.h
+++ b/include/hw/arm/aspeed_coprocessor.h
@@ -22,7 +22,6 @@ struct AspeedCoprocessorState {
MemoryRegion uart_alias;
Clock *sysclk;
- AspeedSCUState scuio;
AspeedTimerCtrlState timerctrl;
SerialMM *uart;
int uart_dev;
@@ -45,14 +44,15 @@ struct Aspeed27x0CoprocessorState {
AspeedCoprocessorState parent;
AspeedINTCState intc[2];
UnimplementedDeviceState ipc[2];
- UnimplementedDeviceState scuio;
UnimplementedDeviceState pric[2];
UnimplementedDeviceState otp;
ARMv7MState armv7m;
MemoryRegion scu_alias;
+ MemoryRegion scuio_alias;
Aspeed2700SCUState *scu;
+ AspeedSCUState *scuio;
};
#define TYPE_ASPEED27X0SSP_COPROCESSOR "aspeed27x0ssp-coprocessor"
diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index 58d0b4d7cd..d14a42ebca 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -157,6 +157,8 @@ static bool ast2700fc_ssp_init(Ast2700FCState *s, AspeedSoCState *psp,
OBJECT(&psp->sram), &error_abort);
object_property_set_link(OBJECT(&s->ssp), "scu",
OBJECT(&s->ca35.scu), &error_abort);
+ object_property_set_link(OBJECT(&s->ssp), "scuio",
+ OBJECT(&psp->scuio), &error_abort);
if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) {
return false;
}
@@ -187,6 +189,8 @@ static bool ast2700fc_tsp_init(Ast2700FCState *s, AspeedSoCState *psp,
OBJECT(&psp->sram), &error_abort);
object_property_set_link(OBJECT(&s->tsp), "scu",
OBJECT(&s->ca35.scu), &error_abort);
+ object_property_set_link(OBJECT(&s->tsp), "scuio",
+ OBJECT(&psp->scuio), &error_abort);
if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) {
return false;
}
diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c
index 28bb59c8c5..fa492f1797 100644
--- a/hw/arm/aspeed_ast27x0-ssp.c
+++ b/hw/arm/aspeed_ast27x0-ssp.c
@@ -142,8 +142,6 @@ static void aspeed_soc_ast27x0ssp_init(Object *obj)
TYPE_UNIMPLEMENTED_DEVICE);
object_initialize_child(obj, "ipc1", &a->ipc[1],
TYPE_UNIMPLEMENTED_DEVICE);
- object_initialize_child(obj, "scuio", &a->scuio,
- TYPE_UNIMPLEMENTED_DEVICE);
object_initialize_child(obj, "pric0", &a->pric[0],
TYPE_UNIMPLEMENTED_DEVICE);
object_initialize_child(obj, "pric1", &a->pric[1],
@@ -173,6 +171,12 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
return;
}
+ if (!a->scuio) {
+ error_setg(errp, TYPE_ASPEED27X0SSP_COPROCESSOR
+ ": 'scuio' link is not set");
+ return;
+ }
+
/* AST27X0 SSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
@@ -207,6 +211,13 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCU],
&a->scu_alias);
+ /* SCUIO */
+ memory_region_init_alias(&a->scuio_alias, OBJECT(a), "scuio.alias",
+ &a->scuio->iomem, 0,
+ memory_region_size(&a->scuio->iomem));
+ memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCUIO],
+ &a->scuio_alias);
+
/* INTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
return;
@@ -267,9 +278,6 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->ipc[1]),
"aspeed.ipc1",
sc->memmap[ASPEED_DEV_IPC1], 0x1000);
- aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->scuio),
- "aspeed.scuio",
- sc->memmap[ASPEED_DEV_SCUIO], 0x1000);
aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[0]),
"aspeed.pric0",
sc->memmap[ASPEED_DEV_PRIC0], 0x1000);
@@ -284,6 +292,8 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
static const Property aspeed_27x0_coprocessor_properties[] = {
DEFINE_PROP_LINK("scu", Aspeed27x0CoprocessorState, scu,
TYPE_ASPEED_2700_SCU, Aspeed2700SCUState *),
+ DEFINE_PROP_LINK("scuio", Aspeed27x0CoprocessorState, scuio,
+ TYPE_ASPEED_SCU, AspeedSCUState *),
};
static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c
index f5c4a02161..3a98bd232c 100644
--- a/hw/arm/aspeed_ast27x0-tsp.c
+++ b/hw/arm/aspeed_ast27x0-tsp.c
@@ -142,8 +142,6 @@ static void aspeed_soc_ast27x0tsp_init(Object *obj)
TYPE_UNIMPLEMENTED_DEVICE);
object_initialize_child(obj, "ipc1", &a->ipc[1],
TYPE_UNIMPLEMENTED_DEVICE);
- object_initialize_child(obj, "scuio", &a->scuio,
- TYPE_UNIMPLEMENTED_DEVICE);
object_initialize_child(obj, "pric0", &a->pric[0],
TYPE_UNIMPLEMENTED_DEVICE);
object_initialize_child(obj, "pric1", &a->pric[1],
@@ -173,6 +171,12 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
return;
}
+ if (!a->scuio) {
+ error_setg(errp, TYPE_ASPEED27X0TSP_COPROCESSOR
+ ": 'scuio' link is not set");
+ return;
+ }
+
/* AST27X0 TSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
@@ -207,6 +211,13 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCU],
&a->scu_alias);
+ /* SCUIO */
+ memory_region_init_alias(&a->scuio_alias, OBJECT(a), "scuio.alias",
+ &a->scuio->iomem, 0,
+ memory_region_size(&a->scuio->iomem));
+ memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SCUIO],
+ &a->scuio_alias);
+
/* INTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
return;
@@ -267,9 +278,6 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->ipc[1]),
"aspeed.ipc1",
sc->memmap[ASPEED_DEV_IPC1], 0x1000);
- aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->scuio),
- "aspeed.scuio",
- sc->memmap[ASPEED_DEV_SCUIO], 0x1000);
aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[0]),
"aspeed.pric0",
sc->memmap[ASPEED_DEV_PRIC0], 0x1000);
@@ -284,6 +292,8 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
static const Property aspeed_27x0_coprocessor_properties[] = {
DEFINE_PROP_LINK("scu", Aspeed27x0CoprocessorState, scu,
TYPE_ASPEED_2700_SCU, Aspeed2700SCUState *),
+ DEFINE_PROP_LINK("scuio", Aspeed27x0CoprocessorState, scuio,
+ TYPE_ASPEED_SCU, AspeedSCUState *),
};
static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 7/9] hw/arm/ast27x0: Share FMC controller with SSP and TSP
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
` (5 preceding siblings ...)
2026-07-17 8:18 ` [PATCH v3 6/9] hw/arm/ast27x0: Share single SCUIO instance across PSP, SSP, and TSP Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 8/9] hw/ssi/aspeed_smc: Add Data FIFO-based flash access support for AST2700 Jamin Lin
2026-07-17 8:18 ` [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode test Jamin Lin
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Philippe Mathieu-Daudé,
Cédric Le Goater
AST2700 provides a single FMC controller shared by the main CA35 processor
(PSP) and the SSP/TSP coprocessors.
From the PSP perspective, the FMC controller is memory-mapped at
0x14000000–0x140000FF. The SSP and TSP access the same controller through
a different address window at 0x74000000–0x740000FF.
This change allows the SSP and TSP SoC models to reference the existing
PSP FMC instance instead of creating independent controllers. An MMIO
alias is added in the SSP and TSP address spaces to map their FMC access
window to the shared FMC device.
This ensures consistent FMC state across PSP, SSP, and TSP and matches
the AST2700 hardware design.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/arm/aspeed_coprocessor.h | 7 +++++++
hw/arm/aspeed_ast27x0-fc.c | 4 ++++
hw/arm/aspeed_ast27x0-ssp.c | 16 ++++++++++++++++
hw/arm/aspeed_ast27x0-tsp.c | 16 ++++++++++++++++
4 files changed, 43 insertions(+)
diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h
index b77ea06e7f..acb8b06457 100644
--- a/include/hw/arm/aspeed_coprocessor.h
+++ b/include/hw/arm/aspeed_coprocessor.h
@@ -49,10 +49,17 @@ struct Aspeed27x0CoprocessorState {
ARMv7MState armv7m;
+ /*
+ * SCU, SCUIO and FMC are not owned by this coprocessor: they are
+ * shared with the main PSP SoC, and only aliased into this
+ * coprocessor's own address space here.
+ */
MemoryRegion scu_alias;
MemoryRegion scuio_alias;
+ MemoryRegion fmc_alias;
Aspeed2700SCUState *scu;
AspeedSCUState *scuio;
+ AspeedSMCState *fmc;
};
#define TYPE_ASPEED27X0SSP_COPROCESSOR "aspeed27x0ssp-coprocessor"
diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index d14a42ebca..058cea42ed 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -159,6 +159,8 @@ static bool ast2700fc_ssp_init(Ast2700FCState *s, AspeedSoCState *psp,
OBJECT(&s->ca35.scu), &error_abort);
object_property_set_link(OBJECT(&s->ssp), "scuio",
OBJECT(&psp->scuio), &error_abort);
+ object_property_set_link(OBJECT(&s->ssp), "fmc",
+ OBJECT(&psp->fmc), &error_abort);
if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) {
return false;
}
@@ -191,6 +193,8 @@ static bool ast2700fc_tsp_init(Ast2700FCState *s, AspeedSoCState *psp,
OBJECT(&s->ca35.scu), &error_abort);
object_property_set_link(OBJECT(&s->tsp), "scuio",
OBJECT(&psp->scuio), &error_abort);
+ object_property_set_link(OBJECT(&s->tsp), "fmc",
+ OBJECT(&psp->fmc), &error_abort);
if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) {
return false;
}
diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c
index fa492f1797..e03653086c 100644
--- a/hw/arm/aspeed_ast27x0-ssp.c
+++ b/hw/arm/aspeed_ast27x0-ssp.c
@@ -27,6 +27,7 @@ static const hwaddr aspeed_soc_ast27x0ssp_memmap[] = {
[ASPEED_DEV_TIMER1] = 0x72C10000,
[ASPEED_DEV_UART4] = 0x72C1A000,
[ASPEED_DEV_IPC0] = 0x72C1C000,
+ [ASPEED_DEV_FMC] = 0x74000000,
[ASPEED_DEV_PRIC1] = 0x74100000,
[ASPEED_DEV_SCUIO] = 0x74C02000,
[ASPEED_DEV_OTP] = 0x74C07000,
@@ -177,6 +178,12 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
return;
}
+ if (!a->fmc) {
+ error_setg(errp, TYPE_ASPEED27X0SSP_COPROCESSOR
+ ": 'fmc' link is not set");
+ return;
+ }
+
/* AST27X0 SSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
@@ -269,6 +276,13 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(s->uart), 0,
aspeed_soc_ast27x0ssp_get_irq(s, s->uart_dev));
+ /* FMC */
+ memory_region_init_alias(&a->fmc_alias, OBJECT(a), "fmc.alias",
+ &a->fmc->mmio, 0,
+ memory_region_size(&a->fmc->mmio));
+ memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_FMC],
+ &a->fmc_alias);
+
aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->timerctrl),
"aspeed.timerctrl",
sc->memmap[ASPEED_DEV_TIMER1], 0x200);
@@ -294,6 +308,8 @@ static const Property aspeed_27x0_coprocessor_properties[] = {
TYPE_ASPEED_2700_SCU, Aspeed2700SCUState *),
DEFINE_PROP_LINK("scuio", Aspeed27x0CoprocessorState, scuio,
TYPE_ASPEED_SCU, AspeedSCUState *),
+ DEFINE_PROP_LINK("fmc", Aspeed27x0CoprocessorState, fmc, TYPE_ASPEED_SMC,
+ AspeedSMCState *),
};
static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c
index 3a98bd232c..39ba062a20 100644
--- a/hw/arm/aspeed_ast27x0-tsp.c
+++ b/hw/arm/aspeed_ast27x0-tsp.c
@@ -27,6 +27,7 @@ static const hwaddr aspeed_soc_ast27x0tsp_memmap[] = {
[ASPEED_DEV_TIMER1] = 0x72C10000,
[ASPEED_DEV_UART4] = 0x72C1A000,
[ASPEED_DEV_IPC0] = 0x72C1C000,
+ [ASPEED_DEV_FMC] = 0x74000000,
[ASPEED_DEV_PRIC1] = 0x74100000,
[ASPEED_DEV_SCUIO] = 0x74C02000,
[ASPEED_DEV_OTP] = 0x74C07000,
@@ -177,6 +178,12 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
return;
}
+ if (!a->fmc) {
+ error_setg(errp, TYPE_ASPEED27X0TSP_COPROCESSOR
+ ": 'fmc' link is not set");
+ return;
+ }
+
/* AST27X0 TSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
@@ -269,6 +276,13 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(s->uart), 0,
aspeed_soc_ast27x0tsp_get_irq(s, s->uart_dev));
+ /* FMC */
+ memory_region_init_alias(&a->fmc_alias, OBJECT(a), "fmc.alias",
+ &a->fmc->mmio, 0,
+ memory_region_size(&a->fmc->mmio));
+ memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_FMC],
+ &a->fmc_alias);
+
aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->timerctrl),
"aspeed.timerctrl",
sc->memmap[ASPEED_DEV_TIMER1], 0x200);
@@ -294,6 +308,8 @@ static const Property aspeed_27x0_coprocessor_properties[] = {
TYPE_ASPEED_2700_SCU, Aspeed2700SCUState *),
DEFINE_PROP_LINK("scuio", Aspeed27x0CoprocessorState, scuio,
TYPE_ASPEED_SCU, AspeedSCUState *),
+ DEFINE_PROP_LINK("fmc", Aspeed27x0CoprocessorState, fmc, TYPE_ASPEED_SMC,
+ AspeedSMCState *),
};
static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 8/9] hw/ssi/aspeed_smc: Add Data FIFO-based flash access support for AST2700
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
` (6 preceding siblings ...)
2026-07-17 8:18 ` [PATCH v3 7/9] hw/arm/ast27x0: Share FMC controller with SSP " Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:18 ` [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode test Jamin Lin
8 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee, Cédric Le Goater,
Philippe Mathieu-Daudé
AST2700 supports a Data FIFO mode where flash accesses can be performed
directly through Data FIFO MMIO offsets. The Data FIFO start offset
increments by one for every 16MB of flash address space, allowing the
chip select (CS) to be decoded from the Data FIFO offset.
This change adds Data FIFO support to the Aspeed SMC model and introduces
a class callback to translate Data FIFO offsets into CS indices. For
AST2700, the Data FIFO offset is matched against the segment start address
of each CS to determine the target flash device.
The SMC register region size (nregs) is also extended dynamically
based on the number of supported chip selects to cover all possible
Data FIFO regions.
This breaks migration compatibility with older QEMU builds for the
affected models, even though Aspeed machines are not officially
covered by migration compatibility guarantees.
Bump version_id to 4 and minimum_version_id to 2 to reflect the
incompatible format.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/ssi/aspeed_smc.h | 3 +-
hw/ssi/aspeed_smc.c | 117 +++++++++++++++++++++++++++++++++---
2 files changed, 109 insertions(+), 11 deletions(-)
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index a273365689..5f391fc24e 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -47,7 +47,7 @@ struct AspeedSMCFlash {
#define TYPE_ASPEED_SMC "aspeed.smc"
OBJECT_DECLARE_TYPE(AspeedSMCState, AspeedSMCClass, ASPEED_SMC)
-#define ASPEED_SMC_R_MAX (0x100 / 4)
+#define ASPEED_SMC_R_MAX (0x300 / 4)
#define ASPEED_SMC_CS_MAX 5
struct AspeedSMCState {
@@ -114,6 +114,7 @@ struct AspeedSMCClass {
AspeedSegments *seg);
void (*dma_ctrl)(AspeedSMCState *s, uint32_t value);
int (*addr_width)(const AspeedSMCState *s);
+ int (*data_fifo_offset_to_cs)(const AspeedSMCState *s, uint32_t offset);
const MemoryRegionOps *reg_ops;
};
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index c8cc6cfa56..bf596f7b2d 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -163,6 +163,9 @@
/* Read Timing Compensation Register */
#define R_TIMINGS (0x94 / 4)
+/* Data fifo */
+#define R_DATA_FIFO (0x200 / 4)
+
/* SPI controller registers and bits (AST2400) */
#define R_SPI_CONF (0x00 / 4)
#define SPI_CONF_ENABLE_W0 0
@@ -209,6 +212,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
#define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
+#define ASPEED_SMC_FEATURE_DATA_FIFO 0x10
static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
{
@@ -225,6 +229,11 @@ static inline bool aspeed_smc_has_dma64(const AspeedSMCClass *asc)
return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
}
+static inline bool aspeed_smc_has_data_fifo(const AspeedSMCClass *asc)
+{
+ return !!(asc->features & ASPEED_SMC_FEATURE_DATA_FIFO);
+}
+
#define aspeed_smc_error(fmt, ...) \
qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
@@ -664,6 +673,7 @@ static MemTxResult aspeed_smc_read(void *opaque, hwaddr addr, uint64_t *data,
{
AspeedSMCState *s = ASPEED_SMC(opaque);
AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(opaque);
+ int cs;
addr >>= 2;
@@ -689,6 +699,18 @@ static MemTxResult aspeed_smc_read(void *opaque, hwaddr addr, uint64_t *data,
trace_aspeed_smc_read(addr << 2, size, s->regs[addr]);
*data = s->regs[addr];
+ } else if (aspeed_smc_has_data_fifo(asc) && addr >= R_DATA_FIFO) {
+ cs = asc->data_fifo_offset_to_cs(s, addr << 2);
+ if (cs >= 0) {
+ /*
+ * Data fifo mode only supports SPI user mode.
+ * The flash address is provided by the SPI command/address cycles,
+ * the MMIO addr parameter is ignored.
+ */
+ return aspeed_smc_flash_read(&s->flashes[cs], 0, data, size, attrs);
+ }
+ aspeed_smc_error("Invalid data fifo offset %" HWADDR_PRIx, addr << 2);
+ return MEMTX_ERROR;
} else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr);
@@ -1063,6 +1085,19 @@ static MemTxResult aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
} else if (aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) &&
addr == R_DMA_DRAM_ADDR_HIGH) {
s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
+ } else if (aspeed_smc_has_data_fifo(asc) && addr >= R_DATA_FIFO) {
+ int cs = asc->data_fifo_offset_to_cs(s, addr << 2);
+ if (cs >= 0) {
+ /*
+ * Data fifo mode only supports SPI user mode.
+ * The flash address is provided by the SPI command/address cycles,
+ * the MMIO addr parameter is ignored.
+ */
+ return aspeed_smc_flash_write(&s->flashes[cs], 0, data, size,
+ attrs);
+ }
+ aspeed_smc_error("Invalid data fifo offset %" HWADDR_PRIx, addr << 2);
+ return MEMTX_ERROR;
} else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr);
@@ -1183,8 +1218,8 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
static const VMStateDescription vmstate_aspeed_smc = {
.name = "aspeed.smc",
- .version_id = 3,
- .minimum_version_id = 1,
+ .version_id = 4,
+ .minimum_version_id = 2,
.fields = (const VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX),
VMSTATE_UNUSED_V(2, 2), /* was snoop_index/snoop_dummies */
@@ -1808,6 +1843,39 @@ static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s,
}
}
+/*
+ * Convert a data fifo offset to a chip select (CS).
+ *
+ * Data fifo access starts at 0x200. The data fifo offset index is
+ * calculated by subtracting the data fifo base offset from the MMIO address.
+ *
+ * The data fifo offset index increments by 1 for every 16MB of flash address
+ * space. Each offset step therefore represents a 16MB address decode range.
+ *
+ * The CS is determined by matching the data fifo offset index against the
+ * segment start address of each CS.
+ *
+ * Returns the CS index on success, or -1 if the offset is invalid.
+ */
+static int aspeed_2700_smc_data_fifo_offset_to_cs(const AspeedSMCState *s,
+ uint32_t offset)
+{
+ AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
+ uint32_t start_offset;
+ uint32_t fifo_offset;
+ int i;
+
+ for (i = 0; i < asc->cs_num_max; i++) {
+ start_offset = (s->regs[R_SEG_ADDR0 + i] & 0x0000ffff) << 16;
+ fifo_offset = start_offset / 0x1000000;
+ if (fifo_offset == offset - (R_DATA_FIFO << 2)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = {
[R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 |
CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1),
@@ -1842,6 +1910,27 @@ static const AspeedSegments aspeed_2700_fmc_segments[] = {
{ 0x0, 0 }, /* disabled */
};
+/*
+ * AST2700 supports data fifo mode with a base data fifo start offset of 0x200.
+ *
+ * The data fifo start offset increments by 1 for every 16MB of flash address
+ * space. Each offset step therefore represents a 16MB address decode range.
+ *
+ * Assuming each chip select (CS) can use the maximum flash size of 256MB:
+ * 256MB / 16MB = 0x10 offset steps per CS.
+ *
+ * Data fifo start offset for CSn:
+ * 0x200 + (n * 0x10)
+ *
+ * Examples:
+ * CS0: 0x200
+ * CS1: 0x210
+ * CS2: 0x220
+ * CS3: 0x230
+ *
+ * asc->nregs should be set to: 0x200 + (asc->cs_num_max * 0x10)
+ * to cover all possible data fifo regions.
+ */
static void aspeed_2700_fmc_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1861,14 +1950,16 @@ static void aspeed_2700_fmc_class_init(ObjectClass *klass, const void *data)
asc->flash_window_base = 0x100000000;
asc->flash_window_size = 1 * GiB;
asc->features = ASPEED_SMC_FEATURE_DMA |
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
+ ASPEED_SMC_FEATURE_DATA_FIFO;
asc->dma_flash_mask = 0x2FFFFFFC;
asc->dma_dram_mask = 0xFFFFFFFC;
asc->dma_start_length = 1;
- asc->nregs = ASPEED_SMC_R_MAX;
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
@@ -1896,14 +1987,16 @@ static void aspeed_2700_spi0_class_init(ObjectClass *klass, const void *data)
asc->flash_window_base = 0x180000000;
asc->flash_window_size = 1 * GiB;
asc->features = ASPEED_SMC_FEATURE_DMA |
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
+ ASPEED_SMC_FEATURE_DATA_FIFO;
asc->dma_flash_mask = 0x2FFFFFFC;
asc->dma_dram_mask = 0xFFFFFFFC;
asc->dma_start_length = 1;
- asc->nregs = ASPEED_SMC_R_MAX;
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
@@ -1930,14 +2023,16 @@ static void aspeed_2700_spi1_class_init(ObjectClass *klass, const void *data)
asc->flash_window_base = 0x200000000;
asc->flash_window_size = 1 * GiB;
asc->features = ASPEED_SMC_FEATURE_DMA |
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
+ ASPEED_SMC_FEATURE_DATA_FIFO;
asc->dma_flash_mask = 0x2FFFFFFC;
asc->dma_dram_mask = 0xFFFFFFFC;
asc->dma_start_length = 1;
- asc->nregs = ASPEED_SMC_R_MAX;
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
@@ -1964,14 +2059,16 @@ static void aspeed_2700_spi2_class_init(ObjectClass *klass, const void *data)
asc->flash_window_base = 0x280000000;
asc->flash_window_size = 1 * GiB;
asc->features = ASPEED_SMC_FEATURE_DMA |
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
+ ASPEED_SMC_FEATURE_DATA_FIFO;
asc->dma_flash_mask = 0x0FFFFFFC;
asc->dma_dram_mask = 0xFFFFFFFC;
asc->dma_start_length = 1;
- asc->nregs = ASPEED_SMC_R_MAX;
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
asc->reg_ops = &aspeed_2700_smc_flash_ops;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode test
2026-07-17 8:18 [PATCH v3 0/9] Refactor AST2700 SCU preparation for coprocessors Jamin Lin
` (7 preceding siblings ...)
2026-07-17 8:18 ` [PATCH v3 8/9] hw/ssi/aspeed_smc: Add Data FIFO-based flash access support for AST2700 Jamin Lin
@ 2026-07-17 8:18 ` Jamin Lin
2026-07-17 8:23 ` Cédric Le Goater
8 siblings, 1 reply; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:18 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Jamin Lin, Troy Lee
Add two qtest cases exercising the new AST2700 Data FIFO-based flash
access path (R_DATA_FIFO at spi_base + 0x200).
Write_page_datafifo sends the page-program command and data through
the FIFO port, then verifies the result via the regular read path.
Read_page_datafifo writes a page the regular way, then reads it back
through the FIFO port, so both directions are checked independently.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
tests/qtest/aspeed-smc-utils.h | 4 ++
tests/qtest/aspeed-smc-utils.c | 103 +++++++++++++++++++++++++++++++++
tests/qtest/ast2700-smc-test.c | 4 ++
3 files changed, 111 insertions(+)
diff --git a/tests/qtest/aspeed-smc-utils.h b/tests/qtest/aspeed-smc-utils.h
index 19c557b822..e4f538e579 100644
--- a/tests/qtest/aspeed-smc-utils.h
+++ b/tests/qtest/aspeed-smc-utils.h
@@ -33,6 +33,8 @@
#define CTRL_DUMMY_LOW_SHIFT 6
#define CTRL_DUMMY_HIGH_SHIFT 14
#define SR_WEL BIT(1)
+/* Data fifo */
+#define R_DATA_FIFO 0x200
/*
* Flash commands
@@ -87,5 +89,7 @@ void aspeed_smc_test_read_page_mem_dor(const void *data);
void aspeed_smc_test_write_page_dor(const void *data);
void aspeed_smc_test_read_page_mem_qor(const void *data);
void aspeed_smc_test_write_page_qor(const void *data);
+void aspeed_smc_test_write_page_datafifo(const void *data);
+void aspeed_smc_test_read_page_datafifo(const void *data);
#endif /* TESTS_ASPEED_SMC_UTILS_H */
diff --git a/tests/qtest/aspeed-smc-utils.c b/tests/qtest/aspeed-smc-utils.c
index 6d75a95578..6f1a4b2ec7 100644
--- a/tests/qtest/aspeed-smc-utils.c
+++ b/tests/qtest/aspeed-smc-utils.c
@@ -57,6 +57,28 @@ static inline uint32_t flash_readl(const AspeedSMCTestData *data,
return qtest_readl(data->s, data->flash_base + offset);
}
+/*
+ * Data FIFO port, in spi_base's register bank (not flash_base). Accesses
+ * through the FIFO require the complete user-mode transaction (opcode,
+ * address, and data). Assumes CS0, whose FIFO slot is at R_DATA_FIFO.
+ */
+static inline void datafifo_writeb(const AspeedSMCTestData *data,
+ uint8_t value)
+{
+ qtest_writeb(data->s, data->spi_base + R_DATA_FIFO, value);
+}
+
+static inline void datafifo_writel(const AspeedSMCTestData *data,
+ uint32_t value)
+{
+ spi_writel(data, R_DATA_FIFO, value);
+}
+
+static inline uint32_t datafifo_readl(const AspeedSMCTestData *data)
+{
+ return spi_readl(data, R_DATA_FIFO);
+}
+
static void spi_conf(const AspeedSMCTestData *data, uint32_t value)
{
uint32_t conf = spi_readl(data, R_CONF);
@@ -826,3 +848,84 @@ void aspeed_smc_test_write_page_qor(const void *data)
{
test_write_page(data, read_page_qor);
}
+
+void aspeed_smc_test_write_page_datafifo(const void *data)
+{
+ const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
+ uint32_t my_page_addr = test_data->page_addr;
+ uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE;
+ uint32_t page[FLASH_PAGE_SIZE / 4];
+ int i;
+
+ spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
+
+ /*
+ * Send the complete user-mode transaction (opcode, address, data)
+ * through the Data FIFO port.
+ */
+ spi_ctrl_start_user(test_data);
+ datafifo_writeb(test_data, EN_4BYTE_ADDR);
+ datafifo_writeb(test_data, WREN);
+ datafifo_writeb(test_data, PP);
+ datafifo_writel(test_data, make_be32(my_page_addr));
+
+ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+ datafifo_writel(test_data, make_be32(my_page_addr + i * 4));
+ }
+ spi_ctrl_stop_user(test_data);
+
+ /* Check what was written, using the regular read path */
+ read_page(test_data, my_page_addr, page);
+ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+ g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
+ }
+
+ /* Check some other page. It should be full of 0xff */
+ read_page(test_data, some_page_addr, page);
+ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+ g_assert_cmphex(page[i], ==, 0xffffffff);
+ }
+
+ flash_reset(test_data);
+}
+
+void aspeed_smc_test_read_page_datafifo(const void *data)
+{
+ const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
+ uint32_t my_page_addr = test_data->page_addr;
+ uint32_t page[FLASH_PAGE_SIZE / 4];
+ int i;
+
+ spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
+
+ /* Write the page the regular way */
+ spi_ctrl_start_user(test_data);
+ flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+ flash_writeb(test_data, 0, WREN);
+ flash_writeb(test_data, 0, PP);
+ flash_writel(test_data, 0, make_be32(my_page_addr));
+ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+ flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
+ }
+ spi_ctrl_stop_user(test_data);
+
+ /*
+ * Read it back through the data FIFO port, again sending the whole
+ * transaction (opcode, address, data) through it.
+ */
+ spi_ctrl_start_user(test_data);
+ datafifo_writeb(test_data, EN_4BYTE_ADDR);
+ datafifo_writeb(test_data, READ);
+ datafifo_writel(test_data, make_be32(my_page_addr));
+ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+ page[i] = make_be32(datafifo_readl(test_data));
+ }
+ spi_ctrl_stop_user(test_data);
+
+ for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+ g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
+ }
+
+ flash_reset(test_data);
+}
+
diff --git a/tests/qtest/ast2700-smc-test.c b/tests/qtest/ast2700-smc-test.c
index f85077e04f..925dbcfaaf 100644
--- a/tests/qtest/ast2700-smc-test.c
+++ b/tests/qtest/ast2700-smc-test.c
@@ -64,6 +64,10 @@ static void test_ast2700_evb(AspeedSMCTestData *data)
data, aspeed_smc_test_read_page_mem_qor);
qtest_add_data_func("/ast2700/smc/write_page_qor",
data, aspeed_smc_test_write_page_qor);
+ qtest_add_data_func("/ast2700/smc/write_page_datafifo",
+ data, aspeed_smc_test_write_page_datafifo);
+ qtest_add_data_func("/ast2700/smc/read_page_datafifo",
+ data, aspeed_smc_test_read_page_datafifo);
}
int main(int argc, char **argv)
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode test
2026-07-17 8:18 ` [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode test Jamin Lin
@ 2026-07-17 8:23 ` Cédric Le Goater
2026-07-17 8:46 ` Jamin Lin
0 siblings, 1 reply; 12+ messages in thread
From: Cédric Le Goater @ 2026-07-17 8:23 UTC (permalink / raw)
To: Jamin Lin, Peter Maydell, Steven Lee, Troy Lee, Kane Chen,
Andrew Jeffery, Joel Stanley, Alistair Francis, Fabiano Rosas,
Laurent Vivier, Paolo Bonzini, open list:ASPEED BMCs,
open list:All patches CC here
Cc: Troy Lee
On 7/17/26 10:18, Jamin Lin wrote:
> Add two qtest cases exercising the new AST2700 Data FIFO-based flash
> access path (R_DATA_FIFO at spi_base + 0x200).
>
> Write_page_datafifo sends the page-program command and data through
> the FIFO port, then verifies the result via the regular read path.
> Read_page_datafifo writes a page the regular way, then reads it back
> through the FIFO port, so both directions are checked independently.
>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> tests/qtest/aspeed-smc-utils.h | 4 ++
> tests/qtest/aspeed-smc-utils.c | 103 +++++++++++++++++++++++++++++++++
> tests/qtest/ast2700-smc-test.c | 4 ++
> 3 files changed, 111 insertions(+)
>
This patch doesn't apply on aspeed-next.
Thanks,
C.
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode test
2026-07-17 8:23 ` Cédric Le Goater
@ 2026-07-17 8:46 ` Jamin Lin
0 siblings, 0 replies; 12+ messages in thread
From: Jamin Lin @ 2026-07-17 8:46 UTC (permalink / raw)
To: Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee,
Kane Chen, Andrew Jeffery, Joel Stanley, Alistair Francis,
Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
open list:ASPEED BMCs, open list:All patches CC here
Cc: Troy Lee
> Subject: Re: [PATCH v3 9/9] tests/qtest/ast2700-smc-test: Add Data FIFO mode
> test
>
> On 7/17/26 10:18, Jamin Lin wrote:
> > Add two qtest cases exercising the new AST2700 Data FIFO-based flash
> > access path (R_DATA_FIFO at spi_base + 0x200).
> >
> > Write_page_datafifo sends the page-program command and data through
> > the FIFO port, then verifies the result via the regular read path.
> > Read_page_datafifo writes a page the regular way, then reads it back
> > through the FIFO port, so both directions are checked independently.
> >
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> > tests/qtest/aspeed-smc-utils.h | 4 ++
> > tests/qtest/aspeed-smc-utils.c | 103
> +++++++++++++++++++++++++++++++++
> > tests/qtest/ast2700-smc-test.c | 4 ++
> > 3 files changed, 111 insertions(+)
> >
> This patch doesn't apply on aspeed-next.
>
Sorry resend v4
Jamin
> Thanks,
>
> C.
^ permalink raw reply [flat|nested] 12+ messages in thread