diff options
author | Shantanu Jain <shjain@codeaurora.org> | 2014-03-11 16:09:57 +0530 |
---|---|---|
committer | Shantanu Jain <shjain@codeaurora.org> | 2017-02-10 17:29:50 +0530 |
commit | c26a324755f986614785921594510b7b57779af2 (patch) | |
tree | 4d46015fe70c465d553e86a55d3a03338fab818d /drivers | |
parent | 2aa89ab3ff59a788321bc6af782d639cfc8dab1f (diff) |
input: gpio_keys: Add support for pinctrl framework
Add pinctrl framework support for gpio configuration
to gpio_keys driver.
Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
Change-Id: I50c46caca0a65f8906f816e04f89610497956eea
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 91 |
1 files changed, 88 insertions, 3 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index cbf603ed5916..517b08b3bc0c 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -31,6 +31,7 @@ #include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/spinlock.h> +#include <linux/pinctrl/consumer.h> struct gpio_button_data { const struct gpio_keys_button *button; @@ -50,6 +51,7 @@ struct gpio_button_data { struct gpio_keys_drvdata { const struct gpio_keys_platform_data *pdata; + struct pinctrl *key_pinctrl; struct input_dev *input; struct mutex disable_lock; struct gpio_button_data data[0]; @@ -564,6 +566,41 @@ static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) input_sync(input); } +static int gpio_keys_pinctrl_configure(struct gpio_keys_drvdata *ddata, + bool active) +{ + struct pinctrl_state *set_state; + int retval; + + if (active) { + set_state = + pinctrl_lookup_state(ddata->key_pinctrl, + "tlmm_gpio_key_active"); + if (IS_ERR(set_state)) { + dev_err(&ddata->input->dev, + "cannot get ts pinctrl active state\n"); + return PTR_ERR(set_state); + } + } else { + set_state = + pinctrl_lookup_state(ddata->key_pinctrl, + "tlmm_gpio_key_suspend"); + if (IS_ERR(set_state)) { + dev_err(&ddata->input->dev, + "cannot get gpiokey pinctrl sleep state\n"); + return PTR_ERR(set_state); + } + } + retval = pinctrl_select_state(ddata->key_pinctrl, set_state); + if (retval) { + dev_err(&ddata->input->dev, + "cannot set ts pinctrl active state\n"); + return retval; + } + + return 0; +} + static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); @@ -708,6 +745,7 @@ static int gpio_keys_probe(struct platform_device *pdev) size_t size; int i, error; int wakeup = 0; + struct pinctrl_state *set_state; if (!pdata) { pdata = gpio_keys_get_devtree_pdata(dev); @@ -751,13 +789,31 @@ static int gpio_keys_probe(struct platform_device *pdev) if (pdata->rep) __set_bit(EV_REP, input->evbit); + /* Get pinctrl if target uses pinctrl */ + ddata->key_pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(ddata->key_pinctrl)) { + if (PTR_ERR(ddata->key_pinctrl) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + pr_debug("Target does not use pinctrl\n"); + ddata->key_pinctrl = NULL; + } + + if (ddata->key_pinctrl) { + error = gpio_keys_pinctrl_configure(ddata, true); + if (error) { + dev_err(dev, "cannot set ts pinctrl active state\n"); + return error; + } + } + for (i = 0; i < pdata->nbuttons; i++) { const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) - return error; + goto err_setup_key; if (button->wakeup) wakeup = 1; @@ -767,7 +823,7 @@ static int gpio_keys_probe(struct platform_device *pdev) if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); - return error; + goto err_create_sysfs; } error = input_register_device(input); @@ -783,6 +839,18 @@ static int gpio_keys_probe(struct platform_device *pdev) err_remove_group: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); +err_create_sysfs: +err_setup_key: + if (ddata->key_pinctrl) { + set_state = + pinctrl_lookup_state(ddata->key_pinctrl, + "tlmm_gpio_key_suspend"); + if (IS_ERR(set_state)) + dev_err(dev, "cannot get gpiokey pinctrl sleep state\n"); + else + pinctrl_select_state(ddata->key_pinctrl, set_state); + } + return error; } @@ -800,7 +868,7 @@ static int gpio_keys_suspend(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct input_dev *input = ddata->input; - int i; + int i, ret; if (device_may_wakeup(dev)) { for (i = 0; i < ddata->pdata->nbuttons; i++) { @@ -815,6 +883,14 @@ static int gpio_keys_suspend(struct device *dev) mutex_unlock(&input->mutex); } + if (ddata->key_pinctrl) { + ret = gpio_keys_pinctrl_configure(ddata, false); + if (ret) { + dev_err(dev, "failed to put the pin in suspend state\n"); + return ret; + } + } + return 0; } @@ -841,6 +917,15 @@ static int gpio_keys_resume(struct device *dev) if (error) return error; + if (ddata->key_pinctrl) { + error = gpio_keys_pinctrl_configure(ddata, true); + if (error) { + dev_err(dev, "failed to put the pin in resume state\n"); + return error; + } + } + + gpio_keys_report_state(ddata); return 0; } |