From 2152b8e41403d0abf31709f61041fde86e89adef Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 30 Oct 2024 11:15:07 +0800 Subject: [PATCH] irq: multilevel: compile 3rd level IRQ APIs only when enabled This revert the idea of 3fa7d78 from #78845. The 3rd level IRQ APIs won't compile when CONFIG_3RD_LEVEL_INTERRUPT_BITS=0. Updated testcase accordingly. Signed-off-by: Yong Cong Sin Signed-off-by: Yong Cong Sin Signed-off-by: Yong Cong Sin --- include/zephyr/irq_multilevel.h | 56 ++++++++++++++----- tests/kernel/interrupt/src/multilevel_irq.c | 61 ++++++++++++++++----- tests/kernel/interrupt/testcase.yaml | 8 +++ 3 files changed, 99 insertions(+), 26 deletions(-) diff --git a/include/zephyr/irq_multilevel.h b/include/zephyr/irq_multilevel.h index dc18c3049b6..adb0ffefc91 100644 --- a/include/zephyr/irq_multilevel.h +++ b/include/zephyr/irq_multilevel.h @@ -32,15 +32,19 @@ typedef union _z_irq { uint32_t l1: CONFIG_1ST_LEVEL_INTERRUPT_BITS; /* Second level interrupt bits */ uint32_t l2: CONFIG_2ND_LEVEL_INTERRUPT_BITS; +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS /* Third level interrupt bits */ uint32_t l3: CONFIG_3RD_LEVEL_INTERRUPT_BITS; +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ } bits; +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS /* Third level IRQ's interrupt controller */ struct { /* IRQ of the third level interrupt aggregator */ uint32_t irq: CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS; } l3_intc; +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ /* Second level IRQ's interrupt controller */ struct { @@ -61,16 +65,20 @@ static inline uint32_t _z_l2_irq(_z_irq_t irq) return irq.bits.l2 - 1; } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS static inline uint32_t _z_l3_irq(_z_irq_t irq) { return irq.bits.l3 - 1; } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ static inline unsigned int _z_irq_get_level(_z_irq_t z_irq) { +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS if (z_irq.bits.l3 != 0) { return 3; } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ if (z_irq.bits.l2 != 0) { return 2; @@ -142,7 +150,9 @@ static inline unsigned int irq_to_level_2(unsigned int irq) .bits = { .l1 = 0, .l2 = irq + 1, +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS .l3 = 0, +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ }, }; @@ -168,6 +178,7 @@ static inline unsigned int irq_parent_level_2(unsigned int irq) return _z_l1_irq(z_irq); } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS /** * @brief Return the 3rd level interrupt number * @@ -241,6 +252,7 @@ static inline unsigned int irq_parent_level_3(unsigned int irq) return _z_l2_irq(z_irq); } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ /** * @brief Return the interrupt number for a given level @@ -256,11 +268,14 @@ static inline unsigned int irq_from_level(unsigned int irq, unsigned int level) return irq; } else if (level == 2) { return irq_from_level_2(irq); - } else if (level == 3) { + } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + else if (level == 3) { return irq_from_level_3(irq); } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - /* level is higher than 3 */ + /* level is higher than what's supported */ __ASSERT_NO_MSG(false); return irq; } @@ -279,11 +294,14 @@ static inline unsigned int irq_to_level(unsigned int irq, unsigned int level) return irq; } else if (level == 2) { return irq_to_level_2(irq); - } else if (level == 3) { + } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + else if (level == 3) { return irq_to_level_3(irq); } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - /* level is higher than 3 */ + /* level is higher than what's supported */ __ASSERT_NO_MSG(false); return irq; } @@ -303,11 +321,14 @@ static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level return irq; } else if (level == 2) { return irq_parent_level_2(irq); - } else if (level == 3) { + } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + else if (level == 3) { return irq_parent_level_3(irq); } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - /* level is higher than 3 */ + /* level is higher than what's supported */ __ASSERT_NO_MSG(false); return irq; } @@ -322,19 +343,24 @@ static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level static inline unsigned int irq_get_intc_irq(unsigned int irq) { const unsigned int level = irq_get_level(irq); - - __ASSERT_NO_MSG(level <= 3); _z_irq_t z_irq = { .irq = irq, }; +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + __ASSERT_NO_MSG(level <= 3); if (level == 3) { return z_irq.l3_intc.irq; - } else if (level == 2) { - return z_irq.l2_intc.irq; - } else { - return irq; } +#else + __ASSERT_NO_MSG(level <= 2); +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + + if (level == 2) { + return z_irq.l2_intc.irq; + } + + return irq; } /** @@ -351,8 +377,12 @@ static inline unsigned int irq_increment(unsigned int irq, unsigned int val) .irq = irq, }; - if (z_irq.bits.l3 != 0) { + if (false) { + /* so that it evaluates the next condition */ +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + } else if (z_irq.bits.l3 != 0) { z_irq.bits.l3 += val; +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ } else if (z_irq.bits.l2 != 0) { z_irq.bits.l2 += val; } else { diff --git a/tests/kernel/interrupt/src/multilevel_irq.c b/tests/kernel/interrupt/src/multilevel_irq.c index 76dbd29b454..b73626bc1aa 100644 --- a/tests/kernel/interrupt/src/multilevel_irq.c +++ b/tests/kernel/interrupt/src/multilevel_irq.c @@ -12,18 +12,15 @@ ZTEST(interrupt_feature, test_multi_level_api) { /* Zephyr multilevel-encoded IRQ */ - const uint32_t irqn_l3 = DT_IRQN(DT_NODELABEL(test_l3_irq)); const uint32_t irqn_l2 = DT_IRQN(DT_NODELABEL(test_l2_irq)); const uint32_t irqn_l1 = DT_IRQN(DT_NODELABEL(test_l1_irq)); /* Raw IRQ specified in the devicetree */ - const uint32_t raw_l3 = DT_IRQ(DT_NODELABEL(test_l3_irq), irq); const uint32_t raw_l2 = DT_IRQ(DT_NODELABEL(test_l2_irq), irq); const uint32_t raw_l1 = DT_IRQ(DT_NODELABEL(test_l1_irq), irq); /** * - irq_get_level() */ - zassert_equal(3, irq_get_level(irqn_l3)); zassert_equal(2, irq_get_level(irqn_l2)); zassert_equal(1, irq_get_level(irqn_l1)); @@ -32,13 +29,59 @@ ZTEST(interrupt_feature, test_multi_level_api) * - irq_to_level_2() * - irq_parent_level_2() */ - zassert_equal(irq_from_level_2(irqn_l3), raw_l2); zassert_equal(irq_from_level_2(irqn_l2), raw_l2); zassert_equal(irq_to_level_2(raw_l2) & irqn_l2, irq_to_level_2(raw_l2)); zassert_equal(irq_parent_level_2(irqn_l2), raw_l1); + /** + * - irq_from_level() + * - irq_to_level() + * - irq_parent_level() + */ + zassert_equal(irq_from_level(irqn_l2, 2), raw_l2); + + zassert_equal(irq_to_level(raw_l2, 2) & irqn_l2, irq_to_level(raw_l2, 2)); + + zassert_equal(irq_parent_level(irqn_l2, 2), raw_l1); + + /** + * - irq_get_intc_irq() + */ + zassert_equal(irq_get_intc_irq(irqn_l2), irqn_l1); + zassert_equal(irq_get_intc_irq(irqn_l1), irqn_l1); + + 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); +} + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS +ZTEST(interrupt_feature, test_multi_level_api_l3) +{ + /* Zephyr multilevel-encoded IRQ */ + const uint32_t irqn_l2 = DT_IRQN(DT_NODELABEL(test_l2_irq)); + const uint32_t irqn_l3 = DT_IRQN(DT_NODELABEL(test_l3_irq)); + /* Raw IRQ specified in the devicetree */ + const uint32_t raw_l2 = DT_IRQ(DT_NODELABEL(test_l2_irq), irq); + const uint32_t raw_l3 = DT_IRQ(DT_NODELABEL(test_l3_irq), irq); + + /** + * - irq_get_level() + */ + zassert_equal(3, irq_get_level(irqn_l3)); + + /** + * - irq_from_level_2() + */ + zassert_equal(irq_from_level_2(irqn_l3), raw_l2); + /** * - irq_from_level_3() * - irq_to_level_3() @@ -56,32 +99,24 @@ ZTEST(interrupt_feature, test_multi_level_api) * - irq_parent_level() */ zassert_equal(irq_from_level(irqn_l3, 2), raw_l2); - zassert_equal(irq_from_level(irqn_l2, 2), raw_l2); zassert_equal(irq_from_level(irqn_l3, 3), raw_l3); - zassert_equal(irq_to_level(raw_l2, 2) & irqn_l2, irq_to_level(raw_l2, 2)); zassert_equal(irq_to_level(raw_l3, 3) & irqn_l3, irq_to_level(raw_l3, 3)); - zassert_equal(irq_parent_level(irqn_l2, 2), raw_l1); zassert_equal(irq_parent_level(irqn_l3, 3), raw_l2); /** * - irq_get_intc_irq() */ 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); } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ ZTEST_SUITE(gen_isr_table_multilevel, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/kernel/interrupt/testcase.yaml b/tests/kernel/interrupt/testcase.yaml index 1ed995c0baa..ec4afb7ab93 100644 --- a/tests/kernel/interrupt/testcase.yaml +++ b/tests/kernel/interrupt/testcase.yaml @@ -85,3 +85,11 @@ tests: - EXTRA_DTC_OVERLAY_FILE="multilevel_irq.overlay" extra_configs: - CONFIG_TEST_MULTILEVEL_IRQ=y + arch.interrupt.multilevel_l3: + filter: CONFIG_MULTI_LEVEL_INTERRUPTS + extra_args: + - EXTRA_DTC_OVERLAY_FILE="multilevel_irq.overlay" + extra_configs: + - CONFIG_TEST_MULTILEVEL_IRQ=y + - CONFIG_3RD_LEVEL_INTERRUPTS=y + - CONFIG_3RD_LEVEL_INTERRUPT_BITS=11