diff options
| author | Vevek Venkatesan <vevekv@codeaurora.org> | 2016-09-30 21:29:22 +0530 |
|---|---|---|
| committer | Shantanu Jain <shjain@codeaurora.org> | 2016-10-14 14:37:26 +0530 |
| commit | 1e5dde5a4cf503d7c37deb435defc6ad4b6712d8 (patch) | |
| tree | d39b99067df90bc96aa204a0bd830de78a55f572 /drivers/input | |
| parent | 3ef7b5c53ec92b76f6a63c8bfa080f108cf456a4 (diff) | |
input: misc: pat9125: add gpio configuration and pinctrl support
Pat9125 is a gpio driven i2c slave. This change adds the gpio
configuration and pinctrl support for pat9125 driver.
Change-Id: I2a9b379715622b5f010a5780ca481da7f9619400
Signed-off-by: Vevek Venkatesan <vevekv@codeaurora.org>
Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/misc/ots_pat9125/pat9125_linux_driver.c | 137 | ||||
| -rw-r--r-- | drivers/input/misc/ots_pat9125/pixart_ots.h | 3 |
2 files changed, 114 insertions, 26 deletions
diff --git a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c index fa44b7d866f8..ac4caa48312d 100644 --- a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c +++ b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c @@ -18,11 +18,14 @@ struct pixart_pat9125_data { struct i2c_client *client; struct input_dev *input; int irq_gpio; - u32 irq_flags; u32 press_keycode; bool press_en; bool inverse_x; bool inverse_y; + struct pinctrl *pinctrl; + struct pinctrl_state *pinctrl_state_active; + struct pinctrl_state *pinctrl_state_suspend; + struct pinctrl_state *pinctrl_state_release; }; static int pat9125_i2c_write(struct i2c_client *client, u8 reg, u8 *data, @@ -197,6 +200,44 @@ static struct attribute_group pat9125_attr_grp = { .attrs = pat9125_attr_list, }; +static int pixart_pinctrl_init(struct pixart_pat9125_data *data) +{ + int err; + struct device *dev = &data->client->dev; + + data->pinctrl = devm_pinctrl_get(&(data->client->dev)); + if (IS_ERR_OR_NULL(data->pinctrl)) { + err = PTR_ERR(data->pinctrl); + dev_err(dev, "Target does not use pinctrl %d\n", err); + return err; + } + + data->pinctrl_state_active = pinctrl_lookup_state(data->pinctrl, + PINCTRL_STATE_ACTIVE); + if (IS_ERR_OR_NULL(data->pinctrl_state_active)) { + err = PTR_ERR(data->pinctrl_state_active); + dev_err(dev, "Can not lookup active pinctrl state %d\n", err); + return err; + } + + data->pinctrl_state_suspend = pinctrl_lookup_state(data->pinctrl, + PINCTRL_STATE_SUSPEND); + if (IS_ERR_OR_NULL(data->pinctrl_state_suspend)) { + err = PTR_ERR(data->pinctrl_state_suspend); + dev_err(dev, "Can not lookup suspend pinctrl state %d\n", err); + return err; + } + + data->pinctrl_state_release = pinctrl_lookup_state(data->pinctrl, + PINCTRL_STATE_RELEASE); + if (IS_ERR_OR_NULL(data->pinctrl_state_release)) { + err = PTR_ERR(data->pinctrl_state_release); + dev_err(dev, "Can not lookup release pinctrl state %d\n", err); + return err; + } + return 0; +} + static int pat9125_parse_dt(struct device *dev, struct pixart_pat9125_data *data) { @@ -218,6 +259,9 @@ static int pat9125_parse_dt(struct device *dev, } } + data->irq_gpio = of_get_named_gpio_flags(np, "pixart,irq-gpio", + 0, NULL); + return 0; } @@ -272,24 +316,39 @@ static int pat9125_i2c_probe(struct i2c_client *client, err = input_register_device(data->input); if (err < 0) { dev_err(dev, "Failed to register input device\n"); - goto err_register_input_device; - } - - if (!gpio_is_valid(data->irq_gpio)) { - dev_err(dev, "invalid irq_gpio: %d\n", data->irq_gpio); - return -EINVAL; - } - - err = gpio_request(data->irq_gpio, "pixart_pat9125_irq_gpio"); - if (err) { - dev_err(dev, "unable to request gpio %d\n", data->irq_gpio); return err; } - err = gpio_direction_input(data->irq_gpio); - if (err) { - dev_err(dev, "unable to set dir for gpio %d\n", data->irq_gpio); - goto free_gpio; + err = pixart_pinctrl_init(data); + if (!err && data->pinctrl) { + /* + * Pinctrl handle is optional. If pinctrl handle is found + * let pins to be configured in active state. If not + * found continue further without error. + */ + err = pinctrl_select_state(data->pinctrl, + data->pinctrl_state_active); + if (err < 0) + dev_err(dev, "Could not set pin to active state %d\n", + err); + } else { + if (gpio_is_valid(data->irq_gpio)) { + err = devm_gpio_request(dev, data->irq_gpio, + "pixart_pat9125_irq_gpio"); + if (err) { + dev_err(dev, "Couldn't request gpio %d\n", err); + return err; + } + err = gpio_direction_input(data->irq_gpio); + if (err) { + dev_err(dev, "Couldn't set dir for gpio %d\n", + err); + return err; + } + } else { + dev_err(dev, "Invalid gpio %d\n", data->irq_gpio); + return -EINVAL; + } } if (!ots_sensor_init(client)) { @@ -316,33 +375,59 @@ static int pat9125_i2c_probe(struct i2c_client *client, err_sysfs_create: err_request_threaded_irq: err_sensor_init: -free_gpio: - gpio_free(data->irq_gpio); -err_register_input_device: - input_free_device(data->input); + if (data->pinctrl) + if (pinctrl_select_state(data->pinctrl, + data->pinctrl_state_release) < 0) + dev_err(dev, "Couldn't set pin to release state\n"); + return err; } static int pat9125_i2c_remove(struct i2c_client *client) { struct pixart_pat9125_data *data = i2c_get_clientdata(client); + struct device *dev = &data->client->dev; - devm_free_irq(&client->dev, client->irq, data); - if (gpio_is_valid(data->irq_gpio)) - gpio_free(data->irq_gpio); - input_unregister_device(data->input); - devm_kfree(&client->dev, data); - data = NULL; + if (data->pinctrl) + if (pinctrl_select_state(data->pinctrl, + data->pinctrl_state_release) < 0) + dev_err(dev, "Couldn't set pin to release state\n"); return 0; } static int pat9125_suspend(struct device *dev) { + int rc; + struct pixart_pat9125_data *data = + (struct pixart_pat9125_data *)dev->driver_data; + + disable_irq(data->client->irq); + if (data->pinctrl) { + rc = pinctrl_select_state(data->pinctrl, + data->pinctrl_state_suspend); + if (rc < 0) + dev_err(dev, "Could not set pin to suspend state %d\n", + rc); + } + return 0; } static int pat9125_resume(struct device *dev) { + int rc; + struct pixart_pat9125_data *data = + (struct pixart_pat9125_data *)dev->driver_data; + + if (data->pinctrl) { + rc = pinctrl_select_state(data->pinctrl, + data->pinctrl_state_active); + if (rc < 0) + dev_err(dev, "Could not set pin to active state %d\n", + rc); + } + enable_irq(data->client->irq); + return 0; } diff --git a/drivers/input/misc/ots_pat9125/pixart_ots.h b/drivers/input/misc/ots_pat9125/pixart_ots.h index 91813929d811..824d6bafd9bf 100644 --- a/drivers/input/misc/ots_pat9125/pixart_ots.h +++ b/drivers/input/misc/ots_pat9125/pixart_ots.h @@ -10,6 +10,9 @@ #define PAT9125_DEV_NAME "pixart_pat9125" #define MAX_BUF_SIZE 20 #define RESET_DELAY_US 1000 +#define PINCTRL_STATE_ACTIVE "pmx_rot_switch_active" +#define PINCTRL_STATE_SUSPEND "pmx_rot_switch_suspend" +#define PINCTRL_STATE_RELEASE "pmx_rot_switch_release" /* Register addresses */ #define PIXART_PAT9125_PRODUCT_ID1_REG 0x00 |
