@@ -91,11 +91,36 @@ static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
qemu_set_irq(s->output_pins[outpin_idx], level);
}
+static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
+ const AspeedINTCIRQ *irq, uint32_t select)
+{
+ 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.
+ * b. status register value is not 0 means previous
+ * source interrupt does not be executed, yet.
+ *
+ * save source interrupt to pending variable.
+ */
+ 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[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);
+ }
+}
+
/*
- * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
- * Utilize "address & 0x0f00" to get the irq and irq output pin index
- * The value of irq should be 0 to num_ints.
- * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
+ * GICINT128 to GICINT136 map 1:1 to input and output IRQs 0 to 8.
+ * The value of input IRQ should be between 0 and the number of inputs.
*/
static void aspeed_intc_set_irq(void *opaque, int irq_idx, int level)
{
@@ -136,28 +161,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq_idx, int level)
trace_aspeed_intc_select(select);
- 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.
- * b. status register value is not 0 means previous
- * source interrupt does not be executed, yet.
- *
- * save source interrupt to pending variable.
- */
- 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[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);
- }
+ aspeed_intc_set_irq_handler(s, irq, select);
}
static void aspeed_2700_intc_enable_handler(AspeedINTCState *s, uint32_t addr,
The behavior of the INTC set IRQ is almost identical between INTC0 and INTC1. To reduce duplicated code, introduce the `aspeed_intc_set_irq_handler` function to handle both INTC0 and INTC1 IRQ behavior. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> --- hw/intc/aspeed_intc.c | 56 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 26 deletions(-)