irq: multilevel: add APIs with level as argument

Add APIs that accept an additional `level` argument, and use
that to call the respective functions. In some cases this can
reduce code complexity, especially when the level isn't known
at build time.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
This commit is contained in:
Yong Cong Sin 2024-01-26 12:45:40 +08:00 committed by Johan Hedberg
commit dcaf217336
2 changed files with 77 additions and 0 deletions

View file

@ -12,6 +12,7 @@
#define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_
#ifndef _ASMLANGUAGE
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/types.h>
@ -166,6 +167,76 @@ static inline unsigned int irq_parent_level_3(unsigned int irq)
BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS);
}
/**
* @brief Return the interrupt number for a given level
*
* @param irq IRQ number in its zephyr format
* @param level IRQ level
*
* @return IRQ number in the level
*/
static inline unsigned int irq_from_level(unsigned int irq, unsigned int level)
{
if (level == 1) {
return irq;
} else if (level == 2) {
return irq_from_level_2(irq);
} else if (level == 3) {
return irq_from_level_3(irq);
}
/* level is higher than 3 */
__ASSERT_NO_MSG(false);
return irq;
}
/**
* @brief Converts irq from level 1 to to a given level
*
* @param irq IRQ number in its zephyr format
* @param level IRQ level
*
* @return Converted IRQ number in the level
*/
static inline unsigned int irq_to_level(unsigned int irq, unsigned int level)
{
if (level == 1) {
return irq;
} else if (level == 2) {
return irq_to_level_2(irq);
} else if (level == 3) {
return irq_to_level_3(irq);
}
/* level is higher than 3 */
__ASSERT_NO_MSG(false);
return irq;
}
/**
* @brief Returns the parent IRQ of the given level raw IRQ number
*
* @param irq IRQ number in its zephyr format
* @param level IRQ level
*
* @return IRQ parent of the given level
*/
static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level)
{
if (level == 1) {
/* doesn't really make sense, but return anyway */
return irq;
} else if (level == 2) {
return irq_parent_level_2(irq);
} else if (level == 3) {
return irq_parent_level_3(irq);
}
/* level is higher than 3 */
__ASSERT_NO_MSG(false);
return irq;
}
/**
* @brief Returns the parent interrupt controller IRQ of the given IRQ number
*

View file

@ -415,14 +415,20 @@ static void test_multi_level_bit_masks_fn(uint32_t irq1, uint32_t irq2, uint32_t
if (has_l2) {
zassert_equal(hwirq2, irq_from_level_2(irqn));
zassert_equal(hwirq2, irq_from_level(irqn, 2));
zassert_equal((hwirq2 + 1) << l2_shift, irq_to_level_2(hwirq2));
zassert_equal((hwirq2 + 1) << l2_shift, irq_to_level(hwirq2, 2));
zassert_equal(hwirq1, irq_parent_level_2(irqn));
zassert_equal(hwirq1, irq_parent_level(irqn, 2));
}
if (has_l3) {
zassert_equal(hwirq3, irq_from_level_3(irqn));
zassert_equal(hwirq3, irq_from_level(irqn, 3));
zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level_3(hwirq3));
zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level(hwirq3, 3));
zassert_equal(hwirq2 + 1, irq_parent_level_3(irqn));
zassert_equal(hwirq2 + 1, irq_parent_level(irqn, 3));
}
if (has_l3) {