@@ -42,20 +42,32 @@ REG32(GICINT136_STATUS, 0x804)
#define GICINT_STATUS_BASE R_GICINT128_STATUS
-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);
const char *name = object_get_typename(OBJECT(s));
- if (irq >= aic->num_inpins) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Invalid input pin index: %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;
}
- trace_aspeed_intc_update_irq(name, irq, level);
- qemu_set_irq(s->output_pins[irq], level);
+ 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(name, inpin_idx, outpin_idx, level);
+ qemu_set_irq(s->output_pins[outpin_idx], level);
}
/*
@@ -73,6 +85,11 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
uint32_t select = 0;
uint32_t enable;
int i;
+ int inpin_idx;
+ int outpin_idx;
+
+ inpin_idx = irq;
+ outpin_idx = irq;
if (irq >= aic->num_inpins) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n",
@@ -80,15 +97,15 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
return;
}
- trace_aspeed_intc_set_irq(name, irq, level);
- enable = s->enable[irq];
+ trace_aspeed_intc_set_irq(name, inpin_idx, level);
+ enable = s->enable[inpin_idx];
if (!level) {
return;
}
for (i = 0; i < aic->num_lines; i++) {
- if (s->orgates[irq].levels[i]) {
+ if (s->orgates[inpin_idx].levels[i]) {
if (enable & BIT(i)) {
select |= BIT(i);
}
@@ -101,7 +118,7 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level)
trace_aspeed_intc_select(name, select);
- if (s->mask[irq] || s->regs[status_addr]) {
+ if (s->mask[inpin_idx] || s->regs[status_addr]) {
/*
* a. mask is not 0 means in ISR mode
* sources interrupt routine are executing.
@@ -110,16 +127,17 @@ 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(name, irq, s->pending[irq]);
+ s->pending[inpin_idx] |= select;
+ trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
} else {
/*
* notify firmware which source interrupt are coming
* by setting status register
*/
s->regs[status_addr] = select;
- trace_aspeed_intc_trigger_irq(name, irq, s->regs[status_addr]);
- aspeed_intc_update(s, irq, 1);
+ trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+ s->regs[status_addr]);
+ aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
}
}
@@ -132,13 +150,15 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
uint32_t old_enable;
uint32_t change;
uint32_t irq;
+ int inpin_idx;
irq = (offset & 0x0f00) >> 8;
+ inpin_idx = irq;
- if (irq >= aic->num_inpins) {
+ if (inpin_idx >= aic->num_inpins) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid input pin index: %d\n",
- __func__, irq);
+ __func__, inpin_idx);
return;
}
@@ -149,17 +169,17 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
*/
/* disable all source interrupt */
- if (!data && !s->enable[irq]) {
+ if (!data && !s->enable[inpin_idx]) {
s->regs[addr] = data;
return;
}
- old_enable = s->enable[irq];
- s->enable[irq] |= data;
+ old_enable = s->enable[inpin_idx];
+ s->enable[inpin_idx] |= data;
/* enable new source interrupt */
- if (old_enable != s->enable[irq]) {
- trace_aspeed_intc_enable(name, s->enable[irq]);
+ if (old_enable != s->enable[inpin_idx]) {
+ trace_aspeed_intc_enable(name, s->enable[inpin_idx]);
s->regs[addr] = data;
return;
}
@@ -167,11 +187,11 @@ static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
/* mask and unmask source interrupt */
change = s->regs[addr] ^ data;
if (change & data) {
- s->mask[irq] &= ~change;
- trace_aspeed_intc_unmask(name, change, s->mask[irq]);
+ s->mask[inpin_idx] &= ~change;
+ trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]);
} else {
- s->mask[irq] |= change;
- trace_aspeed_intc_mask(name, change, s->mask[irq]);
+ s->mask[inpin_idx] |= change;
+ trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]);
}
s->regs[addr] = data;
@@ -184,6 +204,8 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
const char *name = object_get_typename(OBJECT(s));
uint32_t addr = offset >> 2;
uint32_t irq;
+ int inpin_idx;
+ int outpin_idx;
if (!data) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
@@ -191,11 +213,13 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
}
irq = (offset & 0x0f00) >> 8;
+ inpin_idx = irq;
+ outpin_idx = irq;
- if (irq >= aic->num_inpins) {
+ if (inpin_idx >= aic->num_inpins) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid input pin index: %d\n",
- __func__, irq);
+ __func__, inpin_idx);
return;
}
@@ -214,21 +238,22 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
/* All source ISR execution are done */
if (!s->regs[addr]) {
- trace_aspeed_intc_all_isr_done(name, irq);
- if (s->pending[irq]) {
+ trace_aspeed_intc_all_isr_done(name, inpin_idx);
+ if (s->pending[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(name, irq, s->regs[addr]);
- aspeed_intc_update(s, irq, 1);
+ s->regs[addr] = s->pending[inpin_idx];
+ s->pending[inpin_idx] = 0;
+ trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
+ s->regs[addr]);
+ aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
} else {
/* clear irq */
- trace_aspeed_intc_clear_irq(name, irq, 0);
- aspeed_intc_update(s, irq, 0);
+ trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0);
+ aspeed_intc_update(s, inpin_idx, outpin_idx, 0);
}
}
}
@@ -82,12 +82,12 @@ aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64
# aspeed_intc.c
aspeed_intc_read(const char *s, uint64_t offset, unsigned size, uint32_t value) "%s: From 0x%" PRIx64 " of size %u: 0x%" PRIx32
aspeed_intc_write(const char *s, uint64_t offset, unsigned size, uint32_t data) "%s: To 0x%" PRIx64 " of size %u: 0x%" PRIx32
-aspeed_intc_set_irq(const char *s, int irq, int level) "%s: Set IRQ %d: %d"
-aspeed_intc_clear_irq(const char *s, int irq, int level) "%s: Clear IRQ %d: %d"
-aspeed_intc_update_irq(const char *s, int irq, int level) "%s: Update IRQ: %d: %d"
-aspeed_intc_pending_irq(const char *s, int irq, uint32_t value) "%s: Pending IRQ: %d: 0x%x"
-aspeed_intc_trigger_irq(const char *s, int irq, uint32_t value) "%s: Trigger IRQ: %d: 0x%x"
-aspeed_intc_all_isr_done(const char *s, int irq) "%s: All source ISR execution are done: %d"
+aspeed_intc_set_irq(const char *s, int inpin_idx, int level) "%s: Set IRQ %d: %d"
+aspeed_intc_clear_irq(const char *s, int inpin_idx, int outpin_idx, int level) "%s: Clear IRQ %d-%d: %d"
+aspeed_intc_update_irq(const char *s, int inpin_idx, int outpin_idx, int level) "%s: Update IRQ: %d-%d: %d"
+aspeed_intc_pending_irq(const char *s, int inpin_idx, uint32_t value) "%s: Pending IRQ: %d: 0x%x"
+aspeed_intc_trigger_irq(const char *s, int inpin_idx, int outpin_idx, uint32_t value) "%s: Trigger IRQ: %d-%d: 0x%x"
+aspeed_intc_all_isr_done(const char *s, int inpin_idx) "%s: All source ISR execution are done: %d"
aspeed_intc_enable(const char *s, uint32_t value) "%s: Enable: 0x%x"
aspeed_intc_select(const char *s, uint32_t value) "%s: Select: 0x%x"
aspeed_intc_mask(const char *s, uint32_t change, uint32_t value) "%s: Mask: 0x%x: 0x%x"