diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-11-27 15:24:16 +0530 |
---|---|---|
committer | Laxman Dewangan <ldewangan@nvidia.com> | 2013-11-28 01:24:03 -0800 |
commit | 8416afe381eb7739150b4b89a51713efa926e95a (patch) | |
tree | 4dddc343e3eae83a62069ab0662b1be7325a4341 /drivers/pinctrl | |
parent | ace6cd0b38dbdaca9d8100b19a71b002e030aee5 (diff) |
pinctrl: core: add support to configure user specified states
Currently, pincontrol driver defines three states i.e. default, idle and
sleep. The default state get sets when the pincontrol driver gets
regsitered.
In tegra boards, we define three types of default, commpn pinmux table,
driver setting table and unused low-power pins pinmux tables.
Add the API to support the user specified state names to configure the
pinmux.
Change-Id: I0a6a234e891b5d53dbb8996db47984323463da48
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/336158
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/core.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 5327f35d9b5c..7be3dbab53ee 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1020,6 +1020,65 @@ unapply_new_state: } EXPORT_SYMBOL_GPL(pinctrl_select_state); +int pinctrl_configure_user_state(struct pinctrl_dev *pctldev, + const char *user_state_name) +{ + struct pinctrl_setting *setting, *setting2; + struct pinctrl_state *user_state; + int ret; + + if (!pctldev || IS_ERR(pctldev->p)) { + pr_err("The pincontrol driver is not valid\n"); + return -EINVAL; + } + + user_state = pinctrl_lookup_state(pctldev->p, user_state_name); + if (IS_ERR(user_state)) { + ret = PTR_ERR(user_state); + dev_info(pctldev->dev, "lookup the user state %s not found\n", + user_state_name); + return ret; + } + + list_for_each_entry(setting, &user_state->settings, node) { + switch (setting->type) { + case PIN_MAP_TYPE_MUX_GROUP: + ret = pinmux_enable_setting(setting); + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + ret = pinconf_apply_setting(setting); + break; + default: + ret = -EINVAL; + break; + } + + if (ret < 0) + goto unapply_new_state; + } + return 0; + +unapply_new_state: + dev_err(pctldev->dev, "Error applying setting, reverse things back\n"); + + list_for_each_entry(setting2, &user_state->settings, node) { + if (&setting2->node == &setting->node) + break; + /* + * All we can do here is pinmux_disable_setting. + * That means that some pins are muxed differently now + * than they were before applying the setting (We can't + * "unmux a pin"!), but it's not a big deal since the pins + * are free to be muxed by another apply_setting. + */ + if (setting2->type == PIN_MAP_TYPE_MUX_GROUP) + pinmux_disable_setting(setting2); + } + return ret; +} +EXPORT_SYMBOL_GPL(pinctrl_configure_user_state); + static void devm_pinctrl_release(struct device *dev, void *res) { pinctrl_put(*(struct pinctrl **)res); |