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>
diff --git a/include/irq.h b/include/irq.h
index 3dcec83..9a513cc 100644
--- a/include/irq.h
+++ b/include/irq.h
@@ -253,6 +253,104 @@
 #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.
  *
  * This routine enables interrupts from source @a irq.
diff --git a/soc/riscv/riscv-privilege/common/soc_common_irq.c b/soc/riscv/riscv-privilege/common/soc_common_irq.c
index ba33a25..6f4864f 100644
--- a/soc/riscv/riscv-privilege/common/soc_common_irq.c
+++ b/soc/riscv/riscv-privilege/common/soc_common_irq.c
@@ -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 @@
 	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_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 @@
 	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