This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 79ce1647da2 arch/arm: GPIO IMX9 Add support for IRQ line1 and GPIO5
79ce1647da2 is described below

commit 79ce1647da21d018da7fe60534341d9ecc0f2dd6
Author: Peter van der Perk <[email protected]>
AuthorDate: Wed Jan 28 11:07:35 2026 +0100

    arch/arm: GPIO IMX9 Add support for IRQ line1 and GPIO5
    
    Adds support to select irq line 1 to share the same GPIO with Linux
    Also added GPIO5 definiton for IRQ
    
    Signed-off-by: Peter van der Perk <[email protected]>
---
 arch/arm/include/imx9/chip.h     |   2 +-
 arch/arm/src/imx9/Kconfig        | 100 +++++++++++++++++++++++++++++++
 arch/arm/src/imx9/imx9_gpio.c    |   5 ++
 arch/arm/src/imx9/imx9_gpioirq.c | 126 +++++++++++++++++++++++++++++++++++++--
 4 files changed, 227 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/imx9/chip.h b/arch/arm/include/imx9/chip.h
index 0b46efc3827..466b45451c0 100644
--- a/arch/arm/include/imx9/chip.h
+++ b/arch/arm/include/imx9/chip.h
@@ -47,6 +47,6 @@
 #define NVIC_SYSH_PRIORITY_MAX        0x00 /* Zero is maximum priority */
 #define NVIC_SYSH_PRIORITY_STEP       0x40 /* Two bits of interrupt pri used */
 
-#define IMX9_GPIO_NPORTS          4
+#define IMX9_GPIO_NPORTS          5
 
 #endif /* __ARCH_ARM_INCLUDE_IMX9_CHIP_H */
diff --git a/arch/arm/src/imx9/Kconfig b/arch/arm/src/imx9/Kconfig
index 32d52ce3043..0fe2d362e41 100644
--- a/arch/arm/src/imx9/Kconfig
+++ b/arch/arm/src/imx9/Kconfig
@@ -382,18 +382,118 @@ config IMX9_GPIO1_IRQ
        bool "GPIO1 Interrupt"
        default n
 
+choice
+       prompt "GPIO1 IRQ output select"
+       depends on IMX9_GPIO1_IRQ
+       default IMX9_GPIO1_IRQ_OUT_LINE1
+       ---help---
+               Each IMX9 GPIO controller provides two IRQ output lines. These
+               lines may be shared with other cores or domains in the SoC
+               (e.g. A55 vs M7), so selecting the correct line avoids 
conflicts.
+
+               By default this subsystem uses IRQ line 1, leaving line 0 
available
+               for the A55 or other system components that typically rely on 
it.
+
+config IMX9_GPIO1_IRQ_OUT_LINE0
+       bool "Use GPIO1 IRQ line 0"
+
+config IMX9_GPIO1_IRQ_OUT_LINE1
+       bool "Use GPIO1 IRQ line 1"
+endchoice
+
 config IMX9_GPIO2_IRQ
        bool "GPIO2 Interrupt"
        default n
 
+choice
+       prompt "GPIO2 IRQ output select"
+       depends on IMX9_GPIO2_IRQ
+       default IMX9_GPIO2_IRQ_OUT_LINE1
+       ---help---
+               Each IMX9 GPIO controller provides two IRQ output lines. These
+               lines may be shared with other cores or domains in the SoC
+               (e.g. A55 vs M7), so selecting the correct line avoids 
conflicts.
+
+               By default this subsystem uses IRQ line 1, leaving line 0 
available
+               for the A55 or other system components that typically rely on 
it.
+
+config IMX9_GPIO2_IRQ_OUT_LINE0
+       bool "Use GPIO2 IRQ line 0"
+
+config IMX9_GPIO2_IRQ_OUT_LINE1
+       bool "Use GPIO2 IRQ line 1"
+endchoice
+
 config IMX9_GPIO3_IRQ
        bool "GPIO3 Interrupt"
        default n
 
+choice
+       prompt "GPIO3 IRQ output select"
+       depends on IMX9_GPIO3_IRQ
+       default IMX9_GPIO3_IRQ_OUT_LINE1
+       ---help---
+               Each IMX9 GPIO controller provides two IRQ output lines. These
+               lines may be shared with other cores or domains in the SoC
+               (e.g. A55 vs M7), so selecting the correct line avoids 
conflicts.
+
+               By default this subsystem uses IRQ line 1, leaving line 0 
available
+               for the A55 or other system components that typically rely on 
it.
+
+config IMX9_GPIO3_IRQ_OUT_LINE0
+       bool "Use GPIO3 IRQ line 0"
+
+config IMX9_GPIO3_IRQ_OUT_LINE1
+       bool "Use GPIO3 IRQ line 1"
+endchoice
+
 config IMX9_GPIO4_IRQ
        bool "GPIO4 Interrupt"
        default n
 
