From: Kane-Chen-AS <kane_chen@aspeedtech.com>
AST27x0 boards may host up to two AST1700 IO expander cards. Model the
per-expander interrupt controller (INTCIO) instances and map their MMIO
windows in the SoC.
This reserves the IO expander interrupt controller address space so that
firmware can later route and handle interrupts for AST1700-based boards.
Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com>
---
include/hw/arm/aspeed_soc.h | 4 ++-
include/hw/intc/aspeed_intc.h | 2 ++
hw/arm/aspeed_ast27x0.c | 37 +++++++++++++++++++++
hw/intc/aspeed_intc.c | 60 +++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 1 deletion(-)
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 648c8d5c00..290bb7a6cf 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -151,7 +151,7 @@ struct Aspeed27x0SoCState {
AspeedSoCState parent;
ARMCPU cpu[ASPEED_CPUS_NUM];
- AspeedINTCState intc[2];
+ AspeedINTCState intc[4];
GICv3State gic;
MemoryRegion dram_empty;
};
@@ -307,6 +307,8 @@ enum {
ASPEED_DEV_IPC1,
ASPEED_DEV_LTPI_CTRL1,
ASPEED_DEV_LTPI_CTRL2,
+ ASPEED_DEV_IOEXP0_INTCIO,
+ ASPEED_DEV_IOEXP1_INTCIO,
};
qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 51288384a5..4565bbab84 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -15,6 +15,8 @@
#define TYPE_ASPEED_INTC "aspeed.intc"
#define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
#define TYPE_ASPEED_2700_INTCIO TYPE_ASPEED_INTC "io-ast2700"
+#define TYPE_ASPEED_2700_INTCIOEXP1 TYPE_ASPEED_INTC "ast2700-ioexp1"
+#define TYPE_ASPEED_2700_INTCIOEXP2 TYPE_ASPEED_INTC "ast2700-ioexp2"
#define TYPE_ASPEED_2700SSP_INTC TYPE_ASPEED_INTC "-ast2700ssp"
#define TYPE_ASPEED_2700SSP_INTCIO TYPE_ASPEED_INTC "io-ast2700ssp"
#define TYPE_ASPEED_2700TSP_INTC TYPE_ASPEED_INTC "-ast2700tsp"
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index d63a331c0a..d192534e9e 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -84,7 +84,9 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = {
[ASPEED_DEV_LTPI_CTRL2] = 0x14C35000,
[ASPEED_DEV_WDT] = 0x14C37000,
[ASPEED_DEV_LTPI_IO0] = 0x30000000,
+ [ASPEED_DEV_IOEXP0_INTCIO] = 0x30C18000,
[ASPEED_DEV_LTPI_IO1] = 0x50000000,
+ [ASPEED_DEV_IOEXP1_INTCIO] = 0x50C18000,
[ASPEED_DEV_SPI_BOOT] = 0x100000000,
[ASPEED_DEV_SDRAM] = 0x400000000,
};
@@ -504,6 +506,10 @@ static void aspeed_soc_ast2700_init(Object *obj)
object_initialize_child(obj, "intc", &a->intc[0], TYPE_ASPEED_2700_INTC);
object_initialize_child(obj, "intcio", &a->intc[1],
TYPE_ASPEED_2700_INTCIO);
+ object_initialize_child(obj, "intcioexp0", &a->intc[2],
+ TYPE_ASPEED_2700_INTCIOEXP1);
+ object_initialize_child(obj, "intcioexp1", &a->intc[3],
+ TYPE_ASPEED_2700_INTCIOEXP2);
snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
object_initialize_child(obj, "adc", &s->adc, typename);
@@ -642,6 +648,8 @@ static void aspeed_soc_ast2700_ast1700_realize(Aspeed27x0SoCState *a,
int index, Error **errp)
{
SerialMM *smm;
+ AspeedINTCClass *icio = ASPEED_INTC_GET_CLASS(&a->intc[2 + index]);
+ int i;
hwaddr uart_base = sc->memmap[ASPEED_DEV_LTPI_IO0 + index] +
aspeed_soc_ast1700_memmap[ASPEED_DEV_UART12];
AspeedLTPIState *ltpi_ctrl = ASPEED_LTPI(&s->ltpi_ctrl[index]);
@@ -661,6 +669,19 @@ static void aspeed_soc_ast2700_ast1700_realize(Aspeed27x0SoCState *a,
return;
}
aspeed_mmio_map(s, SYS_BUS_DEVICE(ltpi_ctrl), 0, ltpi_base);
+
+ /* INTC2/3 internal: orgate[i] -> input[i] */
+ for (i = 0; i < icio->num_inpins; i++) {
+ qdev_connect_gpio_out(DEVICE(&a->intc[2 + index].orgates[i]), 0,
+ qdev_get_gpio_in(DEVICE(&a->intc[2 + index]), i));
+ }
+
+ /* INTC2/3 output[i] -> INTC0.orgate[0].input[i] */
+ for (i = 0; i < icio->num_outpins; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc[2 + index]), i,
+ qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), i));
+ }
+
aspeed_mmio_map(s, SYS_BUS_DEVICE(smm), 0, uart_base);
}
@@ -717,6 +738,22 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[1]), 0,
sc->memmap[ASPEED_DEV_INTCIO]);
+ /* INTCIOEXP0 */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[2]), errp)) {
+ return;
+ }
+
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[2]), 0,
+ sc->memmap[ASPEED_DEV_IOEXP0_INTCIO]);
+
+ /* INTCIOEXP */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[3]), errp)) {
+ return;
+ }
+
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[3]), 0,
+ sc->memmap[ASPEED_DEV_IOEXP1_INTCIO]);
+
/* irq sources -> orgates -> INTC */
for (i = 0; i < ic->num_inpins; i++) {
qdev_connect_gpio_out(DEVICE(&a->intc[0].orgates[i]), 0,
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 5cd786dee6..a04005ee7c 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -924,6 +924,64 @@ static const TypeInfo aspeed_2700_intc_info = {
.class_init = aspeed_2700_intc_class_init,
};
+static AspeedINTCIRQ aspeed_2700_intcioexp2_irqs[ASPEED_INTC_MAX_INPINS] = {
+ {0, 8, 1, R_GICINT192_EN, R_GICINT192_STATUS},
+ {1, 9, 1, R_GICINT193_EN, R_GICINT193_STATUS},
+};
+
+static void aspeed_2700_intcioexp2_class_init(ObjectClass *klass,
+ const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 IOEXP2 INTC Controller";
+ aic->num_lines = 32;
+ aic->num_inpins = 2;
+ aic->num_outpins = 10;
+ aic->mem_size = 0x400;
+ aic->nr_regs = 0x58 >> 2;
+ aic->reg_offset = 0x100;
+ aic->reg_ops = &aspeed_intcio_ops;
+ aic->irq_table = aspeed_2700_intcioexp2_irqs;
+ aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcioexp2_irqs);
+}
+
+static const TypeInfo aspeed_2700_intcioexp2_info = {
+ .name = TYPE_ASPEED_2700_INTCIOEXP2,
+ .parent = TYPE_ASPEED_INTC,
+ .class_init = aspeed_2700_intcioexp2_class_init,
+};
+
+static AspeedINTCIRQ aspeed_2700_intcioexp1_irqs[ASPEED_INTC_MAX_INPINS] = {
+ {0, 6, 1, R_GICINT192_EN, R_GICINT192_STATUS},
+ {1, 7, 1, R_GICINT193_EN, R_GICINT193_STATUS},
+};
+
+static void aspeed_2700_intcioexp1_class_init(ObjectClass *klass,
+ const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 IOEXP1 INTC Controller";
+ aic->num_lines = 32;
+ aic->num_inpins = 2;
+ aic->num_outpins = 10;
+ aic->mem_size = 0x400;
+ aic->nr_regs = 0x58 >> 2;
+ aic->reg_offset = 0x100;
+ aic->reg_ops = &aspeed_intcio_ops;
+ aic->irq_table = aspeed_2700_intcioexp1_irqs;
+ aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcioexp1_irqs);
+}
+
+static const TypeInfo aspeed_2700_intcioexp1_info = {
+ .name = TYPE_ASPEED_2700_INTCIOEXP1,
+ .parent = TYPE_ASPEED_INTC,
+ .class_init = aspeed_2700_intcioexp1_class_init,
+};
+
static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
{0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS},
{1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS},
@@ -1099,6 +1157,8 @@ static void aspeed_intc_register_types(void)
type_register_static(&aspeed_intc_info);
type_register_static(&aspeed_2700_intc_info);
type_register_static(&aspeed_2700_intcio_info);
+ type_register_static(&aspeed_2700_intcioexp1_info);
+ type_register_static(&aspeed_2700_intcioexp2_info);
type_register_static(&aspeed_2700ssp_intc_info);
type_register_static(&aspeed_2700ssp_intcio_info);
type_register_static(&aspeed_2700tsp_intc_info);
--
2.43.0
© 2016 - 2025 Red Hat, Inc.