From ecfe2ed4d3995493cf2ece597fa3ec5de8b87e89 Mon Sep 17 00:00:00 2001 From: "Daniel P. Carvalho" Date: Sat, 3 Oct 2026 21:44:39 -0300 Subject: [PATCH] arch/mips/pic32mz: support GPIO interrupts on the PIC32MZ-W1. The change notification code assumed the EC/EF layout: the IRQ of an I/O port was PIC32MZ_IRQ_PORTA plus the port index, and initialization reset the change notification registers of every port index. The PIC32MZ-W1 only implements PORTA, PORTB, PORTC and PORTK, its change notification vectors are PIC32MZ_IRQ_CNA/CNB/CNC/CNK, and the addresses of the missing ports D-J belong to other peripherals (I2C1 is at the PORTE address). Map the port index to its IRQ through a table on the W1, skip the unimplemented ports during initialization, and pass the port index to the common handler as its argument instead of deriving it from the IRQ number. Hide the PORTD-PORTJ interrupt options on the W1. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Daniel P. Carvalho --- arch/mips/src/pic32mz/Kconfig | 6 ++++ arch/mips/src/pic32mz/pic32mz_gpioirq.c | 48 +++++++++++++++++++------ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/arch/mips/src/pic32mz/Kconfig b/arch/mips/src/pic32mz/Kconfig index a613f552dd6..0bf69e6f545 100644 --- a/arch/mips/src/pic32mz/Kconfig +++ b/arch/mips/src/pic32mz/Kconfig @@ -998,26 +998,32 @@ config PIC32MZ_GPIOIRQ_PORTC config PIC32MZ_GPIOIRQ_PORTD bool "I/O PORTD Interrupt Support" default n + depends on !ARCH_CHIP_PIC32MZW1 config PIC32MZ_GPIOIRQ_PORTE bool "I/O PORTE Interrupt Support" default n + depends on !ARCH_CHIP_PIC32MZW1 config PIC32MZ_GPIOIRQ_PORTF bool "I/O PORTF Interrupt Support" default n + depends on !ARCH_CHIP_PIC32MZW1 config PIC32MZ_GPIOIRQ_PORTG bool "I/O PORTG Interrupt Support" default n + depends on !ARCH_CHIP_PIC32MZW1 config PIC32MZ_GPIOIRQ_PORTH bool "I/O PORTH Interrupt Support" default n + depends on !ARCH_CHIP_PIC32MZW1 config PIC32MZ_GPIOIRQ_PORTJ bool "I/O PORTJ Interrupt Support" default n + depends on !ARCH_CHIP_PIC32MZW1 config PIC32MZ_GPIOIRQ_PORTK bool "I/O PORTK Interrupt Support" diff --git a/arch/mips/src/pic32mz/pic32mz_gpioirq.c b/arch/mips/src/pic32mz/pic32mz_gpioirq.c index e9652964215..47d6da5eb42 100644 --- a/arch/mips/src/pic32mz/pic32mz_gpioirq.c +++ b/arch/mips/src/pic32mz/pic32mz_gpioirq.c @@ -152,6 +152,27 @@ static struct ioport_level2_s * const g_level2_handlers[CHIP_NPORTS] = #endif }; +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +/* Look-up of port to change notification IRQ. The PIC32MZ-W1 implements + * only PORTA, PORTB, PORTC and PORTK, so the port index cannot be added to + * the PORTA IRQ number. Zero marks an unimplemented port. + */ + +static const uint8_t g_cnirq[CHIP_NPORTS] = +{ + [PIC32MZ_IOPORTA] = PIC32MZ_IRQ_CNA, + [PIC32MZ_IOPORTB] = PIC32MZ_IRQ_CNB, + [PIC32MZ_IOPORTC] = PIC32MZ_IRQ_CNC, + [PIC32MZ_IOPORTK] = PIC32MZ_IRQ_CNK, +}; + +# define pic32mz_cnirq(ioport) ((int)g_cnirq[ioport]) +# define pic32mz_haveport(ioport) (g_cnirq[ioport] != 0) +#else +# define pic32mz_cnirq(ioport) (PIC32MZ_IRQ_PORTA + (ioport)) +# define pic32mz_haveport(ioport) (true) +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -225,12 +246,11 @@ static int pic32mz_cninterrupt(int irq, void *context, void *arg) int ret = OK; int i; - /* Get the IO port index from the IRQ number. This, of course, - * assumes that the irq numbers are consecutive beginning with - * IOPORTA. + /* The IO port index was provided as the argument when the handler was + * attached. */ - ioport = irq - PIC32MZ_IRQ_PORTA; + ioport = (int)(uintptr_t)arg; DEBUGASSERT(ioport >= 0 && ioport < CHIP_NPORTS); /* If we got this interrupt, then there must also be an array @@ -377,6 +397,13 @@ void pic32mz_gpioirqinitialize(void) for (i = 0; i < CHIP_NPORTS; i++) { + /* Skip IO ports that are not implemented on this part */ + + if (!pic32mz_haveport(i)) + { + continue; + } + /* Get the base address of this IO port peripheral */ base = g_gpiobase[i]; @@ -395,11 +422,12 @@ void pic32mz_gpioirqinitialize(void) if (g_level2_handlers[i] != NULL) { /* Yes.. Attach the common change notice interrupt handler - * to the IO port interrupt. Notice that this assumes that - * each IRQ number is consecutive beginning with IOPORTA. + * to the IO port interrupt. The IO port index is passed as the + * argument. */ - ret = irq_attach(PIC32MZ_IRQ_PORTA + i, pic32mz_cninterrupt, NULL); + ret = irq_attach(pic32mz_cnirq(i), pic32mz_cninterrupt, + (void *)(uintptr_t)i); DEBUGASSERT(ret == OK); UNUSED(ret); @@ -414,9 +442,9 @@ void pic32mz_gpioirqinitialize(void) regval = getreg32(base + PIC32MZ_IOPORT_PORT_OFFSET); UNUSED(regval); - /* Clear the CN interrupt flag. Same assumption as above. */ + /* Clear the CN interrupt flag. */ - mips_clrpend_irq(PIC32MZ_IRQ_PORTA + i); + mips_clrpend_irq(pic32mz_cnirq(i)); } } } @@ -605,7 +633,7 @@ void pic32mz_gpioirqenable(pinset_t pinset) /* And enable the interrupt. */ - up_enable_irq(ioport + PIC32MZ_IRQ_PORTA); + up_enable_irq(pic32mz_cnirq(ioport)); } }