Commit 8ce5ef64 authored by Caleb Connolly's avatar Caleb Connolly Committed by Linus Walleij

pinctrl/rockchip: support deferring other gpio params

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: e7165b1d ("pinctrl/rockchip: add a queue for deferred pin output settings on probe")
Fixes: 59dd178e ("gpio/rockchip: fetch deferred output settings on probe")
Signed-off-by: default avatarCaleb Connolly <kc@postmarketos.org>
Link: https://lore.kernel.org/r/20220328005005.72492-2-kc@postmarketos.orgSigned-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent bf3e7f49
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include "../pinctrl/core.h" #include "../pinctrl/core.h"
...@@ -706,7 +707,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev) ...@@ -706,7 +707,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
struct device_node *pctlnp = of_get_parent(np); struct device_node *pctlnp = of_get_parent(np);
struct pinctrl_dev *pctldev = NULL; struct pinctrl_dev *pctldev = NULL;
struct rockchip_pin_bank *bank = NULL; struct rockchip_pin_bank *bank = NULL;
struct rockchip_pin_output_deferred *cfg; struct rockchip_pin_deferred *cfg;
static int gpio; static int gpio;
int id, ret; int id, ret;
...@@ -747,15 +748,22 @@ static int rockchip_gpio_probe(struct platform_device *pdev) ...@@ -747,15 +748,22 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
return ret; return ret;
} }
while (!list_empty(&bank->deferred_output)) { while (!list_empty(&bank->deferred_pins)) {
cfg = list_first_entry(&bank->deferred_output, cfg = list_first_entry(&bank->deferred_pins,
struct rockchip_pin_output_deferred, head); struct rockchip_pin_deferred, head);
list_del(&cfg->head); list_del(&cfg->head);
ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); switch (cfg->param) {
if (ret) case PIN_CONFIG_OUTPUT:
dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg); 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); kfree(cfg);
} }
......
...@@ -2095,19 +2095,20 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, ...@@ -2095,19 +2095,20 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
return false; return false;
} }
static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank, static int rockchip_pinconf_defer_pin(struct rockchip_pin_bank *bank,
unsigned int pin, u32 arg) unsigned int pin, u32 param, u32 arg)
{ {
struct rockchip_pin_output_deferred *cfg; struct rockchip_pin_deferred *cfg;
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg) if (!cfg)
return -ENOMEM; return -ENOMEM;
cfg->pin = pin; cfg->pin = pin;
cfg->param = param;
cfg->arg = arg; cfg->arg = arg;
list_add_tail(&cfg->head, &bank->deferred_output); list_add_tail(&cfg->head, &bank->deferred_pins);
return 0; return 0;
} }
...@@ -2128,6 +2129,25 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, ...@@ -2128,6 +2129,25 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(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) { switch (param) {
case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_DISABLE:
rc = rockchip_set_pull(bank, pin - bank->pin_base, rc = rockchip_set_pull(bank, pin - bank->pin_base,
...@@ -2156,22 +2176,6 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, ...@@ -2156,22 +2176,6 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
if (rc != RK_FUNC_GPIO) if (rc != RK_FUNC_GPIO)
return -EINVAL; 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, rc = gpio->direction_output(gpio, pin - bank->pin_base,
arg); arg);
if (rc) if (rc)
...@@ -2485,7 +2489,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, ...@@ -2485,7 +2489,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
pdesc++; pdesc++;
} }
INIT_LIST_HEAD(&pin_bank->deferred_output); INIT_LIST_HEAD(&pin_bank->deferred_pins);
mutex_init(&pin_bank->deferred_lock); mutex_init(&pin_bank->deferred_lock);
} }
...@@ -2748,7 +2752,7 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev) ...@@ -2748,7 +2752,7 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev)
{ {
struct rockchip_pinctrl *info = platform_get_drvdata(pdev); struct rockchip_pinctrl *info = platform_get_drvdata(pdev);
struct rockchip_pin_bank *bank; struct rockchip_pin_bank *bank;
struct rockchip_pin_output_deferred *cfg; struct rockchip_pin_deferred *cfg;
int i; int i;
of_platform_depopulate(&pdev->dev); of_platform_depopulate(&pdev->dev);
...@@ -2757,9 +2761,9 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev) ...@@ -2757,9 +2761,9 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev)
bank = &info->ctrl->pin_banks[i]; bank = &info->ctrl->pin_banks[i];
mutex_lock(&bank->deferred_lock); mutex_lock(&bank->deferred_lock);
while (!list_empty(&bank->deferred_output)) { while (!list_empty(&bank->deferred_pins)) {
cfg = list_first_entry(&bank->deferred_output, cfg = list_first_entry(&bank->deferred_pins,
struct rockchip_pin_output_deferred, head); struct rockchip_pin_deferred, head);
list_del(&cfg->head); list_del(&cfg->head);
kfree(cfg); kfree(cfg);
} }
......
...@@ -171,7 +171,7 @@ struct rockchip_pin_bank { ...@@ -171,7 +171,7 @@ struct rockchip_pin_bank {
u32 toggle_edge_mode; u32 toggle_edge_mode;
u32 recalced_mask; u32 recalced_mask;
u32 route_mask; u32 route_mask;
struct list_head deferred_output; struct list_head deferred_pins;
struct mutex deferred_lock; struct mutex deferred_lock;
}; };
...@@ -247,9 +247,12 @@ struct rockchip_pin_config { ...@@ -247,9 +247,12 @@ struct rockchip_pin_config {
unsigned int nconfigs; unsigned int nconfigs;
}; };
struct rockchip_pin_output_deferred { enum pin_config_param;
struct rockchip_pin_deferred {
struct list_head head; struct list_head head;
unsigned int pin; unsigned int pin;
enum pin_config_param param;
u32 arg; u32 arg;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment