]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
gpio: msm: add support for special pins
authorNeil Armstrong <neil.armstrong@linaro.org>
Wed, 11 Sep 2024 18:07:14 +0000 (20:07 +0200)
committerCaleb Connolly <caleb.connolly@linaro.org>
Fri, 4 Oct 2024 12:57:02 +0000 (14:57 +0200)
Leverage the data introduced in the struct msm_special_pin_data to allow
setting the gpio direction and value if supported by the pin data.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Caleb Connolly <caleb.connolly@linaro.org>
drivers/gpio/msm_gpio.c

index 2fb266f12854d17ae570da1f048e8ae8d2e57fc7..cea073b329777d4e03fbfa86415041a825f65aad 100644 (file)
@@ -34,13 +34,31 @@ struct msm_gpio_bank {
 #define GPIO_IN_OUT_REG(dev, x) \
        (GPIO_CONFIG_REG(dev, x) + 0x4)
 
+static void msm_gpio_direction_input_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;
+
+       data = &priv->pin_data->special_pins_data[offset];
+
+       if (!data->ctl_reg || data->oe_bit >= 31)
+               return;
+
+       /* switch direction */
+       clrsetbits_le32(priv->base + data->ctl_reg,
+                       BIT(data->oe_bit), 0);
+}
+
 static void msm_gpio_direction_input(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;
+               msm_gpio_direction_input_special(priv, gpio);
 
        /* Disable OE bit */
        clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
@@ -49,13 +67,33 @@ static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
        return;
 }
 
+static int msm_gpio_set_value_special(struct msm_gpio_bank *priv,
+                                     unsigned int gpio, int value)
+{
+       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 0;
+
+       data = &priv->pin_data->special_pins_data[offset];
+
+       if (!data->io_reg || data->out_bit >= 31)
+               return 0;
+
+       value = !!value;
+       /* set value */
+       writel(value << data->out_bit, priv->base + data->io_reg);
+
+       return 0;
+}
+
 static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
 {
        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_set_value_special(priv, gpio, value);
 
        value = !!value;
        /* set value */
@@ -64,14 +102,42 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
        return 0;
 }
 
+static int msm_gpio_direction_output_special(struct msm_gpio_bank *priv,
+                                            unsigned int gpio,
+                                            int value)
+{
+       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 0;
+
+       data = &priv->pin_data->special_pins_data[offset];
+
+       if (!data->io_reg || data->out_bit >= 31)
+               return 0;
+
+       value = !!value;
+       /* set value */
+       writel(value << data->out_bit, priv->base + data->io_reg);
+
+       if (!data->ctl_reg || data->oe_bit >= 31)
+               return 0;
+
+       /* switch direction */
+       clrsetbits_le32(priv->base + data->ctl_reg,
+                       BIT(data->oe_bit), BIT(data->oe_bit));
+
+       return 0;
+}
+
 static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
                                     int value)
 {
        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_direction_output_special(priv, gpio, value);
 
        value = !!value;
        /* set value */
@@ -100,13 +166,28 @@ static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flag
        return 0;
 }
 
+static int msm_gpio_get_value_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 0;
+
+       data = &priv->pin_data->special_pins_data[offset];
+
+       if (!data->io_reg || data->in_bit >= 31)
+               return 0;
+
+       return !!(readl(priv->base + data->io_reg) >> data->in_bit);
+}
+
 static int msm_gpio_get_value(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_value_special(priv, gpio);
 
        return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
 }