summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt25
-rw-r--r--drivers/input/misc/ots_pat9125/pat9125_linux_driver.c137
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_ots.h3
3 files changed, 139 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt b/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
index 1b68c695d2c5..54ba2be39f0c 100644
--- a/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
+++ b/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
@@ -15,6 +15,25 @@ Optional properties:
- pixart,inverse-x : boolean, use this to invert the x data before sending it to input framework
- pixart,inverse-y : boolean, use this to invert the y data before sending it to input framework
- pixart,press-enabled : boolean, use this to enable detection of pressing the button
+ - pinctrl-names : This should be defined if a target uses pinctrl framework.
+ See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt
+ It should specify the names of the configs that pinctrl can
+ install in driver.
+ Following are the pinctrl configs that can be installed:
+ "pmx_rot_switch_active" : Active configuration of pins,
+ it should specify active config
+ defined in pin groups of
+ interrupt gpio.
+ "pmx_rot_switch_suspend" : Disabled configuration of
+ pins, it should specify sleep
+ config defined in pin groups
+ of interrupt gpio.
+ "pmx_rot_switch_release" : Release configuration of
+ pins, it should specify release
+ config defined in pin groups of
+ interrupt gpio.
+ - pixart,irq-gpio : This should be defined if a target doesn't use pinctrl framework.
+ irq gpio, which is to provide interrupts to host, same as "interrupts" node.
Required properties if 'pixart,press-enabled' DT property is defined:
- pixart,press-keycode : keycode to be sent when press is detected by the driver.
@@ -26,4 +45,10 @@ Example:
interrupt-parent = <&msm_gpio>;
interrupts = <98 0x2008>;
pixart,irq-gpio = <&msm_gpio 98 0x2008>;
+ pinctrl-names = "pmx_rot_switch_active",
+ "pmx_rot_switch_suspend",
+ "pmx_rot_switch_release";
+ pinctrl-0 = <&pix_int_active>;
+ pinctrl-1 = <&pix_int_suspend>;
+ pinctrl-2 = <&pix_release>;
};
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