From 25498787cd8c043cd478ccae93b0b2b5e57e6e82 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 31 Jul 2026 09:18:44 +0100 Subject: [PATCH 1/2] pinctrl: bcm2835: Make IRQ usage set pin to input If a GPIO is being used as a source of interrupts, it must be configured as an input otherwise one risks an interrupt storm. Signed-off-by: Phil Elwell --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 82c7074811ba9f..2b3acb65d0bcc5 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -724,6 +724,23 @@ static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on) return ret; } +static int bcm2835_gpio_irq_reqres(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + int ret; + + ret = gpiochip_irq_reqres(d); + if (!ret) + ret = bcm2835_gpio_direction_input(gc, d->hwirq); + + return ret; +} + +static void bcm2835_gpio_irq_relres(struct irq_data *d) +{ + return gpiochip_irq_relres(d); +} + static const struct irq_chip bcm2835_gpio_irq_chip = { .name = MODULE_NAME, .irq_set_type = bcm2835_gpio_irq_set_type, @@ -731,6 +748,8 @@ static const struct irq_chip bcm2835_gpio_irq_chip = { .irq_mask = bcm2835_gpio_irq_mask, .irq_unmask = bcm2835_gpio_irq_unmask, .irq_set_wake = bcm2835_gpio_irq_set_wake, + .irq_request_resources = bcm2835_gpio_irq_reqres, + .irq_release_resources = bcm2835_gpio_irq_relres, .flags = (IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE), GPIOCHIP_IRQ_RESOURCE_HELPERS, }; From 093398d5a9b14b71c6ed29e6e59197a2034894c6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 31 Jul 2026 09:27:38 +0100 Subject: [PATCH 2/2] pinctrl: bcm2835: Enable strict pinmux mode Enable strict pinmux so GPIO requests on function pins are rejected. Implement function_is_gpio so pins muxed as GPIO, including hogs and legacy brcm,function maps, stay requestable. Signed-off-by: Phil Elwell --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 2b3acb65d0bcc5..d8da3fb071d62d 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -1034,6 +1034,13 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, return 0; } +static bool bcm2835_pmx_function_is_gpio(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return selector == BCM2835_FSEL_GPIO_IN || + selector == BCM2835_FSEL_GPIO_OUT; +} + static const struct pinmux_ops bcm2835_pmx_ops = { .free = bcm2835_pmx_free, .get_functions_count = bcm2835_pmx_get_functions_count, @@ -1042,6 +1049,8 @@ static const struct pinmux_ops bcm2835_pmx_ops = { .set_mux = bcm2835_pmx_set, .gpio_disable_free = bcm2835_pmx_gpio_disable_free, .gpio_set_direction = bcm2835_pmx_gpio_set_direction, + .function_is_gpio = bcm2835_pmx_function_is_gpio, + .strict = true, }; static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,