diff options
author | Neil Armstrong <neil.armstrong@linaro.org> | 2025-04-01 09:45:19 +0200 |
---|---|---|
committer | Caleb Connolly <caleb.connolly@linaro.org> | 2025-04-11 15:24:54 +0200 |
commit | 0708bdd34d4fdd0680706d2719de34704402719d (patch) | |
tree | 1897c98b019f137b28c9657dfcbd43d8bce09f72 /drivers/gpio/msm_gpio.c | |
parent | 45acd9d2d4ec84775d09c73aab75a4fd989beb41 (diff) |
gpio: msm: fix get_function return for special pins
The get_function callback wrongly returns 0 for special pins,
return the appropriate pin function by probing into the special
pins data fields to find if the pin is gpio capable.
Fixes: f9bb539460d ("gpio: msm: add support for special pins")
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20250401-topic-sm8x50-msm-gpio-special-fixes-v1-1-a1148a02bb16@linaro.org
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
Diffstat (limited to 'drivers/gpio/msm_gpio.c')
-rw-r--r-- | drivers/gpio/msm_gpio.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index cea073b3297..f208eec7e56 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -192,13 +192,41 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio) return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN); } +static int msm_gpio_get_function_special(struct msm_gpio_bank *priv, + unsigned int gpio) +{ + unsigned int offset = gpio - priv->pin_data->special_pins_start; + const struct msm_special_pin_data *data; + + if (!priv->pin_data->special_pins_data) + return GPIOF_UNKNOWN; + + data = &priv->pin_data->special_pins_data[offset]; + + /* No I/O fields, cannot control/read the I/O value */ + if (!data->io_reg || (data->out_bit >= 31 && data->in_bit >= 31)) + return GPIOF_FUNC; + + /* No Output-Enable register, cannot control I/O direction */ + if (!data->ctl_reg || data->oe_bit >= 31) { + if (data->out_bit >= 31) + return GPIOF_INPUT; + else + return GPIOF_OUTPUT; + } + + if (readl(priv->base + data->ctl_reg) & BIT(data->oe_bit)) + return GPIOF_OUTPUT; + + return GPIOF_INPUT; +} + static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); - /* Always NOP for special pins, assume they're in the correct state */ if (qcom_is_special_pin(priv->pin_data, gpio)) - return 0; + return msm_gpio_get_function_special(priv, gpio); if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE) return GPIOF_OUTPUT; |