Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/arm/include/imx9/chip.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
100 changes: 100 additions & 0 deletions arch/arm/src/imx9/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions arch/arm/src/imx9/imx9_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
126 changes: 121 additions & 5 deletions arch/arm/src/imx9/imx9_gpioirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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 */
Expand Down Expand Up @@ -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
}

/****************************************************************************
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
Loading