summaryrefslogtreecommitdiff
path: root/drivers/gpio/msm_gpio.c
diff options
context:
space:
mode:
authorNeil Armstrong <neil.armstrong@linaro.org>2025-04-01 09:45:19 +0200
committerCaleb Connolly <caleb.connolly@linaro.org>2025-04-11 15:24:54 +0200
commit0708bdd34d4fdd0680706d2719de34704402719d (patch)
tree1897c98b019f137b28c9657dfcbd43d8bce09f72 /drivers/gpio/msm_gpio.c
parent45acd9d2d4ec84775d09c73aab75a4fd989beb41 (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.c32
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;