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 <peter.vanderperk@nxp.com>
This commit is contained in:
Peter van der Perk 2026-01-28 11:07:35 +01:00 committed by Xiang Xiao
parent 99501bba9a
commit 79ce1647da
4 changed files with 227 additions and 6 deletions

View file

@ -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 */

View file

@ -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

View file

@ -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);

View file

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