]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
gpio: dwapb: Mask interrupts at hardware initialization
authorLiang Hao <haohlliang@gmail.com>
Sun, 5 Jul 2026 07:47:59 +0000 (15:47 +0800)
committerBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Tue, 7 Jul 2026 12:32:01 +0000 (14:32 +0200)
GPIO interrupts may retain stale state across warm reboots when
peripherals remain powered. If a GPIO line is not explicitly
configured for interrupts, this can result in interrupt storms
due to missing handlers.

Fix this by ensuring all interrupts are masked and disabled at
hardware initialization time via the init_hw() callback. Pending
interrupts are also cleared to start from a known-safe state.

Interrupts will be unmasked only when explicitly configured by
userspace or kernel drivers.

Signed-off-by: Liang Hao <haohlliang@gmail.com>
Link: https://patch.msgid.link/20260705074759.47863-1-haohlliang@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
drivers/gpio/gpio-dwapb.c

index 21e39fb940fefdb39afe174f3752a78f7da388ff..aa7c08e60707469a4074a652c80ab30aa90925bc 100644 (file)
@@ -200,6 +200,22 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
        dwapb_write(gpio, GPIO_INT_POLARITY, pol);
 }
 
+static int dwapb_irq_init_hw(struct gpio_chip *gc)
+{
+       struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
+
+       /*
+        * GPIO interrupts may retain stale state across warm reboots when
+        * peripherals stay powered. Force a known-safe state before the GPIO
+        * irqchip and irq domain are set up.
+        */
+       dwapb_write(gpio, GPIO_INTEN, 0);
+       dwapb_write(gpio, GPIO_INTMASK, 0xffffffff);
+       dwapb_write(gpio, GPIO_PORTA_EOI, 0xffffffff);
+
+       return 0;
+}
+
 static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
 {
        struct gpio_generic_chip *gen_gc = &gpio->ports[0].chip;
@@ -471,6 +487,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
        girq = &gc->irq;
        girq->handler = handle_bad_irq;
        girq->default_type = IRQ_TYPE_NONE;
+       girq->init_hw = dwapb_irq_init_hw;
 
        port->pirq = pirq;