+choice
+       prompt "GPIO4 IRQ output select"
+       depends on IMX9_GPIO4_IRQ
+       default IMX9_GPIO4_IRQ_OUT_LINE1
+       ---help---
+               Each IMX9 GPIO controller provides two IRQ output lines. These
+               lines may be shared with other cores or domains in the SoC
+               (e.g. A55 vs M7), so selecting the correct line avoids 
conflicts.
+
+               By default this subsystem uses IRQ line 1, leaving line 0 
available
+               for the A55 or other system components that typically rely on 
it.
+
+config IMX9_GPIO4_IRQ_OUT_LINE0
+       bool "Use GPIO4 IRQ line 0"
+
+config IMX9_GPIO4_IRQ_OUT_LINE1
+       bool "Use GPIO4 IRQ line 1"
+endchoice
+
+config IMX9_GPIO5_IRQ
+       bool "GPIO5 Interrupt"
+       default n
+
+choice
+       prompt "GPIO5 IRQ output select"
+       depends on IMX9_GPIO5_IRQ
+       default IMX9_GPIO5_IRQ_OUT_LINE1
+       ---help---
+               Each IMX9 GPIO controller provides two IRQ output lines. These
+               lines may be shared with other cores or domains in the SoC
+               (e.g. A55 vs M7), so selecting the correct line avoids 
conflicts.
+
+               By default this subsystem uses IRQ line 1, leaving line 0 
available
+               for the A55 or other system components that typically rely on 
it.
+
+config IMX9_GPIO5_IRQ_OUT_LINE0
+       bool "Use GPIO5 IRQ line 0"
+
+config IMX9_GPIO5_IRQ_OUT_LINE1
+       bool "Use GPIO5 IRQ line 1"
+endchoice
+
+
 endmenu # GPIO Interrupt Configuration
 
 config IMX9_LPI2C
diff --git a/arch/arm/src/imx9/imx9_gpio.c b/arch/arm/src/imx9/imx9_gpio.c
index 60e20c36e8b..346bf3c95aa 100644
--- a/arch/arm/src/imx9/imx9_gpio.c
+++ b/arch/arm/src/imx9/imx9_gpio.c
@@ -124,9 +124,14 @@ static int imx9_gpio_configinput(gpio_pinset_t pinset)
 {
   uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
   uint32_t pin  = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+  uint32_t reg;
 
   DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS);
 
+  reg = getreg32(IMX9_GPIO_PCNS(port));
+  reg &= ~(1 << pin);
+  putreg32(reg, IMX9_GPIO_PCNS(port));
+
   /* Configure pin as in input */
 
   imx9_gpio_dirin(port, pin);
diff --git a/arch/arm/src/imx9/imx9_gpioirq.c b/arch/arm/src/imx9/imx9_gpioirq.c
index b040ffd5dd9..e2118b83327 100644
--- a/arch/arm/src/imx9/imx9_gpioirq.c
+++ b/arch/arm/src/imx9/imx9_gpioirq.c
@@ -68,6 +68,66 @@ static struct imx9_portisr_s g_isrtab[IMX9_GPIO_NPORTS];
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: imx9_get_irqline_for_port
+ *
+ * Description:
+ *   iMX9 has two interrupt sources for each pin, this function fetches
+ *   which line is configured for a given port
+ *
+ ****************************************************************************/
+
+static inline uint32_t imx9_get_irqline_for_port(uint32_t port)
+{
+    switch (port)
+      {
+        case GPIO1:
+#ifdef CONFIG_IMX9_GPIO1_IRQ_OUT_LINE0
+          return 0;
+#elif defined(CONFIG_IMX9_GPIO1_IRQ_OUT_LINE1)
+          return 1;
+#endif
+        break;
+
+      case GPIO2:
+#ifdef CONFIG_IMX9_GPIO2_IRQ_OUT_LINE0
+        return 0;
+#elif defined(CONFIG_IMX9_GPIO2_IRQ_OUT_LINE1)
+        return 1;
+#endif
+      break;
+
+      case GPIO3:
+#ifdef CONFIG_IMX9_GPIO3_IRQ_OUT_LINE0
+        return 0;
+#elif defined(CONFIG_IMX9_GPIO3_IRQ_OUT_LINE1)
+        return 1;
+#endif
+      break;
+
+      case GPIO4:
+#ifdef CONFIG_IMX9_GPIO4_IRQ_OUT_LINE0
+        return 0;
+#elif defined(CONFIG_IMX9_GPIO4_IRQ_OUT_LINE1)
+        return 1;
+#endif
+      break;
+
+      case GPIO5:
+#ifdef CONFIG_IMX9_GPIO5_IRQ_OUT_LINE0
+        return 0;
+#elif defined(CONFIG_IMX9_GPIO5_IRQ_OUT_LINE1)
+        return 1;
+#endif
+      break;
+
+      default:
+        return 0;
+      }
+
+    return 0;
+}
+
 /****************************************************************************
  * Name: imx9_gpio_interrupt
  *
@@ -86,7 +146,15 @@ static int imx9_gpio_interrupt(int irq, void *context, void 
*arg)
 
   /* Get the pending interrupt indications */
 
