pinctrl: stm32: add possibility to configure pins individually
authorAlexandre Torgue <alexandre.torgue@st.com>
Mon, 15 Jun 2020 12:59:51 +0000 (14:59 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Sat, 20 Jun 2020 21:08:00 +0000 (23:08 +0200)
Adds the possibility to configure a single pin through the gpiolib (i.e:
to set PULL_UP/PULL_DOWN config).
Mutex behavior is slightly changed to avoid a deadlock when pin_config_set
is called (in this case pctldev->mutex is already taken).

Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com>
Link: https://lore.kernel.org/r/20200615125951.28008-3-alexandre.torgue@st.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/stm32/pinctrl-stm32.c

index cdf6b01d1956f2ebb52b81b05581a44eec6f01bc..faf2660298f5c0ebefac6ced4e8aea36514e8551 100644 (file)
@@ -303,6 +303,7 @@ static const struct gpio_chip stm32_gpio_template = {
        .direction_output       = stm32_gpio_direction_output,
        .to_irq                 = stm32_gpio_to_irq,
        .get_direction          = stm32_gpio_get_direction,
+       .set_config             = gpiochip_generic_config,
 };
 
 static void stm32_gpio_irq_trigger(struct irq_data *d)
@@ -1052,7 +1053,7 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
        struct stm32_gpio_bank *bank;
        int offset, ret = 0;
 
-       range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin);
        if (!range) {
                dev_err(pctl->dev, "No gpio range defined.\n");
                return -EINVAL;
@@ -1110,9 +1111,11 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
        int i, ret;
 
        for (i = 0; i < num_configs; i++) {
+               mutex_lock(&pctldev->mutex);
                ret = stm32_pconf_parse_conf(pctldev, g->pin,
                        pinconf_to_config_param(configs[i]),
                        pinconf_to_config_argument(configs[i]));
+               mutex_unlock(&pctldev->mutex);
                if (ret < 0)
                        return ret;
 
@@ -1122,6 +1125,22 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
        return 0;
 }
 
+static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+                          unsigned long *configs, unsigned int num_configs)
+{
+       int i, ret;
+
+       for (i = 0; i < num_configs; i++) {
+               ret = stm32_pconf_parse_conf(pctldev, pin,
+                               pinconf_to_config_param(configs[i]),
+                               pinconf_to_config_argument(configs[i]));
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
                                 struct seq_file *s,
                                 unsigned int pin)
@@ -1187,10 +1206,10 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
        }
 }
 
-
 static const struct pinconf_ops stm32_pconf_ops = {
        .pin_config_group_get   = stm32_pconf_group_get,
        .pin_config_group_set   = stm32_pconf_group_set,
+       .pin_config_set         = stm32_pconf_set,
        .pin_config_dbg_show    = stm32_pconf_dbg_show,
 };