summaryrefslogtreecommitdiff
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-11-27 15:24:16 +0530
committerLaxman Dewangan <ldewangan@nvidia.com>2013-11-28 01:24:03 -0800
commit8416afe381eb7739150b4b89a51713efa926e95a (patch)
tree4dddc343e3eae83a62069ab0662b1be7325a4341 /drivers/pinctrl
parentace6cd0b38dbdaca9d8100b19a71b002e030aee5 (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.c59
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);