]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
pinctrl: sunxi: fix gpiochip_lock_as_irq() failure when pinmux is unknown
authorMichal Piekos <michal.piekos@mmpsystems.pl>
Fri, 20 Mar 2026 17:52:31 +0000 (18:52 +0100)
committerLinus Walleij <linusw@kernel.org>
Mon, 23 Mar 2026 13:23:09 +0000 (14:23 +0100)
Fixes kernel hang during boot due to inability to set up IRQ on AXP313a.

The issue is caused by gpiochip_lock_as_irq() which is failing when gpio
is in uninitialized state.

Solution is to set pinmux to GPIO INPUT in
sunxi_pinctrl_irq_request_resources() if it wasn't initialized
earlier.

Tested on Orange Pi Zero 3.

Fixes: 01e10d0272b9 ("pinctrl: sunxi: Implement gpiochip::get_direction()")
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Signed-off-by: Michal Piekos <michal.piekos@mmpsystems.pl>
Signed-off-by: Linus Walleij <linusw@kernel.org>
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/sunxi/pinctrl-sunxi.h

index 685b79fc0bf8b2bbdf7d478fbe921b442d27dffb..d3042e0c9712e888a9bb24f20aa42341e75afbe7 100644 (file)
@@ -1092,6 +1092,9 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
 {
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        struct sunxi_desc_function *func;
+       unsigned int offset;
+       u32 reg, shift, mask;
+       u8 disabled_mux, muxval;
        int ret;
 
        func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
@@ -1099,8 +1102,21 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
        if (!func)
                return -EINVAL;
 
-       ret = gpiochip_lock_as_irq(pctl->chip,
-                       pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
+       offset = pctl->irq_array[d->hwirq] - pctl->desc->pin_base;
+       sunxi_mux_reg(pctl, offset, &reg, &shift, &mask);
+       muxval = (readl(pctl->membase + reg) & mask) >> shift;
+
+       /* Change muxing to GPIO INPUT mode if at reset value */
+       if (pctl->flags & SUNXI_PINCTRL_NEW_REG_LAYOUT)
+               disabled_mux = SUN4I_FUNC_DISABLED_NEW;
+       else
+               disabled_mux = SUN4I_FUNC_DISABLED_OLD;
+
+       if (muxval == disabled_mux)
+               sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq],
+                             SUN4I_FUNC_INPUT);
+
+       ret = gpiochip_lock_as_irq(pctl->chip, offset);
        if (ret) {
                dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
                        irqd_to_hwirq(d));
index 22bffac1c3f001b4040d967ebc37bd36042788c6..0daf7600e2fb019df39e815a7f5e8b190e83d8fb 100644 (file)
@@ -86,6 +86,8 @@
 
 #define SUN4I_FUNC_INPUT       0
 #define SUN4I_FUNC_IRQ         6
+#define SUN4I_FUNC_DISABLED_OLD 7
+#define SUN4I_FUNC_DISABLED_NEW 15
 
 #define SUNXI_PINCTRL_VARIANT_MASK     GENMASK(7, 0)
 #define SUNXI_PINCTRL_NEW_REG_LAYOUT   BIT(8)