irq: multilevel: add API to increment a multilevel IRQ
Unlike a normal IRQ, a multilevel IRQ can't be incremented by simply `irq++`, as that would always increment the L1 of a IRQ, regardless of its level. A function that understands the level for which the IRQ operates in is required. Signed-off-by: Yong Cong Sin <ycsin@meta.com> Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
parent
4b2f5c7de2
commit
8bfdff3cb1
3 changed files with 62 additions and 0 deletions
|
@ -333,6 +333,31 @@ static inline unsigned int irq_get_intc_irq(unsigned int irq)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increments the multilevel-encoded @a irq by @a val
|
||||
*
|
||||
* @param irq IRQ number in its zephyr format
|
||||
* @param val Amount to increment
|
||||
*
|
||||
* @return @a irq incremented by @a val
|
||||
*/
|
||||
static inline unsigned int irq_increment(unsigned int irq, unsigned int val)
|
||||
{
|
||||
_z_irq_t z_irq = {
|
||||
.irq = irq,
|
||||
};
|
||||
|
||||
if (z_irq.bits.l3 != 0) {
|
||||
z_irq.bits.l3 += val;
|
||||
} else if (z_irq.bits.l2 != 0) {
|
||||
z_irq.bits.l2 += val;
|
||||
} else {
|
||||
z_irq.bits.l1 += val;
|
||||
}
|
||||
|
||||
return z_irq.irq;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -40,5 +40,31 @@
|
|||
interrupt-parent = <&test_l2_irq>;
|
||||
interrupt-names = "test";
|
||||
};
|
||||
|
||||
test_l1_irq_inc: interrupt-controller@bbbbdccc {
|
||||
compatible = "vnd,intc";
|
||||
reg = <0xbbbbdccc 0x10>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <12 0>; /* +1 */
|
||||
interrupt-parent = <&test_cpu_intc>;
|
||||
};
|
||||
|
||||
test_l2_irq_inc: interrupt-controller@bbbbdcdc {
|
||||
compatible = "vnd,intc";
|
||||
reg = <0xbbbbdcdc 0x10>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <14 0>; /* +2 */
|
||||
interrupt-parent = <&test_l1_irq>;
|
||||
};
|
||||
|
||||
test_l3_irq_inc: interrupt-holder-inc {
|
||||
compatible = "vnd,interrupt-holder";
|
||||
status = "okay";
|
||||
interrupts = <16 3>; /* +3 */
|
||||
interrupt-parent = <&test_l2_irq>;
|
||||
interrupt-names = "test";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -71,6 +71,17 @@ ZTEST(interrupt_feature, test_multi_level_api)
|
|||
zassert_equal(irq_get_intc_irq(irqn_l3), irqn_l2);
|
||||
zassert_equal(irq_get_intc_irq(irqn_l2), irqn_l1);
|
||||
zassert_equal(irq_get_intc_irq(irqn_l1), irqn_l1);
|
||||
|
||||
const uint32_t irqn_l3_inc = DT_IRQN(DT_NODELABEL(test_l3_irq_inc));
|
||||
const uint32_t irqn_l2_inc = DT_IRQN(DT_NODELABEL(test_l2_irq_inc));
|
||||
const uint32_t irqn_l1_inc = DT_IRQN(DT_NODELABEL(test_l1_irq_inc));
|
||||
|
||||
/**
|
||||
* - irq_increment()
|
||||
*/
|
||||
zassert_equal(irq_increment(irqn_l1, 1), irqn_l1_inc);
|
||||
zassert_equal(irq_increment(irqn_l2, 2), irqn_l2_inc);
|
||||
zassert_equal(irq_increment(irqn_l3, 3), irqn_l3_inc);
|
||||
}
|
||||
|
||||
ZTEST_SUITE(gen_isr_table_multilevel, NULL, NULL, NULL, NULL, NULL);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue