From: Jamin Lin via <qemu-arm@nongnu.org>
To: "Cédric Le Goater" <clg@kaod.org>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Steven Lee" <steven_lee@aspeedtech.com>,
"Troy Lee" <leetroy@gmail.com>,
"Andrew Jeffery" <andrew@codeconstruct.com.au>,
"Joel Stanley" <joel@jms.id.au>,
"open list:ASPEED BMCs" <qemu-arm@nongnu.org>,
"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: <jamin_lin@aspeedtech.com>, <troy_lee@aspeedtech.com>,
<yunlin.tang@aspeedtech.com>
Subject: [PATCH v1 06/18] hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq index and register address
Date: Tue, 21 Jan 2025 15:04:12 +0800 [thread overview]
Message-ID: <20250121070424.2465942-7-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20250121070424.2465942-1-jamin_lin@aspeedtech.com>
The INTC0 controller supports GICINT128 to GICINT136, mapping 1:1 to input and
output IRQs 0 to 8. Previously, the formula "address & 0x0f00" was used to
derive the IRQ index numbers.
However, the INTC0 controller also supports GICINT192_201, mapping 1 input IRQ
pin to 10 output IRQ pins. The pin numbers for input and output are different.
Additionally, the INTC0 controller supports routing to GIC, SSP, TSP, and
BOOTMCU, making it difficult to use a formula to determine the index number of
INTC0 model supported input and output IRQs.
To simplify and improve readability, introduces the AspeedINTCIRQ structure to
save the input/output IRQ index and its enable/status register address.
Introduce the "aspeed_2700_intc0_irqs" table to store IRQ information for INTC0.
Introduce the "aspeed_intc_get_irq" function to retrieve the input/output IRQ
pin index from the provided status/enable register address.
Update the code to use "num_inpins" and "num_outpins" instead of "num_ints".
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/arm/aspeed_ast27x0.c | 2 +-
hw/intc/aspeed_intc.c | 165 ++++++++++++++++++++++------------
hw/intc/trace-events | 12 +--
include/hw/intc/aspeed_intc.h | 26 ++++--
4 files changed, 135 insertions(+), 70 deletions(-)
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index ba461fcd3c..d5e521cd38 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -520,7 +520,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sc->memmap[ASPEED_DEV_INTC0]);
/* GICINT orgates -> INTC -> GIC */
- for (i = 0; i < ic->num_ints; i++) {
+ for (i = 0; i < ic->num_inpins; i++) {
qdev_connect_gpio_out(DEVICE(&a->intc.orgates[i]), 0,
qdev_get_gpio_in(DEVICE(&a->intc), i));
sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), i,
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 7dff5e6039..45f1c59a4b 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -34,20 +34,61 @@ REG32(INTC0_GICINT135_STATUS, 0x1704)
REG32(INTC0_GICINT136_EN, 0x1800)
REG32(INTC0_GICINT136_STATUS, 0x1804)
-#define GICINT_STATUS_BASE R_INTC0_GICINT128_STATUS
+static AspeedINTCIRQ aspeed_2700_intc0_irqs[ASPEED_INTC_MAX_INPINS] = {
+ {0, 0, 1, R_INTC0_GICINT128_EN, R_INTC0_GICINT128_STATUS},
+ {1, 1, 1, R_INTC0_GICINT129_EN, R_INTC0_GICINT129_STATUS},
+ {2, 2, 1, R_INTC0_GICINT130_EN, R_INTC0_GICINT130_STATUS},
+ {3, 3, 1, R_INTC0_GICINT131_EN, R_INTC0_GICINT131_STATUS},
+ {4, 4, 1, R_INTC0_GICINT132_EN, R_INTC0_GICINT132_STATUS},
+ {5, 5, 1, R_INTC0_GICINT133_EN, R_INTC0_GICINT133_STATUS},
+ {6, 6, 1, R_INTC0_GICINT134_EN, R_INTC0_GICINT134_STATUS},
+ {7, 7, 1, R_INTC0_GICINT135_EN, R_INTC0_GICINT135_STATUS},
+ {8, 8, 1, R_INTC0_GICINT136_EN, R_INTC0_GICINT136_STATUS},
+};
+
+static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
+ uint32_t addr)
+{
+ int i;
+
+ for (i = 0; i < aic->irq_table_count; i++) {
+ if (aic->irq_table[i].enable_addr == addr ||
+ aic->irq_table[i].status_addr == addr) {
+ return &aic->irq_table[i];
+ }
+ }
+
+ /*
+ * Invalid addr.
+ */
+ g_assert_not_reached();
+}
-static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
+/*
+ * Update the state of an interrupt controller pin by setting
+ * the specified output pin to the given level.
+ * The input pin index should be between 0 and the number of input pins.
+ * The output pin index should be between 0 and the number of output pins.
+ */
+static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
+ int outpin_idx, int level)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ if (inpin_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
+ __func__, inpin_idx);
+ return;
+ }
+
+ if (outpin_idx >= aic->num_outpins) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid output pin index: %d\n",
+ __func__, outpin_idx);
return;
}
- trace_aspeed_intc_update_irq(irq, level);
- qemu_set_irq(s->output_pins[irq], level);
+ trace_aspeed_intc_update_irq(inpin_idx, outpin_idx, level);
+ qemu_set_irq(s->output_pins[outpin_idx], level);
}
/*
@@ -56,30 +97,33 @@ static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
* The value of irq should be 0 to num_ints.
* The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
*/
-static void aspeed_intc_set_irq(void *opaque, int irq, int level)
+static void aspeed_intc_set_irq(void *opaque, int irq_idx, int level)
{
AspeedINTCState *s = (AspeedINTCState *)opaque;
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t status_addr = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
+ const AspeedINTCIRQ *irq;
uint32_t select = 0;
uint32_t enable;
int i;
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ if (irq_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid input interrupt number: %d\n",
+ __func__, irq_idx);
return;
}
- trace_aspeed_intc_set_irq(irq, level);
- enable = s->enable[irq];
+ irq = &aic->irq_table[irq_idx];
+
+ trace_aspeed_intc_set_irq(irq->inpin_idx, level);
+ enable = s->enable[irq->inpin_idx];
if (!level) {
return;
}
for (i = 0; i < aic->num_lines; i++) {
- if (s->orgates[irq].levels[i]) {
+ if (s->orgates[irq->inpin_idx].levels[i]) {
if (enable & BIT(i)) {
select |= BIT(i);
}
@@ -92,7 +136,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
trace_aspeed_intc_select(select);
- if (s->mask[irq] || s->regs[status_addr]) {
+ if (s->mask[irq->inpin_idx] || s->regs[irq->status_addr]) {
/*
* a. mask is not 0 means in ISR mode
* sources interrupt routine are executing.
@@ -101,16 +145,18 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
*
* save source interrupt to pending variable.
*/
- s->pending[irq] |= select;
- trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
+ s->pending[irq->inpin_idx] |= select;
+ trace_aspeed_intc_pending_irq(irq->inpin_idx,
+ s->pending[irq->inpin_idx]);
} else {
/*
* notify firmware which source interrupt are coming
* by setting status register
*/
- s->regs[status_addr] = select;
- trace_aspeed_intc_trigger_irq(irq, s->regs[status_addr]);
- aspeed_intc_update(s, irq, 1);
+ s->regs[irq->status_addr] = select;
+ trace_aspeed_intc_trigger_irq(irq->inpin_idx, irq->outpin_idx,
+ s->regs[irq->status_addr]);
+ aspeed_intc_update(s, irq->inpin_idx, irq->outpin_idx, 1);
}
}
@@ -118,16 +164,16 @@ static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
uint64_t data)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t offset = addr << 2;
+ const AspeedINTCIRQ *irq;
uint32_t old_enable;
uint32_t change;
- uint32_t irq;
- irq = (offset & 0x0f00) >> 8;
+ irq = aspeed_intc_get_irq(aic, addr);
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ if (irq->inpin_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid input pin index number: %d\n",
+ __func__, irq->inpin_idx);
return;
}
@@ -138,17 +184,17 @@ static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
*/
/* disable all source interrupt */
- if (!data && !s->enable[irq]) {
+ if (!data && !s->enable[irq->inpin_idx]) {
s->regs[addr] = data;
return;
}
- old_enable = s->enable[irq];
- s->enable[irq] |= data;
+ old_enable = s->enable[irq->inpin_idx];
+ s->enable[irq->inpin_idx] |= data;
/* enable new source interrupt */
- if (old_enable != s->enable[irq]) {
- trace_aspeed_intc_enable(s->enable[irq]);
+ if (old_enable != s->enable[irq->inpin_idx]) {
+ trace_aspeed_intc_enable(s->enable[irq->inpin_idx]);
s->regs[addr] = data;
return;
}
@@ -156,11 +202,11 @@ static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
/* mask and unmask source interrupt */
change = s->regs[addr] ^ data;
if (change & data) {
- s->mask[irq] &= ~change;
- trace_aspeed_intc_unmask(change, s->mask[irq]);
+ s->mask[irq->inpin_idx] &= ~change;
+ trace_aspeed_intc_unmask(change, s->mask[irq->inpin_idx]);
} else {
- s->mask[irq] |= change;
- trace_aspeed_intc_mask(change, s->mask[irq]);
+ s->mask[irq->inpin_idx] |= change;
+ trace_aspeed_intc_mask(change, s->mask[irq->inpin_idx]);
}
s->regs[addr] = data;
}
@@ -169,19 +215,19 @@ static void aspeed_2700_intc_status_handler(AspeedINTCState *s, uint32_t addr,
uint64_t data)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t offset = addr << 2;
- uint32_t irq;
-
- irq = (offset & 0x0f00) >> 8;
+ const AspeedINTCIRQ *irq;
if (!data) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
return;
}
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ irq = aspeed_intc_get_irq(aic, addr);
+
+ if (irq->inpin_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid input pin index number: %d\n",
+ __func__, irq->inpin_idx);
return;
}
@@ -200,21 +246,22 @@ static void aspeed_2700_intc_status_handler(AspeedINTCState *s, uint32_t addr,
/* All source ISR execution are done */
if (!s->regs[addr]) {
- trace_aspeed_intc_all_isr_done(irq);
- if (s->pending[irq]) {
+ trace_aspeed_intc_all_isr_done(irq->inpin_idx);
+ if (s->pending[irq->inpin_idx]) {
/*
* handle pending source interrupt
* notify firmware which source interrupt are pending
* by setting status register
*/
- s->regs[addr] = s->pending[irq];
- s->pending[irq] = 0;
- trace_aspeed_intc_trigger_irq(irq, s->regs[addr]);
- aspeed_intc_update(s, irq, 1);
+ s->regs[addr] = s->pending[irq->inpin_idx];
+ s->pending[irq->inpin_idx] = 0;
+ trace_aspeed_intc_trigger_irq(irq->inpin_idx, irq->outpin_idx,
+ s->regs[addr]);
+ aspeed_intc_update(s, irq->inpin_idx, irq->outpin_idx, 1);
} else {
/* clear irq */
- trace_aspeed_intc_clear_irq(irq, 0);
- aspeed_intc_update(s, irq, 0);
+ trace_aspeed_intc_clear_irq(irq->inpin_idx, irq->outpin_idx, 0);
+ aspeed_intc_update(s, irq->inpin_idx, irq->outpin_idx, 0);
}
}
}
@@ -301,8 +348,8 @@ static void aspeed_intc_instance_init(Object *obj)
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
- assert(aic->num_ints <= ASPEED_INTC_NR_INTS);
- for (i = 0; i < aic->num_ints; i++) {
+ assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS);
+ for (i = 0; i < aic->num_inpins; i++) {
object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
TYPE_OR_IRQ);
object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
@@ -337,12 +384,15 @@ static void aspeed_intc_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
- qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
+ qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins);
- for (i = 0; i < aic->num_ints; i++) {
+ for (i = 0; i < aic->num_inpins; i++) {
if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
return;
}
+ }
+
+ for (i = 0; i < aic->num_outpins; i++) {
sysbus_init_irq(sbd, &s->output_pins[i]);
}
}
@@ -387,10 +437,13 @@ static void aspeed_2700_intc0_class_init(ObjectClass *klass, void *data)
dc->desc = "ASPEED 2700 INTC 0 Controller";
aic->num_lines = 32;
- aic->num_ints = 9;
+ aic->num_inpins = 9;
+ aic->num_outpins = 9;
aic->reg_ops = &aspeed_2700_intc0_ops;
aic->mem_size = 0x4000;
aic->reg_size = 0x2000;
+ aic->irq_table = aspeed_2700_intc0_irqs;
+ aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc0_irqs);
}
static const TypeInfo aspeed_2700_intc0_info = {
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 3dcf147198..af9703e1b5 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -82,12 +82,12 @@ aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64
# aspeed_intc.c
aspeed_intc_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_intc_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
-aspeed_intc_set_irq(int irq, int level) "Set IRQ %d: %d"
-aspeed_intc_clear_irq(int irq, int level) "Clear IRQ %d: %d"
-aspeed_intc_update_irq(int irq, int level) "Update IRQ: %d: %d"
-aspeed_intc_pending_irq(int irq, uint32_t value) "Pending IRQ: %d: 0x%x"
-aspeed_intc_trigger_irq(int irq, uint32_t value) "Trigger IRQ: %d: 0x%x"
-aspeed_intc_all_isr_done(int irq) "All source ISR execution are done: %d"
+aspeed_intc_set_irq(int inpin_idx, int level) "Set IRQ %d: %d"
+aspeed_intc_clear_irq(int inpin_idx, int outpin_idx, int level) "Clear IRQ %d-%d: %d"
+aspeed_intc_update_irq(int inpin_idx, int outpin_idx, int level) "Update IRQ: %d-%d: %d"
+aspeed_intc_pending_irq(int inpin_idx, uint32_t value) "Pending IRQ: %d: 0x%x"
+aspeed_intc_trigger_irq(int inpin_idx, int outpin_idx, uint32_t value) "Trigger IRQ: %d-%d: 0x%x"
+aspeed_intc_all_isr_done(int inpin_idx) "All source ISR execution are done: %d"
aspeed_intc_enable(uint32_t value) "Enable: 0x%x"
aspeed_intc_select(uint32_t value) "Select: 0x%x"
aspeed_intc_mask(uint32_t change, uint32_t value) "Mask: 0x%x: 0x%x"
diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index d881cb7088..73261037ea 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -17,7 +17,16 @@
OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
-#define ASPEED_INTC_NR_INTS 9
+#define ASPEED_INTC_MAX_INPINS 9
+#define ASPEED_INTC_MAX_OUTPINS 9
+
+typedef struct AspeedINTCIRQ {
+ int inpin_idx;
+ int outpin_idx;
+ int num_outpins;
+ uint32_t enable_addr;
+ uint32_t status_addr;
+} AspeedINTCIRQ;
struct AspeedINTCState {
/*< private >*/
@@ -28,22 +37,25 @@ struct AspeedINTCState {
MemoryRegion iomem_container;
uint32_t regs[ASPEED_INTC_NR_REGS];
- OrIRQState orgates[ASPEED_INTC_NR_INTS];
- qemu_irq output_pins[ASPEED_INTC_NR_INTS];
+ OrIRQState orgates[ASPEED_INTC_MAX_INPINS];
+ qemu_irq output_pins[ASPEED_INTC_MAX_OUTPINS];
- uint32_t enable[ASPEED_INTC_NR_INTS];
- uint32_t mask[ASPEED_INTC_NR_INTS];
- uint32_t pending[ASPEED_INTC_NR_INTS];
+ uint32_t enable[ASPEED_INTC_MAX_INPINS];
+ uint32_t mask[ASPEED_INTC_MAX_INPINS];
+ uint32_t pending[ASPEED_INTC_MAX_INPINS];
};
struct AspeedINTCClass {
SysBusDeviceClass parent_class;
uint32_t num_lines;
- uint32_t num_ints;
+ uint32_t num_inpins;
+ uint32_t num_outpins;
const MemoryRegionOps *reg_ops;
uint64_t mem_size;
uint64_t reg_size;
+ const AspeedINTCIRQ *irq_table;
+ int irq_table_count;
};
#endif /* ASPEED_INTC_H */
--
2.34.1
WARNING: multiple messages have this Message-ID (diff)
From: Jamin Lin via <qemu-devel@nongnu.org>
To: "Cédric Le Goater" <clg@kaod.org>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Steven Lee" <steven_lee@aspeedtech.com>,
"Troy Lee" <leetroy@gmail.com>,
"Andrew Jeffery" <andrew@codeconstruct.com.au>,
"Joel Stanley" <joel@jms.id.au>,
"open list:ASPEED BMCs" <qemu-arm@nongnu.org>,
"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: <jamin_lin@aspeedtech.com>, <troy_lee@aspeedtech.com>,
<yunlin.tang@aspeedtech.com>
Subject: [PATCH v1 06/18] hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq index and register address
Date: Tue, 21 Jan 2025 15:04:12 +0800 [thread overview]
Message-ID: <20250121070424.2465942-7-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20250121070424.2465942-1-jamin_lin@aspeedtech.com>
The INTC0 controller supports GICINT128 to GICINT136, mapping 1:1 to input and
output IRQs 0 to 8. Previously, the formula "address & 0x0f00" was used to
derive the IRQ index numbers.
However, the INTC0 controller also supports GICINT192_201, mapping 1 input IRQ
pin to 10 output IRQ pins. The pin numbers for input and output are different.
Additionally, the INTC0 controller supports routing to GIC, SSP, TSP, and
BOOTMCU, making it difficult to use a formula to determine the index number of
INTC0 model supported input and output IRQs.
To simplify and improve readability, introduces the AspeedINTCIRQ structure to
save the input/output IRQ index and its enable/status register address.
Introduce the "aspeed_2700_intc0_irqs" table to store IRQ information for INTC0.
Introduce the "aspeed_intc_get_irq" function to retrieve the input/output IRQ
pin index from the provided status/enable register address.
Update the code to use "num_inpins" and "num_outpins" instead of "num_ints".
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/arm/aspeed_ast27x0.c | 2 +-
hw/intc/aspeed_intc.c | 165 ++++++++++++++++++++++------------
hw/intc/trace-events | 12 +--
include/hw/intc/aspeed_intc.h | 26 ++++--
4 files changed, 135 insertions(+), 70 deletions(-)
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index ba461fcd3c..d5e521cd38 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -520,7 +520,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
sc->memmap[ASPEED_DEV_INTC0]);
/* GICINT orgates -> INTC -> GIC */
- for (i = 0; i < ic->num_ints; i++) {
+ for (i = 0; i < ic->num_inpins; i++) {
qdev_connect_gpio_out(DEVICE(&a->intc.orgates[i]), 0,
qdev_get_gpio_in(DEVICE(&a->intc), i));
sysbus_connect_irq(SYS_BUS_DEVICE(&a->intc), i,
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 7dff5e6039..45f1c59a4b 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -34,20 +34,61 @@ REG32(INTC0_GICINT135_STATUS, 0x1704)
REG32(INTC0_GICINT136_EN, 0x1800)
REG32(INTC0_GICINT136_STATUS, 0x1804)
-#define GICINT_STATUS_BASE R_INTC0_GICINT128_STATUS
+static AspeedINTCIRQ aspeed_2700_intc0_irqs[ASPEED_INTC_MAX_INPINS] = {
+ {0, 0, 1, R_INTC0_GICINT128_EN, R_INTC0_GICINT128_STATUS},
+ {1, 1, 1, R_INTC0_GICINT129_EN, R_INTC0_GICINT129_STATUS},
+ {2, 2, 1, R_INTC0_GICINT130_EN, R_INTC0_GICINT130_STATUS},
+ {3, 3, 1, R_INTC0_GICINT131_EN, R_INTC0_GICINT131_STATUS},
+ {4, 4, 1, R_INTC0_GICINT132_EN, R_INTC0_GICINT132_STATUS},
+ {5, 5, 1, R_INTC0_GICINT133_EN, R_INTC0_GICINT133_STATUS},
+ {6, 6, 1, R_INTC0_GICINT134_EN, R_INTC0_GICINT134_STATUS},
+ {7, 7, 1, R_INTC0_GICINT135_EN, R_INTC0_GICINT135_STATUS},
+ {8, 8, 1, R_INTC0_GICINT136_EN, R_INTC0_GICINT136_STATUS},
+};
+
+static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
+ uint32_t addr)
+{
+ int i;
+
+ for (i = 0; i < aic->irq_table_count; i++) {
+ if (aic->irq_table[i].enable_addr == addr ||
+ aic->irq_table[i].status_addr == addr) {
+ return &aic->irq_table[i];
+ }
+ }
+
+ /*
+ * Invalid addr.
+ */
+ g_assert_not_reached();
+}
-static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
+/*
+ * Update the state of an interrupt controller pin by setting
+ * the specified output pin to the given level.
+ * The input pin index should be between 0 and the number of input pins.
+ * The output pin index should be between 0 and the number of output pins.
+ */
+static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
+ int outpin_idx, int level)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ if (inpin_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
+ __func__, inpin_idx);
+ return;
+ }
+
+ if (outpin_idx >= aic->num_outpins) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid output pin index: %d\n",
+ __func__, outpin_idx);
return;
}
- trace_aspeed_intc_update_irq(irq, level);
- qemu_set_irq(s->output_pins[irq], level);
+ trace_aspeed_intc_update_irq(inpin_idx, outpin_idx, level);
+ qemu_set_irq(s->output_pins[outpin_idx], level);
}
/*
@@ -56,30 +97,33 @@ static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
* The value of irq should be 0 to num_ints.
* The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
*/
-static void aspeed_intc_set_irq(void *opaque, int irq, int level)
+static void aspeed_intc_set_irq(void *opaque, int irq_idx, int level)
{
AspeedINTCState *s = (AspeedINTCState *)opaque;
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t status_addr = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
+ const AspeedINTCIRQ *irq;
uint32_t select = 0;
uint32_t enable;
int i;
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ if (irq_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid input interrupt number: %d\n",
+ __func__, irq_idx);
return;
}
- trace_aspeed_intc_set_irq(irq, level);
- enable = s->enable[irq];
+ irq = &aic->irq_table[irq_idx];
+
+ trace_aspeed_intc_set_irq(irq->inpin_idx, level);
+ enable = s->enable[irq->inpin_idx];
if (!level) {
return;
}
for (i = 0; i < aic->num_lines; i++) {
- if (s->orgates[irq].levels[i]) {
+ if (s->orgates[irq->inpin_idx].levels[i]) {
if (enable & BIT(i)) {
select |= BIT(i);
}
@@ -92,7 +136,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
trace_aspeed_intc_select(select);
- if (s->mask[irq] || s->regs[status_addr]) {
+ if (s->mask[irq->inpin_idx] || s->regs[irq->status_addr]) {
/*
* a. mask is not 0 means in ISR mode
* sources interrupt routine are executing.
@@ -101,16 +145,18 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
*
* save source interrupt to pending variable.
*/
- s->pending[irq] |= select;
- trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
+ s->pending[irq->inpin_idx] |= select;
+ trace_aspeed_intc_pending_irq(irq->inpin_idx,
+ s->pending[irq->inpin_idx]);
} else {
/*
* notify firmware which source interrupt are coming
* by setting status register
*/
- s->regs[status_addr] = select;
- trace_aspeed_intc_trigger_irq(irq, s->regs[status_addr]);
- aspeed_intc_update(s, irq, 1);
+ s->regs[irq->status_addr] = select;
+ trace_aspeed_intc_trigger_irq(irq->inpin_idx, irq->outpin_idx,
+ s->regs[irq->status_addr]);
+ aspeed_intc_update(s, irq->inpin_idx, irq->outpin_idx, 1);
}
}
@@ -118,16 +164,16 @@ static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
uint64_t data)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t offset = addr << 2;
+ const AspeedINTCIRQ *irq;
uint32_t old_enable;
uint32_t change;
- uint32_t irq;
- irq = (offset & 0x0f00) >> 8;
+ irq = aspeed_intc_get_irq(aic, addr);
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ if (irq->inpin_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid input pin index number: %d\n",
+ __func__, irq->inpin_idx);
return;
}
@@ -138,17 +184,17 @@ static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
*/
/* disable all source interrupt */
- if (!data && !s->enable[irq]) {
+ if (!data && !s->enable[irq->inpin_idx]) {
s->regs[addr] = data;
return;
}
- old_enable = s->enable[irq];
- s->enable[irq] |= data;
+ old_enable = s->enable[irq->inpin_idx];
+ s->enable[irq->inpin_idx] |= data;
/* enable new source interrupt */
- if (old_enable != s->enable[irq]) {
- trace_aspeed_intc_enable(s->enable[irq]);
+ if (old_enable != s->enable[irq->inpin_idx]) {
+ trace_aspeed_intc_enable(s->enable[irq->inpin_idx]);
s->regs[addr] = data;
return;
}
@@ -156,11 +202,11 @@ static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
/* mask and unmask source interrupt */
change = s->regs[addr] ^ data;
if (change & data) {
- s->mask[irq] &= ~change;
- trace_aspeed_intc_unmask(change, s->mask[irq]);
+ s->mask[irq->inpin_idx] &= ~change;
+ trace_aspeed_intc_unmask(change, s->mask[irq->inpin_idx]);
} else {
- s->mask[irq] |= change;
- trace_aspeed_intc_mask(change, s->mask[irq]);
+ s->mask[irq->inpin_idx] |= change;
+ trace_aspeed_intc_mask(change, s->mask[irq->inpin_idx]);
}
s->regs[addr] = data;
}
@@ -169,19 +215,19 @@ static void aspeed_2700_intc_status_handler(AspeedINTCState *s, uint32_t addr,
uint64_t data)
{
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
- uint32_t offset = addr << 2;
- uint32_t irq;
-
- irq = (offset & 0x0f00) >> 8;
+ const AspeedINTCIRQ *irq;
if (!data) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
return;
}
- if (irq >= aic->num_ints) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
- __func__, irq);
+ irq = aspeed_intc_get_irq(aic, addr);
+
+ if (irq->inpin_idx >= aic->num_inpins) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Invalid input pin index number: %d\n",
+ __func__, irq->inpin_idx);
return;
}
@@ -200,21 +246,22 @@ static void aspeed_2700_intc_status_handler(AspeedINTCState *s, uint32_t addr,
/* All source ISR execution are done */
if (!s->regs[addr]) {
- trace_aspeed_intc_all_isr_done(irq);
- if (s->pending[irq]) {
+ trace_aspeed_intc_all_isr_done(irq->inpin_idx);
+ if (s->pending[irq->inpin_idx]) {
/*
* handle pending source interrupt
* notify firmware which source interrupt are pending
* by setting status register
*/
- s->regs[addr] = s->pending[irq];
- s->pending[irq] = 0;
- trace_aspeed_intc_trigger_irq(irq, s->regs[addr]);
- aspeed_intc_update(s, irq, 1);
+ s->regs[addr] = s->pending[irq->inpin_idx];
+ s->pending[irq->inpin_idx] = 0;
+ trace_aspeed_intc_trigger_irq(irq->inpin_idx, irq->outpin_idx,
+ s->regs[addr]);
+ aspeed_intc_update(s, irq->inpin_idx, irq->outpin_idx, 1);
} else {
/* clear irq */
- trace_aspeed_intc_clear_irq(irq, 0);
- aspeed_intc_update(s, irq, 0);
+ trace_aspeed_intc_clear_irq(irq->inpin_idx, irq->outpin_idx, 0);
+ aspeed_intc_update(s, irq->inpin_idx, irq->outpin_idx, 0);
}
}
}
@@ -301,8 +348,8 @@ static void aspeed_intc_instance_init(Object *obj)
AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
int i;
- assert(aic->num_ints <= ASPEED_INTC_NR_INTS);
- for (i = 0; i < aic->num_ints; i++) {
+ assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS);
+ for (i = 0; i < aic->num_inpins; i++) {
object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
TYPE_OR_IRQ);
object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
@@ -337,12 +384,15 @@ static void aspeed_intc_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
- qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
+ qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins);
- for (i = 0; i < aic->num_ints; i++) {
+ for (i = 0; i < aic->num_inpins; i++) {
if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
return;
}
+ }
+
+ for (i = 0; i < aic->num_outpins; i++) {
sysbus_init_irq(sbd, &s->output_pins[i]);
}
}
@@ -387,10 +437,13 @@ static void aspeed_2700_intc0_class_init(ObjectClass *klass, void *data)
dc->desc = "ASPEED 2700 INTC 0 Controller";
aic->num_lines = 32;
- aic->num_ints = 9;
+ aic->num_inpins = 9;
+ aic->num_outpins = 9;
aic->reg_ops = &aspeed_2700_intc0_ops;
aic->mem_size = 0x4000;
aic->reg_size = 0x2000;
+ aic->irq_table = aspeed_2700_intc0_irqs;
+ aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc0_irqs);
}
static const TypeInfo aspeed_2700_intc0_info = {
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 3dcf147198..af9703e1b5 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -82,12 +82,12 @@ aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64
# aspeed_intc.c
aspeed_intc_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_intc_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
-aspeed_intc_set_irq(int irq, int level) "Set IRQ %d: %d"
-aspeed_intc_clear_irq(int irq, int level) "Clear IRQ %d: %d"
-aspeed_intc_update_irq(int irq, int level) "Update IRQ: %d: %d"
-aspeed_intc_pending_irq(int irq, uint32_t value) "Pending IRQ: %d: 0x%x"
-aspeed_intc_trigger_irq(int irq, uint32_t value) "Trigger IRQ: %d: 0x%x"
-aspeed_intc_all_isr_done(int irq) "All source ISR execution are done: %d"
+aspeed_intc_set_irq(int inpin_idx, int level) "Set IRQ %d: %d"
+aspeed_intc_clear_irq(int inpin_idx, int outpin_idx, int level) "Clear IRQ %d-%d: %d"
+aspeed_intc_update_irq(int inpin_idx, int outpin_idx, int level) "Update IRQ: %d-%d: %d"
+aspeed_intc_pending_irq(int inpin_idx, uint32_t value) "Pending IRQ: %d: 0x%x"
+aspeed_intc_trigger_irq(int inpin_idx, int outpin_idx, uint32_t value) "Trigger IRQ: %d-%d: 0x%x"
+aspeed_intc_all_isr_done(int inpin_idx) "All source ISR execution are done: %d"
aspeed_intc_enable(uint32_t value) "Enable: 0x%x"
aspeed_intc_select(uint32_t value) "Select: 0x%x"
aspeed_intc_mask(uint32_t change, uint32_t value) "Mask: 0x%x: 0x%x"
diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index d881cb7088..73261037ea 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -17,7 +17,16 @@
OBJECT_DECLARE_TYPE(AspeedINTCState, AspeedINTCClass, ASPEED_INTC)
#define ASPEED_INTC_NR_REGS (0x2000 >> 2)
-#define ASPEED_INTC_NR_INTS 9
+#define ASPEED_INTC_MAX_INPINS 9
+#define ASPEED_INTC_MAX_OUTPINS 9
+
+typedef struct AspeedINTCIRQ {
+ int inpin_idx;
+ int outpin_idx;
+ int num_outpins;
+ uint32_t enable_addr;
+ uint32_t status_addr;
+} AspeedINTCIRQ;
struct AspeedINTCState {
/*< private >*/
@@ -28,22 +37,25 @@ struct AspeedINTCState {
MemoryRegion iomem_container;
uint32_t regs[ASPEED_INTC_NR_REGS];
- OrIRQState orgates[ASPEED_INTC_NR_INTS];
- qemu_irq output_pins[ASPEED_INTC_NR_INTS];
+ OrIRQState orgates[ASPEED_INTC_MAX_INPINS];
+ qemu_irq output_pins[ASPEED_INTC_MAX_OUTPINS];
- uint32_t enable[ASPEED_INTC_NR_INTS];
- uint32_t mask[ASPEED_INTC_NR_INTS];
- uint32_t pending[ASPEED_INTC_NR_INTS];
+ uint32_t enable[ASPEED_INTC_MAX_INPINS];
+ uint32_t mask[ASPEED_INTC_MAX_INPINS];
+ uint32_t pending[ASPEED_INTC_MAX_INPINS];
};
struct AspeedINTCClass {
SysBusDeviceClass parent_class;
uint32_t num_lines;
- uint32_t num_ints;
+ uint32_t num_inpins;
+ uint32_t num_outpins;
const MemoryRegionOps *reg_ops;
uint64_t mem_size;
uint64_t reg_size;
+ const AspeedINTCIRQ *irq_table;
+ int irq_table_count;
};
#endif /* ASPEED_INTC_H */
--
2.34.1
next prev parent reply other threads:[~2025-01-21 7:06 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-21 7:04 [PATCH v1 00/18] Support AST2700 A1 Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 01/18] hw/intc/aspeed: Rename INTC to INTC0 Jamin Lin via
2025-01-29 17:03 ` Cédric Le Goater
2025-01-30 3:22 ` Andrew Jeffery
2025-02-04 6:50 ` Jamin Lin
2025-02-04 7:34 ` Cédric Le Goater
2025-02-04 8:22 ` Jamin Lin
2025-02-04 10:26 ` Cédric Le Goater
2025-01-30 3:27 ` Andrew Jeffery
2025-01-21 7:04 ` [PATCH v1 02/18] hw/intc/aspeed: Support different memory region ops Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-30 3:32 ` Andrew Jeffery
2025-02-04 7:00 ` Jamin Lin
2025-01-21 7:04 ` [PATCH v1 03/18] hw/intc/aspeed: Introduce a new aspeed_2700_intc0_ops for INTC0 Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 04/18] hw/intc/aspeed: Support setting different memory and register size Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 05/18] hw/intc/aspeed: Introduce helper functions for enable and status registers Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via [this message]
2025-01-21 7:04 ` [PATCH v1 06/18] hw/intc/aspeed: Introduce AspeedINTCIRQ structure to save the irq index and register address Jamin Lin via
2025-01-30 3:55 ` Andrew Jeffery
2025-02-04 9:45 ` Jamin Lin
2025-01-21 7:04 ` [PATCH v1 07/18] hw/intc/aspeed: Introduce IRQ handler function to reduce code duplication Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 08/18] hw/intc/aspeed: Add Support for Multi-Output IRQ Handling Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 09/18] hw/intc/aspeed: Add ID to trace events for better debugging Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 10/18] hw/intc/aspeed: Add Support for AST2700 INTC1 Controller Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 11/18] hw/misc/aspeed_scu: Add Support for AST2700/AST2750 A1 Silicon Revisions Jamin Lin via
2025-01-30 4:05 ` Andrew Jeffery
2025-02-04 7:23 ` Jamin Lin
2025-02-04 7:29 ` Cédric Le Goater
2025-01-21 7:04 ` [PATCH v1 12/18] hw/arm/aspeed_ast27x0: Support two levels of INTC controllers for AST2700 A1 Jamin Lin via
2025-01-30 4:19 ` Andrew Jeffery
2025-02-04 9:43 ` Jamin Lin
2025-02-05 3:50 ` Andrew Jeffery
2025-02-05 7:12 ` Jamin Lin
2025-02-05 23:39 ` Andrew Jeffery
2025-02-06 4:55 ` Joel Stanley
2025-02-06 5:15 ` Jamin Lin
2025-02-06 7:17 ` Cédric Le Goater
2025-02-06 7:22 ` Jamin Lin
2025-02-06 7:22 ` Cédric Le Goater
2025-02-06 7:24 ` Jamin Lin
2025-01-21 7:04 ` [PATCH v1 13/18] hw/arm/aspeed: Rename IRQ table and machine name for AST2700 A0 Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 14/18] hw/arm/aspeed: Add SoC and Machine Support for AST2700 A1 Jamin Lin via
2025-01-30 4:22 ` Andrew Jeffery
2025-02-03 8:55 ` Jamin Lin
2025-01-21 7:04 ` [PATCH v1 15/18] hw/misc/aspeed_hace: Fix coding style Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-21 7:04 ` [PATCH v1 16/18] hw/misc/aspeed_hace: Add AST2700 support Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-30 4:30 ` Andrew Jeffery
2025-01-21 7:04 ` [PATCH v1 17/18] hw/arm/aspeed_ast27x0: Add HACE support for AST2700 Jamin Lin via
2025-01-30 4:32 ` Andrew Jeffery
2025-01-21 7:04 ` [PATCH v1 18/18] hw/misc/aspeed_hace: (DROP) Fix boot issue in the Crypto Manager Self Test(WORKAROUND) Jamin Lin via
2025-01-21 7:04 ` Jamin Lin via
2025-01-31 7:34 ` [PATCH v1 00/18] Support AST2700 A1 Cédric Le Goater
2025-02-04 8:05 ` Jamin Lin
2025-06-30 20:28 ` Cédric Le Goater
2025-07-02 1:57 ` Jamin Lin
2025-07-02 6:43 ` Cédric Le Goater
2025-07-03 7:43 ` Jamin Lin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250121070424.2465942-7-jamin_lin@aspeedtech.com \
--to=qemu-arm@nongnu.org \
--cc=andrew@codeconstruct.com.au \
--cc=clg@kaod.org \
--cc=jamin_lin@aspeedtech.com \
--cc=joel@jms.id.au \
--cc=leetroy@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=steven_lee@aspeedtech.com \
--cc=troy_lee@aspeedtech.com \
--cc=yunlin.tang@aspeedtech.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.