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

From: Andre Przywara

Date: Mon Mar 16 2026 - 10:37:57 EST


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)?

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

+ 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,