diff mbox series

[v2,1/2] irqdomain: support three-cell scheme interrupts

Message ID 20250302-04-gpio-irq-threecell-v2-1-34f13ad37ea4@gentoo.org
State New
Headers show
Series [v2,1/2] irqdomain: support three-cell scheme interrupts | expand

Commit Message

Yixun Lan March 1, 2025, 11:15 p.m. UTC
The is a prerequisite patch to support parsing three-cell
interrupts which encoded as <instance hwirq irqflag>,
the translate function will always retrieve irq number and
flag from last two cells.

In this patch, we introduce a generic interrupt cells translation
function, others functions will be inline version.

Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
 include/linux/irqdomain.h | 37 +++++++++++++++++++++++--------
 kernel/irq/irqdomain.c    | 56 +++++++++++++++++++----------------------------
 2 files changed, 50 insertions(+), 43 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index e432b6a12a32f9f16ec1ea2fa8e24a649d55caae..d96796263a2e177140f928cb369656a44dd45dda 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -572,15 +572,34 @@  int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
 			const u32 *intspec, unsigned int intsize,
 			irq_hw_number_t *out_hwirq, unsigned int *out_type);
 
-int irq_domain_translate_twocell(struct irq_domain *d,
-				 struct irq_fwspec *fwspec,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type);
-
-int irq_domain_translate_onecell(struct irq_domain *d,
-				 struct irq_fwspec *fwspec,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type);
+int irq_domain_translate_cells(struct irq_domain *d,
+			       struct irq_fwspec *fwspec,
+			       unsigned long *out_hwirq,
+			       unsigned int *out_type);
+
+static inline int irq_domain_translate_onecell(struct irq_domain *d,
+					       struct irq_fwspec *fwspec,
+					       unsigned long *out_hwirq,
+					       unsigned int *out_type)
+{
+	return irq_domain_translate_cells(d, fwspec, out_hwirq, out_type);
+}
+
+static inline int irq_domain_translate_twocell(struct irq_domain *d,
+					       struct irq_fwspec *fwspec,
+					       unsigned long *out_hwirq,
+					       unsigned int *out_type)
+{
+	return irq_domain_translate_cells(d, fwspec, out_hwirq, out_type);
+}
+
+static inline int irq_domain_translate_threecell(struct irq_domain *d,
+						 struct irq_fwspec *fwspec,
+						 unsigned long *out_hwirq,
+						 unsigned int *out_type)
+{
+	return irq_domain_translate_cells(d, fwspec, out_hwirq, out_type);
+}
 
 /* IPI functions */
 int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index ec6d8e72d980f604ded2bfa2143420e0e0095920..8d3b357b7dedbb2c274d4761c315e430b1d35610 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1171,50 +1171,38 @@  const struct irq_domain_ops irq_domain_simple_ops = {
 EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
 
 /**
- * irq_domain_translate_onecell() - Generic translate for direct one cell
+ * irq_domain_translate_cells() - Generic translate for up to three cells
  * bindings
  * @d:		Interrupt domain involved in the translation
  * @fwspec:	The firmware interrupt specifier to translate
  * @out_hwirq:	Pointer to storage for the hardware interrupt number
  * @out_type:	Pointer to storage for the interrupt type
  */
-int irq_domain_translate_onecell(struct irq_domain *d,
-				 struct irq_fwspec *fwspec,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type)
+int irq_domain_translate_cells(struct irq_domain *d,
+			       struct irq_fwspec *fwspec,
+			       unsigned long *out_hwirq,
+			       unsigned int *out_type)
 {
-	if (WARN_ON(fwspec->param_count < 1))
-		return -EINVAL;
-	*out_hwirq = fwspec->param[0];
-	*out_type = IRQ_TYPE_NONE;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(irq_domain_translate_onecell);
+	unsigned int cells = fwspec->param_count;
 
-/**
- * irq_domain_translate_twocell() - Generic translate for direct two cell
- * bindings
- * @d:		Interrupt domain involved in the translation
- * @fwspec:	The firmware interrupt specifier to translate
- * @out_hwirq:	Pointer to storage for the hardware interrupt number
- * @out_type:	Pointer to storage for the interrupt type
- *
- * Device Tree IRQ specifier translation function which works with two cell
- * bindings where the cell values map directly to the hwirq number
- * and linux irq flags.
- */
-int irq_domain_translate_twocell(struct irq_domain *d,
-				 struct irq_fwspec *fwspec,
-				 unsigned long *out_hwirq,
-				 unsigned int *out_type)
-{
-	if (WARN_ON(fwspec->param_count < 2))
+	switch (cells) {
+	case 1:
+		*out_hwirq = fwspec->param[0];
+		*out_type = IRQ_TYPE_NONE;
+		return 0;
+	case 2 ... 3:
+		/*
+		 * For multi cell translations the hardware interrupt number
+		 * and type are in the last two cells.
+		 */
+		*out_hwirq = fwspec->param[cells - 2];
+		*out_type = fwspec->param[cells - 1] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	default:
 		return -EINVAL;
-	*out_hwirq = fwspec->param[0];
-	*out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
-	return 0;
+	}
 }
-EXPORT_SYMBOL_GPL(irq_domain_translate_twocell);
+EXPORT_SYMBOL_GPL(irq_domain_translate_cells);
 
 int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
 			   int node, const struct irq_affinity_desc *affinity)