summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorVevek Venkatesan <vevekv@codeaurora.org>2016-09-30 21:29:22 +0530
committerShantanu Jain <shjain@codeaurora.org>2016-10-14 14:37:26 +0530
commit1e5dde5a4cf503d7c37deb435defc6ad4b6712d8 (patch)
treed39b99067df90bc96aa204a0bd830de78a55f572 /drivers/input
parent3ef7b5c53ec92b76f6a63c8bfa080f108cf456a4 (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.c137
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_ots.h3
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