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;
}