imx93_gpioirq: Fix the GPIO interrupt source names

The original assumption was that the interrupt numbers are divided
so that 16 pins from 1 port are handled by a single interrupt source.

So source 0 would handle pins 0-15 and source 1 would handle pins 16-31.
This assumption is wrong, each pin has two sources, thus there are two
interrupt lines for each pin.

The driver uses source 0, and leaves source 1 disabled.
This commit is contained in:
Ville Juven 2024-04-15 17:47:35 +03:00 committed by Xiang Xiao
parent ae38e4a50d
commit 8e32a3ce24
3 changed files with 52 additions and 94 deletions

View File

@ -31,8 +31,8 @@
#define IMX9_IRQ_RESERVED39 (IMX9_IRQ_EXT + 7) /* 1-bit or 2-bit ECC or Parity error from CA55 platform cache */ #define IMX9_IRQ_RESERVED39 (IMX9_IRQ_EXT + 7) /* 1-bit or 2-bit ECC or Parity error from CA55 platform cache */
#define IMX9_IRQ_CAN1 (IMX9_IRQ_EXT + 8) /* CAN1 interrupt */ #define IMX9_IRQ_CAN1 (IMX9_IRQ_EXT + 8) /* CAN1 interrupt */
#define IMX9_IRQ_CAN1_ERROR (IMX9_IRQ_EXT + 9) /* CAN1 error interrupt */ #define IMX9_IRQ_CAN1_ERROR (IMX9_IRQ_EXT + 9) /* CAN1 error interrupt */
#define IMX9_IRQ_GPIO1_0_15 (IMX9_IRQ_EXT + 10) /* General Purpose Input/Output 1 interrupt 0 */ #define IMX9_IRQ_GPIO1_0 (IMX9_IRQ_EXT + 10) /* General Purpose Input/Output 1 interrupt 0 */
#define IMX9_IRQ_GPIO1_16_31 (IMX9_IRQ_EXT + 11) /* General Purpose Input/Output 1 interrupt 1 */ #define IMX9_IRQ_GPIO1_1 (IMX9_IRQ_EXT + 11) /* General Purpose Input/Output 1 interrupt 1 */
#define IMX9_IRQ_I3C1 (IMX9_IRQ_EXT + 12) /* Improved Inter-Integrated Circuit 1 interrupt */ #define IMX9_IRQ_I3C1 (IMX9_IRQ_EXT + 12) /* Improved Inter-Integrated Circuit 1 interrupt */
#define IMX9_IRQ_LPI2C1 (IMX9_IRQ_EXT + 13) /* Low Power Inter-Integrated Circuit module 1 */ #define IMX9_IRQ_LPI2C1 (IMX9_IRQ_EXT + 13) /* Low Power Inter-Integrated Circuit module 1 */
#define IMX9_IRQ_LPI2C2 (IMX9_IRQ_EXT + 14) /* Low Power Inter-Integrated Circuit module 2 */ #define IMX9_IRQ_LPI2C2 (IMX9_IRQ_EXT + 14) /* Low Power Inter-Integrated Circuit module 2 */
@ -78,10 +78,10 @@
#define IMX9_IRQ_FLEXIO2 (IMX9_IRQ_EXT + 54) /* Flexible IO 2 interrupt */ #define IMX9_IRQ_FLEXIO2 (IMX9_IRQ_EXT + 54) /* Flexible IO 2 interrupt */
#define IMX9_IRQ_FLEXSPI1 (IMX9_IRQ_EXT + 55) /* FlexSPI controller interface interrupt 1 */ #define IMX9_IRQ_FLEXSPI1 (IMX9_IRQ_EXT + 55) /* FlexSPI controller interface interrupt 1 */
#define IMX9_IRQ_RESERVED88 (IMX9_IRQ_EXT + 56) /* Reserved interrupt */ #define IMX9_IRQ_RESERVED88 (IMX9_IRQ_EXT + 56) /* Reserved interrupt */
#define IMX9_IRQ_GPIO2_0_15 (IMX9_IRQ_EXT + 57) /* General Purpose Input/Output 2 interrupt 0 */ #define IMX9_IRQ_GPIO2_0 (IMX9_IRQ_EXT + 57) /* General Purpose Input/Output 2 interrupt 0 */
#define IMX9_IRQ_GPIO2_16_31 (IMX9_IRQ_EXT + 58) /* General Purpose Input/Output 2 interrupt 1 */ #define IMX9_IRQ_GPIO2_1 (IMX9_IRQ_EXT + 58) /* General Purpose Input/Output 2 interrupt 1 */
#define IMX9_IRQ_GPIO3_0_15 (IMX9_IRQ_EXT + 59) /* General Purpose Input/Output 3 interrupt 0 */ #define IMX9_IRQ_GPIO3_0 (IMX9_IRQ_EXT + 59) /* General Purpose Input/Output 3 interrupt 0 */
#define IMX9_IRQ_GPIO3_16_31 (IMX9_IRQ_EXT + 60) /* General Purpose Input/Output 3 interrupt 1 */ #define IMX9_IRQ_GPIO3_1 (IMX9_IRQ_EXT + 60) /* General Purpose Input/Output 3 interrupt 1 */
#define IMX9_IRQ_I3C2 (IMX9_IRQ_EXT + 61) /* Improved Inter-Integrated Circuit 2 interrupt */ #define IMX9_IRQ_I3C2 (IMX9_IRQ_EXT + 61) /* Improved Inter-Integrated Circuit 2 interrupt */
#define IMX9_IRQ_LPI2C3 (IMX9_IRQ_EXT + 62) /* Low Power Inter-Integrated Circuit module 3 */ #define IMX9_IRQ_LPI2C3 (IMX9_IRQ_EXT + 62) /* Low Power Inter-Integrated Circuit module 3 */
#define IMX9_IRQ_LPI2C4 (IMX9_IRQ_EXT + 63) /* Low Power Inter-Integrated Circuit module 4 */ #define IMX9_IRQ_LPI2C4 (IMX9_IRQ_EXT + 63) /* Low Power Inter-Integrated Circuit module 4 */
@ -210,8 +210,8 @@
#define IMX9_IRQ_RESERVED218 (IMX9_IRQ_EXT + 186) /* Reserved interrupt */ #define IMX9_IRQ_RESERVED218 (IMX9_IRQ_EXT + 186) /* Reserved interrupt */
#define IMX9_IRQ_USB1 (IMX9_IRQ_EXT + 187) /* USB-1 Wake-up Interrupt */ #define IMX9_IRQ_USB1 (IMX9_IRQ_EXT + 187) /* USB-1 Wake-up Interrupt */
#define IMX9_IRQ_USB2 (IMX9_IRQ_EXT + 188) /* USB-2 Wake-up Interrupt */ #define IMX9_IRQ_USB2 (IMX9_IRQ_EXT + 188) /* USB-2 Wake-up Interrupt */
#define IMX9_IRQ_GPIO4_0_15 (IMX9_IRQ_EXT + 189) /* General Purpose Input/Output 4 interrupt 0 */ #define IMX9_IRQ_GPIO4_0 (IMX9_IRQ_EXT + 189) /* General Purpose Input/Output 4 interrupt 0 */
#define IMX9_IRQ_GPIO4_16_31 (IMX9_IRQ_EXT + 190) /* General Purpose Input/Output 4 interrupt 1 */ #define IMX9_IRQ_GPIO4_1 (IMX9_IRQ_EXT + 190) /* General Purpose Input/Output 4 interrupt 1 */
#define IMX9_IRQ_LPSPI5 (IMX9_IRQ_EXT + 191) /* Low Power Serial Peripheral Interface 5 */ #define IMX9_IRQ_LPSPI5 (IMX9_IRQ_EXT + 191) /* Low Power Serial Peripheral Interface 5 */
#define IMX9_IRQ_LPSPI6 (IMX9_IRQ_EXT + 192) /* Low Power Serial Peripheral Interface 6 */ #define IMX9_IRQ_LPSPI6 (IMX9_IRQ_EXT + 192) /* Low Power Serial Peripheral Interface 6 */
#define IMX9_IRQ_LPSPI7 (IMX9_IRQ_EXT + 193) /* Low Power Serial Peripheral Interface 7 */ #define IMX9_IRQ_LPSPI7 (IMX9_IRQ_EXT + 193) /* Low Power Serial Peripheral Interface 7 */

