pinctrl/rockchip: support deferring other gpio params
[ Upstream commit8ce5ef6454
] 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:e7165b1dff
("pinctrl/rockchip: add a queue for deferred pin output settings on probe") Fixes:59dd178e1d
("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>
This commit is contained in:
Родитель
ffea838686
Коммит
dbd72f452e
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче