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

From: Michal Piekos

Date: Sat Mar 14 2026 - 04:10:37 EST


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) {
+ 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

#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,
--
Michal Piekos <michal.piekos@xxxxxxxxxxxxx>