[PATCH] pinctrl: mediatek: paris: Directly modify registers to set GPIO direction

From: Chen-Yu Tsai

Date: Sun Apr 26 2026 - 22:10:57 EST


pinctrl_gpio_direction_input() / pinctrl_gpio_direction_output() take
the pinctrl mutex. This causes a gpiochip operations to need to sleep.
Worse yet, the .can_sleep field in the gpiochip is not set. This causes
the shared GPIO proxy to trip over, as it uses gpiod_cansleep() to check
whether it can use a spinlock or needs a mutex. In this case, it ends
up taking a spinlock, then calls pinctrl_gpio_direction_output(), which
takes a mutex. This causes a huge warning.

While this class of Mediatek hardware does not have separate clear/set
registers, the pinctrl context has a spinlock that is taken whenever
a register read-modify-write is done.

Switch to directly setting the GPIO direction register bits to avoid
the mutex.

Signed-off-by: Chen-Yu Tsai <wenst@xxxxxxxxxxxx>
---
drivers/pinctrl/mediatek/pinctrl-paris.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index 6bf37d8085fa..e4c0bc27d984 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -886,19 +886,24 @@ static int mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)

static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
{
- return pinctrl_gpio_direction_input(chip, gpio);
+ struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+ const struct mtk_pin_desc *desc = &hw->soc->pins[gpio];
+
+ return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 0);
}

static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
int value)
{
+ struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+ const struct mtk_pin_desc *desc = &hw->soc->pins[gpio];
int ret;

ret = mtk_gpio_set(chip, gpio, value);
if (ret)
return ret;

- return pinctrl_gpio_direction_output(chip, gpio);
+ return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 1);
}

static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
--
2.54.0.rc2.544.gc7ae2d5bb8-goog