api: irq: Add Multi-level IRQ utility functions
This adds utility functions to irq.h in accordance with zephyr's multi-level irq numbering schema. Functions that are added will get the zephyr IRQs level and provide function to return the interrupt number at a particular level. Fixes issue #20338 Signed-off-by: Jaron Kelleher <jkelleher@fb.com>
This commit is contained in:
parent
b173c177db
commit
c6fd99d048
2 changed files with 106 additions and 23 deletions
|
@ -252,6 +252,104 @@ void z_smp_global_unlock(unsigned int key);
|
|||
#define irq_unlock(key) arch_irq_unlock(key)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return IRQ level
|
||||
* @def irq_get_level()
|
||||
*
|
||||
* This routine returns the interrupt level number of the provided interrupt.
|
||||
*
|
||||
* @param irq IRQ number in its zephyr format
|
||||
*
|
||||
* @return 1 if IRQ level 1, 2 if IRQ level 2, 3 if IRQ level 3
|
||||
*/
|
||||
static inline unsigned int irq_get_level(unsigned int irq)
|
||||
{
|
||||
#if defined(CONFIG_3RD_LEVEL_INTERRUPTS)
|
||||
return ((irq >> 16) & 0xFF) != 0 ? 3 :
|
||||
(((irq >> 8) & 0xFF) == 0 ? 1 : 2);
|
||||
#elif defined(CONFIG_2ND_LEVEL_INTERRUPTS)
|
||||
return ((irq >> 8) & 0xFF) == 0 ? 1 : 2;
|
||||
#else
|
||||
ARG_UNUSED(irq);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_2ND_LEVEL_INTERRUPTS
|
||||
/**
|
||||
* @brief Return the 2nd level interrupt number
|
||||
* @def irq_from_level_2()
|
||||
*
|
||||
* This routine returns the second level irq number of the zephyr irq
|
||||
* number passed in
|
||||
*
|
||||
* @param irq IRQ number in its zephyr format
|
||||
*
|
||||
* @return 2nd level IRQ number
|
||||
*/
|
||||
static inline unsigned int irq_from_level_2(unsigned int irq)
|
||||
{
|
||||
#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
|
||||
return ((irq >> 8) & 0xFF) - 1;
|
||||
#else
|
||||
return (irq >> 8) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts irq from level 1 to level 2 format
|
||||
* @def irq_to_level_2()
|
||||
*
|
||||
* This routine converts the input into the level 2 irq number format
|
||||
*
|
||||
* @note Values >= 0xFF are invalid
|
||||
*
|
||||
* @param irq IRQ number in its zephyr format
|
||||
*
|
||||
* @return 2nd level IRQ number
|
||||
*/
|
||||
static inline unsigned int irq_to_level_2(unsigned int irq)
|
||||
{
|
||||
return (irq + 1) << 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
|
||||
/**
|
||||
* @brief Return the 3rd level interrupt number
|
||||
* @def irq_from_level_3()
|
||||
*
|
||||
* This routine returns the third level irq number of the zephyr irq
|
||||
* number passed in
|
||||
*
|
||||
* @param irq IRQ number in its zephyr format
|
||||
*
|
||||
* @return 3rd level IRQ number
|
||||
*/
|
||||
static inline unsigned int irq_from_level_3(unsigned int irq)
|
||||
{
|
||||
return (irq >> 16) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts irq from level 1 to level 3 format
|
||||
* @def irq_to_level_3()
|
||||
*
|
||||
* This routine converts the input into the level 3 irq number format
|
||||
*
|
||||
* @note Values >= 0xFF are invalid
|
||||
*
|
||||
* @param irq IRQ number in its zephyr format
|
||||
*
|
||||
* @return 3nd level IRQ number
|
||||
*/
|
||||
static inline unsigned int irq_to_level_3(unsigned int irq)
|
||||
{
|
||||
return (irq + 1) << 16;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable an IRQ.
|
||||
*
|
||||
|
|
|
@ -11,30 +11,15 @@
|
|||
*/
|
||||
#include <irq.h>
|
||||
|
||||
/**
|
||||
* @brief Get an IRQ's level
|
||||
* @param irq The IRQ number in the Zephyr irq.h numbering system
|
||||
* @return IRQ level, either 1 or 2
|
||||
*/
|
||||
static inline unsigned int _irq_level(unsigned int irq)
|
||||
{
|
||||
return ((irq >> 8) & 0xff) == 0U ? 1 : 2;
|
||||
}
|
||||
|
||||
static inline unsigned int _level2_irq(unsigned int irq)
|
||||
{
|
||||
return (irq >> 8) - 1;
|
||||
}
|
||||
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
u32_t mie;
|
||||
|
||||
#if defined(CONFIG_RISCV_HAS_PLIC)
|
||||
unsigned int level = _irq_level(irq);
|
||||
unsigned int level = irq_get_level(irq);
|
||||
|
||||
if (level == 2) {
|
||||
irq = _level2_irq(irq);
|
||||
irq = irq_from_level_2(irq);
|
||||
riscv_plic_irq_enable(irq);
|
||||
return;
|
||||
}
|
||||
|
@ -54,10 +39,10 @@ void arch_irq_disable(unsigned int irq)
|
|||
u32_t mie;
|
||||
|
||||
#if defined(CONFIG_RISCV_HAS_PLIC)
|
||||
unsigned int level = _irq_level(irq);
|
||||
unsigned int level = irq_get_level(irq);
|
||||
|
||||
if (level == 2) {
|
||||
irq = _level2_irq(irq);
|
||||
irq = irq_from_level_2(irq);
|
||||
riscv_plic_irq_disable(irq);
|
||||
return;
|
||||
}
|
||||
|
@ -75,10 +60,10 @@ void arch_irq_disable(unsigned int irq)
|
|||
void arch_irq_priority_set(unsigned int irq, unsigned int prio)
|
||||
{
|
||||
#if defined(CONFIG_RISCV_HAS_PLIC)
|
||||
unsigned int level = _irq_level(irq);
|
||||
unsigned int level = irq_get_level(irq);
|
||||
|
||||
if (level == 2) {
|
||||
irq = _level2_irq(irq);
|
||||
irq = irq_from_level_2(irq);
|
||||
riscv_plic_set_priority(irq, prio);
|
||||
}
|
||||
#endif
|
||||
|
@ -91,10 +76,10 @@ int arch_irq_is_enabled(unsigned int irq)
|
|||
u32_t mie;
|
||||
|
||||
#if defined(CONFIG_RISCV_HAS_PLIC)
|
||||
unsigned int level = _irq_level(irq);
|
||||
unsigned int level = irq_get_level(irq);
|
||||
|
||||
if (level == 2) {
|
||||
irq = _level2_irq(irq);
|
||||
irq = irq_from_level_2(irq);
|
||||
return riscv_plic_irq_is_enabled(irq);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue