pinctrl/rockchip: support deferring other gpio params
authorCaleb Connolly <kc@postmarketos.org>
Mon, 28 Mar 2022 00:50:02 +0000 (01:50 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:23:07 +0000 (10:23 +0200)
[ Upstream commit 8ce5ef64546850294b021497046588a7abcebe96 ]

Add support for deferring other params like PIN_CONFIG_INPUT_ENABLE.
This will be used to add support for PIN_CONFIG_INPUT_ENABLE to the
driver.

Fixes: e7165b1dff06 ("pinctrl/rockchip: add a queue for deferred pin output settings on probe")
Fixes: 59dd178e1d7c ("gpio/rockchip: fetch deferred output settings on probe")
Signed-off-by: Caleb Connolly <kc@postmarketos.org>
Link: https://lore.kernel.org/r/20220328005005.72492-2-kc@postmarketos.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpio/gpio-rockchip.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinctrl-rockchip.h

index 24155c0..22b8f0a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/regmap.h>
 
 #include "../pinctrl/core.h"
@@ -691,7 +692,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
        struct device_node *pctlnp = of_get_parent(np);
        struct pinctrl_dev *pctldev = NULL;
        struct rockchip_pin_bank *bank = NULL;
-       struct rockchip_pin_output_deferred *cfg;
+       struct rockchip_pin_deferred *cfg;
        static int gpio;
        int id, ret;
 
@@ -732,15 +733,22 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
                return ret;
        }
 
-       while (!list_empty(&bank->deferred_output)) {
-               cfg = list_first_entry(&bank->deferred_output,
-                                      struct rockchip_pin_output_deferred, head);
+       while (!list_empty(&bank->deferred_pins)) {
+               cfg = list_first_entry(&bank->deferred_pins,
+                                      struct rockchip_pin_deferred, head);
                list_del(&cfg->head);
 
-               ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg);
-               if (ret)
-                       dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg);
-
+               switch (cfg->param) {
+               case PIN_CONFIG_OUTPUT:
+                       ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg);
+                       if (ret)
+                               dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin,
+                                        cfg->arg);
+                       break;
+               default:
+                       dev_warn(dev, "unknown deferred config param %d\n", cfg->param);
+                       break;
+               }
                kfree(cfg);
        }
 
index 543a499..d808420 100644 (file)
@@ -2107,19 +2107,20 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
        return false;
 }
 
-static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank,
-                                        unsigned int pin, u32 arg)
+static int rockchip_pinconf_defer_pin(struct rockchip_pin_bank *bank,
+                                        unsigned int pin, u32 param, u32 arg)
 {
-       struct rockchip_pin_output_deferred *cfg;
+       struct rockchip_pin_deferred *cfg;
 
        cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
        if (!cfg)
                return -ENOMEM;
 
        cfg->pin = pin;
+       cfg->param = param;
        cfg->arg = arg;
 
-       list_add_tail(&cfg->head, &bank->deferred_output);
+       list_add_tail(&cfg->head, &bank->deferred_pins);
 
        return 0;
 }
@@ -2140,6 +2141,25 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
                param = pinconf_to_config_param(configs[i]);
                arg = pinconf_to_config_argument(configs[i]);
 
+               if (param == (PIN_CONFIG_OUTPUT | PIN_CONFIG_INPUT_ENABLE)) {
+                       /*
+                        * Check for gpio driver not being probed yet.
+                        * The lock makes sure that either gpio-probe has completed
+                        * or the gpio driver hasn't probed yet.
+                        */
+                       mutex_lock(&bank->deferred_lock);
+                       if (!gpio || !gpio->direction_output) {
+                               rc = rockchip_pinconf_defer_pin(bank, pin - bank->pin_base, param,
+                                                               arg);
+                               mutex_unlock(&bank->deferred_lock);
+                               if (rc)
+                                       return rc;
+
+                               break;
+                       }
+                       mutex_unlock(&bank->deferred_lock);
+               }
+
                switch (param) {
                case PIN_CONFIG_BIAS_DISABLE:
                        rc =  rockchip_set_pull(bank, pin - bank->pin_base,
@@ -2168,22 +2188,6 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
                        if (rc != RK_FUNC_GPIO)
                                return -EINVAL;
 
-                       /*
-                        * Check for gpio driver not being probed yet.
-                        * The lock makes sure that either gpio-probe has completed
-                        * or the gpio driver hasn't probed yet.
-                        */
-                       mutex_lock(&bank->deferred_lock);
-                       if (!gpio || !gpio->direction_output) {
-                               rc = rockchip_pinconf_defer_output(bank, pin - bank->pin_base, arg);
-                               mutex_unlock(&bank->deferred_lock);
-                               if (rc)
-                                       return rc;
-
-                               break;
-                       }
-                       mutex_unlock(&bank->deferred_lock);
-
                        rc = gpio->direction_output(gpio, pin - bank->pin_base,
                                                    arg);
                        if (rc)
@@ -2504,7 +2508,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
                        pdesc++;
                }
 
-               INIT_LIST_HEAD(&pin_bank->deferred_output);
+               INIT_LIST_HEAD(&pin_bank->deferred_pins);
                mutex_init(&pin_bank->deferred_lock);
        }
 
@@ -2778,7 +2782,7 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev)
 {
        struct rockchip_pinctrl *info = platform_get_drvdata(pdev);
        struct rockchip_pin_bank *bank;
-       struct rockchip_pin_output_deferred *cfg;
+       struct rockchip_pin_deferred *cfg;
        int i;
 
        of_platform_depopulate(&pdev->dev);
@@ -2787,9 +2791,9 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev)
                bank = &info->ctrl->pin_banks[i];
 
                mutex_lock(&bank->deferred_lock);
-               while (!list_empty(&bank->deferred_output)) {
-                       cfg = list_first_entry(&bank->deferred_output,
-                                              struct rockchip_pin_output_deferred, head);
+               while (!list_empty(&bank->deferred_pins)) {
+                       cfg = list_first_entry(&bank->deferred_pins,
+                                              struct rockchip_pin_deferred, head);
                        list_del(&cfg->head);
                        kfree(cfg);
                }
index 91f1027..98a01a6 100644 (file)
@@ -171,7 +171,7 @@ struct rockchip_pin_bank {
        u32                             toggle_edge_mode;
        u32                             recalced_mask;
        u32                             route_mask;
-       struct list_head                deferred_output;
+       struct list_head                deferred_pins;
        struct mutex                    deferred_lock;
 };
 
@@ -247,9 +247,12 @@ struct rockchip_pin_config {
        unsigned int            nconfigs;
 };
 
-struct rockchip_pin_output_deferred {
+enum pin_config_param;
+
+struct rockchip_pin_deferred {
        struct list_head head;
        unsigned int pin;
+       enum pin_config_param param;
        u32 arg;
 };