Re: [PATCH v3] pinctrl: sunxi: fix gpiochip_lock_as_irq() failure when pinmux is unknown

From: Chen-Yu Tsai

Date: Mon Mar 16 2026 - 12:43:58 EST


On Mon, Mar 16, 2026 at 10:37 PM Andre Przywara <andre.przywara@xxxxxxx> wrote:
>
> Hi,
>
> On 3/14/26 09:09, Michal Piekos wrote:
> > 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 unitialized 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.
> >
> > Signed-off-by: Michal Piekos <michal.piekos@xxxxxxxxxxxxx>
> > Suggested-by: Chen-Yu Tsai <wens@xxxxxxxxxx>
> > ---
> > Changes in v3:
> > - Drop v2 solution which was returning input instead of error when pin
> > is not initialized.
> > - Add checking pinmux configuration in
> > sunxi_pinctrl_irq_request_resources() and set pin to input if
> > uninitialized
> > - Link to v2: https://lore.kernel.org/r/20260308-rc2-boot-hang-v2-1-516fdb820953@xxxxxxxxxxxxx
> >
> > Changes in v2:
> > - Dropped the previous faulty solution which was forcing the axp313 to
> > use r_pio as interrupt controller as pointed out by Jernej Škrabec.
> > - Implemented suggestion from Andrey Skvortsov to return default
> > direction as input
> > - Link to v1: https://lore.kernel.org/r/20260308-rc2-boot-hang-v1-0-d792d1a78dfd@xxxxxxxxxxxxx
> > ---
> > drivers/pinctrl/sunxi/pinctrl-sunxi.c | 13 +++++++++++++
> > drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 +
> > 2 files changed, 14 insertions(+)
> >
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> > index c990b6118172..7d46f7613672 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> > @@ -1089,6 +1089,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 muxval;
> > int ret;
> >
> > func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
> > @@ -1096,6 +1099,16 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
> > if (!func)
> > return -EINVAL;
> >
> > + 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 (muxval == SUN4I_FUNC_IO_DISABLE) {
>
> The "high impedance"/reset value depends on the SoC generation: older
> SoCs didn't have one, so they used 0 (GPIO_INPUT), which is the closest
> to "off" you can get there. Most SoCs afterwards indeed used 0x7, as you
> set below, but newer SoCs (D1/T113, A523, ...) use 0xf now.
>
> Would it work to do:
> if (muxval != SUN4I_FUNC_INPUT) {
> or shall we just force SUN4I_FUNC_INPUT always, without even checking?
> Or can there be other settings already (for instance the IRQ function)?

Yes, by some badly written DT. Pinctrl muxing happens first, then
request_irq(), so you could accidentally re-mux a pin that some
peripheral is using into an IRQ if we don't do the check properly.

> Not really familiar with the call chain here, but shouldn't the mux be
> set to the IRQ function (0x6/0xe) here anyway?

The muxing happens happens a few lines below, right after
gpiochip_lock_as_irq(). However we're trying to silence the warning
that gpiochip_lock_as_irq() indirectly causes.


ChenYu

> > + sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq],
> > + SUN4I_FUNC_INPUT);
> > + }
> > +
> > ret = gpiochip_lock_as_irq(pctl->chip,
> > pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
> > if (ret) {
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > index ad26e4de16a8..22c527fc6ae2 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > @@ -86,6 +86,7 @@
> >
> > #define SUN4I_FUNC_INPUT 0
> > #define SUN4I_FUNC_IRQ 6
> > +#define SUN4I_FUNC_IO_DISABLE 7
>
> As mentioned above, this cannot be a simple fixed define for all SoCs.
>
> Cheers,
> Andre
>
> >
> > #define SUNXI_PINCTRL_VARIANT_MASK GENMASK(7, 0)
> > #define SUNXI_PINCTRL_NEW_REG_LAYOUT BIT(8)
> >
> > ---
> > base-commit: 4ae12d8bd9a830799db335ee661d6cbc6597f838
> > change-id: 20260308-rc2-boot-hang-269e8546635b
> >
> > Best regards,
>