-  regaddr = IMX9_GPIO_ISFR0(port);
+  if (imx9_get_irqline_for_port(port))
+    {
+      regaddr = IMX9_GPIO_ISFR1(port);
+    }
+  else
+    {
+      regaddr = IMX9_GPIO_ISFR0(port);
+    }
+
   status  = getreg32(regaddr);
 
   /* Decode the pending interrupts */
@@ -170,31 +238,70 @@ void imx9_gpioirq_initialize(void)
   up_disable_irq(IMX9_IRQ_GPIO4_0);
   up_disable_irq(IMX9_IRQ_GPIO4_1);
 
+  up_disable_irq(IMX9_IRQ_GPIO5_0);
+  up_disable_irq(IMX9_IRQ_GPIO5_1);
+
   /* Attach the common GPIO interrupt handler and enable the interrupt */
 
-#ifdef CONFIG_IMX9_GPIO1_IRQ
+#ifdef CONFIG_IMX9_GPIO1_IRQ_OUT_LINE0
   DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_0,
                          imx9_gpio_interrupt, (void *)GPIO_PORT1));
   up_enable_irq(IMX9_IRQ_GPIO1_0);
 #endif
 
-#ifdef CONFIG_IMX9_GPIO2_IRQ
+#ifdef CONFIG_IMX9_GPIO1_IRQ_OUT_LINE0
+  DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_1,
+                         imx9_gpio_interrupt, (void *)GPIO_PORT1));
+  up_enable_irq(IMX9_IRQ_GPIO1_1);
+#endif
+
+#ifdef CONFIG_IMX9_GPIO2_IRQ_OUT_LINE0
   DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_0,
                          imx9_gpio_interrupt, (void *)GPIO_PORT2));
   up_enable_irq(IMX9_IRQ_GPIO2_0);
 #endif
 
-#ifdef CONFIG_IMX9_GPIO3_IRQ
+#ifdef CONFIG_IMX9_GPIO2_IRQ_OUT_LINE1
+  DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_1,
+                         imx9_gpio_interrupt, (void *)GPIO_PORT2));
+  up_enable_irq(IMX9_IRQ_GPIO2_1);
+#endif
+
+#ifdef CONFIG_IMX9_GPIO3_IRQ_OUT_LINE0
   DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_0,
                          imx9_gpio_interrupt, (void *)GPIO_PORT3));
   up_enable_irq(IMX9_IRQ_GPIO3_0);
 #endif
 
-#ifdef CONFIG_IMX9_GPIO4_IRQ
+#ifdef CONFIG_IMX9_GPIO3_IRQ_OUT_LINE1
+  DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_1,
+                         imx9_gpio_interrupt, (void *)GPIO_PORT3));
+  up_enable_irq(IMX9_IRQ_GPIO3_1);
+#endif
+
+#ifdef CONFIG_IMX9_GPIO4_IRQ_OUT_LINE0
   DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_0,
                          imx9_gpio_interrupt, (void *)GPIO_PORT4));
   up_enable_irq(IMX9_IRQ_GPIO4_0);
 #endif
+
+#ifdef CONFIG_IMX9_GPIO4_IRQ_OUT_LINE1
+  DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_1,
+                         imx9_gpio_interrupt, (void *)GPIO_PORT4));
+  up_enable_irq(IMX9_IRQ_GPIO4_1);
+#endif
+
+#ifdef CONFIG_IMX9_GPIO5_IRQ_OUT_LINE0
+  DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO5_0,
+                         imx9_gpio_interrupt, (void *)GPIO_PORT5));
+  up_enable_irq(IMX9_IRQ_GPIO5_0);
+#endif
+
+#ifdef CONFIG_IMX9_GPIO5_IRQ_OUT_LINE1
+  DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO5_1,
+                         imx9_gpio_interrupt, (void *)GPIO_PORT5));
+  up_enable_irq(IMX9_IRQ_GPIO5_1);
+#endif
 }
 
 /****************************************************************************
@@ -258,6 +365,10 @@ int imx9_gpioirq_enable(gpio_pinset_t pinset)
   uint32_t  regval;
   uintptr_t regaddr;
 
+  regval = getreg32(IMX9_GPIO_ICNS(port));
+  regval &= ~(1 << (imx9_get_irqline_for_port(port)));
+  putreg32(regval, IMX9_GPIO_ICNS(port));
+
   /* Perform RMW to the specific pin */
 
   regaddr = IMX9_GPIO_ICRN(port, pin);
@@ -285,6 +396,11 @@ int imx9_gpioirq_enable(gpio_pinset_t pinset)
       regval |= IMX9_GPIO_ICRN_FALLING;
     }
 
+  if (imx9_get_irqline_for_port(port))
+    {
+      regval |= IMX9_GPIO_ICRN_IRQS;
+    }
+
   putreg32(regval, regaddr);
   return OK;
 }

Reply via email to