View File

@ -274,6 +274,20 @@ void imx9_gpio_write(gpio_pinset_t pinset, bool value);
bool imx9_gpio_read(gpio_pinset_t pinset); bool imx9_gpio_read(gpio_pinset_t pinset);
/****************************************************************************
* Name: imx9_gpioirq_attach
*
* Description:
* Attach a pin interrupt handler.
*
****************************************************************************/
#ifdef CONFIG_IMX9_GPIO_IRQ
int imx9_gpioirq_attach(gpio_pinset_t pinset, xcpt_t isr, void *arg);
#else
#define imx9_gpioirq_attach(pinset, isr, arg) 0
#endif
/**************************************************************************** /****************************************************************************
* Name: imx9_gpioirq_configure * Name: imx9_gpioirq_configure
* *

View File

@ -66,16 +66,17 @@ static struct imx9_portisr_s g_isrtab[IMX9_GPIO_NPORTS];
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: imx9_gpioN_A_B_interrupt * Name: imx9_gpio_interrupt
* *
* Description: * Description:
* GPIO interrupt handlers. * GPIO interrupt handlers. iMX9 has two interrupt sources for each pin,
* the NuttX driver uses source 0.
* *
****************************************************************************/ ****************************************************************************/
static int imx9_gpio_0_15_interrupt(int irq, void *context, void *arg) static int imx9_gpio_interrupt(int irq, void *context, void *arg)
{ {
uint32_t port = *(uint32_t *)arg; uint32_t port = (uint32_t)((uintptr_t)arg) >> GPIO_PORT_SHIFT;
uint32_t status; uint32_t status;
uint32_t pin; uint32_t pin;
uint32_t regaddr; uint32_t regaddr;
@ -83,56 +84,13 @@ static int imx9_gpio_0_15_interrupt(int irq, void *context, void *arg)
/* Get the pending interrupt indications */ /* Get the pending interrupt indications */
regaddr = IMX9_GPIO_ISFR0(port); regaddr = IMX9_GPIO_ISFR0(port);
status = getreg32(regaddr) & 0x0000ffff; status = getreg32(regaddr);
/* Decode the pending interrupts */ /* Decode the pending interrupts */
for (pin = 0; pin < 16 && status != 0; pin++) for (pin = 0; pin < 32 && status != 0; pin++)
{ {
/* Is the IRQ associate with this pin pending? */ /* Is the IRQ associated with this pin pending? */
uint32_t mask = (1 << pin);
if ((status & mask) != 0)
{
struct imx9_portisr_s *isrtab;
/* Yes, clear the status bit and dispatch the interrupt */
putreg32(mask, regaddr);
status &= ~mask;
/* Get the interrupt table for this port */
isrtab = &g_isrtab[port];
if (isrtab->pins[pin].isr != NULL)
{
/* Run the user handler with the user's argument */
isrtab->pins[pin].isr(irq, context, isrtab->pins[pin].arg);
}
}
}
return OK;
}
static int imx9_gpio_16_31_interrupt(int irq, void *context, void *arg)
{
uint32_t port = *(uint32_t *)arg;
uint32_t status;
uint32_t pin;
uint32_t regaddr;
/* Get the pending interrupt indications */
regaddr = IMX9_GPIO_ISFR0(port);
status = getreg32(regaddr) & 0xffff0000;
/* Decode the pending interrupts */
for (pin = 16; pin < 32 && status != 0; pin++)
{
/* Is the IRQ associate with this pin pending? */
uint32_t mask = (1 << pin); uint32_t mask = (1 << pin);
if ((status & mask) != 0) if ((status & mask) != 0)
@ -189,51 +147,37 @@ void imx9_gpioirq_initialize(void)
} }
} }
/* Disable all unconfigured GPIO interrupts at the NVIC */ /* Disable all GPIO interrupts */
up_disable_irq(IMX9_IRQ_GPIO1_0_15); up_disable_irq(IMX9_IRQ_GPIO1_0);
up_disable_irq(IMX9_IRQ_GPIO1_16_31); up_disable_irq(IMX9_IRQ_GPIO1_1);
up_disable_irq(IMX9_IRQ_GPIO2_0_15); up_disable_irq(IMX9_IRQ_GPIO2_0);
up_disable_irq(IMX9_IRQ_GPIO2_16_31); up_disable_irq(IMX9_IRQ_GPIO2_1);
up_disable_irq(IMX9_IRQ_GPIO3_0_15); up_disable_irq(IMX9_IRQ_GPIO3_0);
up_disable_irq(IMX9_IRQ_GPIO3_16_31); up_disable_irq(IMX9_IRQ_GPIO3_1);
up_disable_irq(IMX9_IRQ_GPIO4_0_15); up_disable_irq(IMX9_IRQ_GPIO4_0);
up_disable_irq(IMX9_IRQ_GPIO4_16_31); up_disable_irq(IMX9_IRQ_GPIO4_1);
/* Attach all configured GPIO interrupts and enable the interrupt at the /* Attach the common GPIO interrupt handler and enable the interrupt */
* NVIC
*/
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_0_15, DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_0,
imx9_gpio_0_15_interrupt, (void *)1)); imx9_gpio_interrupt, (void *)GPIO_PORT1));
up_enable_irq(IMX9_IRQ_GPIO1_0_15); up_enable_irq(IMX9_IRQ_GPIO1_0);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_16_31,
imx9_gpio_16_31_interrupt, (void *)1));
up_enable_irq(IMX9_IRQ_GPIO1_16_31);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_0_15, DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_0,
imx9_gpio_0_15_interrupt, (void *)2)); imx9_gpio_interrupt, (void *)GPIO_PORT2));
up_enable_irq(IMX9_IRQ_GPIO1_0_15); up_enable_irq(IMX9_IRQ_GPIO2_0);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_16_31,
imx9_gpio_16_31_interrupt, (void *)2));
up_enable_irq(IMX9_IRQ_GPIO1_16_31);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_0_15, DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_0,
imx9_gpio_0_15_interrupt, (void *)3)); imx9_gpio_interrupt, (void *)GPIO_PORT3));
up_enable_irq(IMX9_IRQ_GPIO1_0_15); up_enable_irq(IMX9_IRQ_GPIO3_0);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_16_31,
imx9_gpio_16_31_interrupt, (void *)3));
up_enable_irq(IMX9_IRQ_GPIO1_16_31);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_0_15, DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_0,
imx9_gpio_0_15_interrupt, (void *)4)); imx9_gpio_interrupt, (void *)GPIO_PORT4));
up_enable_irq(IMX9_IRQ_GPIO1_0_15); up_enable_irq(IMX9_IRQ_GPIO4_0);
DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_16_31,
imx9_gpio_16_31_interrupt, (void *)4));
up_enable_irq(IMX9_IRQ_GPIO1_16_31);
} }
/**************************************************************************** /****************************************************************************