[PATCH 01/12] pinctrl: airoha: fix setting of GPIO direction

From: Zhengping Zhang

Date: Tue Nov 10 2026 - 05:10:48 EST


From: Daniel Schwierzeck <daniel.schwierzeck@xxxxxxxxx>

The GPIO_CTRL registers have two bits per GPIO where the values 0x2 and
0x3 are reserved. It can happen that both bits in GPIO_CTRL of a GPIO
are set when the pinctrl driver is probed (e.g. modified by bootloader),
but the current code just clears the LSB. Thus when switching a certain
GPIO to output, the updated GPIO_CTRL register can contain the reserved
value 0x2 for that GPIO. This can result in not driving the GPIO pin at
all.

Always clear both bits per GPIO and just set the LSB when the GPIO is
configured for output.

Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@xxxxxxxxx>
Signed-off-by: Zhengping Zhang <zhengping.zhang@xxxxxxxxxx>
---
drivers/pinctrl/airoha/pinctrl-airoha.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
index 52a768c859b71..8dd0881bba4ad 100644
--- a/drivers/pinctrl/airoha/pinctrl-airoha.c
+++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
@@ -164,7 +164,7 @@ static int airoha_gpio_set_direction(struct gpio_chip *chip, unsigned int gpio,
{
struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip);
u32 mask, index;
- int err;
+ int err, offset;

/* set output enable */
mask = BIT(gpio % AIROHA_PIN_BANK_SIZE);
@@ -176,12 +176,13 @@ static int airoha_gpio_set_direction(struct gpio_chip *chip, unsigned int gpio,
return err;

/* set direction */
- mask = BIT(2 * (gpio % AIROHA_REG_GPIOCTRL_NUM_PIN));
+ offset = 2 * (gpio % AIROHA_REG_GPIOCTRL_NUM_PIN);
+ mask = GENMASK(offset + 1, offset); /* always clear the two bits per GPIO */
index = gpio / AIROHA_REG_GPIOCTRL_NUM_PIN;

return regmap_update_bits(pinctrl->regmap,
pinctrl->gpio_regs->dir[index], mask,
- !input ? mask : 0);
+ !input ? BIT(offset) : 0);
}

static int airoha_gpio_direction_input(struct gpio_chip *chip,
--
2.43.0