From c63b0510fb4f922638d7537ce8f1a0baf4e24a40 Mon Sep 17 00:00:00 2001 From: paolo Date: Fri, 30 Jan 2026 14:05:33 +0100 Subject: [PATCH] rp23xx/rp23xx-rv: Fix GPIO interrupt handler for RP2350B variant. The GPIO interrupt handler had hardcoded values that only worked correctly for RP2350A (30 GPIOs). For RP2350B (48 GPIOs): - Loop count was hardcoded to 6 registers but should be computed based on RP23XX_GPIO_NUM (4 for RP2350A, 6 for RP2350B) - Reserved bits mask was always applied at register index 3, but for RP2350B register 3 contains valid GPIOs 24-31. This caused interrupts for GPIOs 30-31 to be incorrectly discarded - PWM port validation rejected valid ports 8-11 on RP2350B which has 12 PWM slices instead of 8 Changes: - Add RP23XX_GPIO_NREGS macro to compute number of interrupt registers - Use conditional compilation to only mask reserved bits on RP2350A where the last register has 6 valid GPIOs (bits 0-23) - Fix PWM port validation to allow 12 ports on RP2350B Signed-off-by: paolo --- arch/arm/src/rp23xx/rp23xx_gpio.c | 18 +++++++++++++++--- arch/arm/src/rp23xx/rp23xx_gpio.h | 4 ++++ arch/risc-v/src/rp23xx-rv/rp23xx_gpio.c | 18 +++++++++++++++--- arch/risc-v/src/rp23xx-rv/rp23xx_gpio.h | 4 ++++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/arch/arm/src/rp23xx/rp23xx_gpio.c b/arch/arm/src/rp23xx/rp23xx_gpio.c index 64b9e554bff..0c15a3edb11 100644 --- a/arch/arm/src/rp23xx/rp23xx_gpio.c +++ b/arch/arm/src/rp23xx/rp23xx_gpio.c @@ -168,15 +168,23 @@ static int rp23xx_gpio_interrupt(int irq, void *context, void *arg) /* Scan all GPIO interrupt status registers */ - for (i = 0; i < 6; i++) + for (i = 0; i < RP23XX_GPIO_NREGS; i++) { /* Get and clear pending GPIO interrupt status */ stat = getreg32(RP23XX_IO_BANK0_PROC_INTS(i * 8, 0)); - if (i == 3) + +#if (RP23XX_GPIO_NUM & 7) != 0 + /* Mask reserved bits in the last register. + * RP2350A: 30 GPIOs, last register has 6 valid GPIOs (bits 0-23) + * RP2350B: 48 GPIOs, all registers fully used (no masking needed) + */ + + if (i == RP23XX_GPIO_NREGS - 1) { - stat &= 0x00ffffff; /* Clear reserved bits */ + stat &= (1u << ((RP23XX_GPIO_NUM & 7) * 4)) - 1; } +#endif putreg32(stat, RP23XX_IO_BANK0_INTR(i * 8)); @@ -256,7 +264,11 @@ int rp23xx_gpio_get_function_pin(uint32_t func, uint32_t port) break; case RP23XX_GPIO_FUNC_PWM: +#ifdef CONFIG_RP23XX_RP2350B + if (port >= 12) +#else if (port >= 8) +#endif { return -1; } diff --git a/arch/arm/src/rp23xx/rp23xx_gpio.h b/arch/arm/src/rp23xx/rp23xx_gpio.h index 5eaa6d0b266..ea94cac14a1 100644 --- a/arch/arm/src/rp23xx/rp23xx_gpio.h +++ b/arch/arm/src/rp23xx/rp23xx_gpio.h @@ -48,6 +48,10 @@ #define RP23XX_GPIO_NUM 30 /* Number of GPIO pins */ #endif +/* Number of GPIO interrupt status registers */ + +#define RP23XX_GPIO_NREGS ((RP23XX_GPIO_NUM + 7) / 8) + /* GPIO function types ******************************************************/ #define RP23XX_GPIO_FUNC_HSTX RP23XX_IO_BANK0_GPIO_CTRL_FUNCSEL_HSTX diff --git a/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.c b/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.c index 46148db5fe4..361ecf66a73 100644 --- a/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.c +++ b/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.c @@ -168,15 +168,23 @@ static int rp23xx_gpio_interrupt(int irq, void *context, void *arg) /* Scan all GPIO interrupt status registers */ - for (i = 0; i < 6; i++) + for (i = 0; i < RP23XX_GPIO_NREGS; i++) { /* Get and clear pending GPIO interrupt status */ stat = getreg32(RP23XX_IO_BANK0_PROC_INTS(i * 8, 0)); - if (i == 3) + +#if (RP23XX_GPIO_NUM & 7) != 0 + /* Mask reserved bits in the last register. + * RP2350A: 30 GPIOs, last register has 6 valid GPIOs (bits 0-23) + * RP2350B: 48 GPIOs, all registers fully used (no masking needed) + */ + + if (i == RP23XX_GPIO_NREGS - 1) { - stat &= 0x00ffffff; /* Clear reserved bits */ + stat &= (1u << ((RP23XX_GPIO_NUM & 7) * 4)) - 1; } +#endif putreg32(stat, RP23XX_IO_BANK0_INTR(i * 8)); @@ -256,7 +264,11 @@ int rp23xx_gpio_get_function_pin(uint32_t func, uint32_t port) break; case RP23XX_GPIO_FUNC_PWM: +#ifdef CONFIG_RP23XX_RV_RP2350B + if (port >= 12) +#else if (port >= 8) +#endif { return -1; } diff --git a/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.h b/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.h index 98aabda43e1..25cae2ddab6 100644 --- a/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.h +++ b/arch/risc-v/src/rp23xx-rv/rp23xx_gpio.h @@ -48,6 +48,10 @@ #define RP23XX_GPIO_NUM 30 /* Number of GPIO pins */ #endif +/* Number of GPIO interrupt status registers */ + +#define RP23XX_GPIO_NREGS ((RP23XX_GPIO_NUM + 7) / 8) + /* GPIO function types ******************************************************/ #define RP23XX_GPIO_FUNC_HSTX RP23XX_IO_BANK0_GPIO_CTRL_FUNCSEL_HSTX