summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBingzhe Cai <bingzhec@codeaurora.org>2014-05-06 19:26:33 +0800
committerBingzhe Cai <bingzhec@codeaurora.org>2014-05-12 16:42:54 +0800
commiteeaabccc1c7b5220d8d5674669662e8ca0c07ec0 (patch)
tree5c91023831cf8dc5187e274906bf252ccd8b5cde /drivers
parent27f64aa9a37d7faa18abc82aee8c392e83a0cff9 (diff)
input: sensors: pull down 8916SKUH sensor GPIOs for power saving
As sensor will power down during suspend, those GPIOs used by sensors also need pull down to minimize leakage. CRs-fixed: 655099 Change-Id: If9463e0cc89675204b9b4bee5eca2dd5a44515a5 Signed-off-by: Bingzhe Cai <bingzhec@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/misc/lis3dh_acc.c62
-rw-r--r--drivers/misc/apds993x.c64
2 files changed, 113 insertions, 13 deletions
diff --git a/drivers/input/misc/lis3dh_acc.c b/drivers/input/misc/lis3dh_acc.c
index d58ec0d5c374..662c27fe64c3 100644
--- a/drivers/input/misc/lis3dh_acc.c
+++ b/drivers/input/misc/lis3dh_acc.c
@@ -221,6 +221,9 @@ struct lis3dh_acc_data {
struct i2c_client *client;
struct lis3dh_acc_platform_data *pdata;
struct sensors_classdev cdev;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pin_default;
+ struct pinctrl_state *pin_sleep;
struct mutex lock;
struct delayed_work input_work;
@@ -513,11 +516,6 @@ static void lis3dh_acc_device_power_off(struct lis3dh_acc_data *acc)
if (err < 0)
dev_err(&acc->client->dev, "soft power off failed: %d\n", err);
- if (gpio_is_valid(acc->pdata->gpio_int1))
- disable_irq_nosync(acc->irq1);
- if (gpio_is_valid(acc->pdata->gpio_int2))
- disable_irq_nosync(acc->irq2);
-
lis3dh_acc_config_regulator(acc, false);
if (acc->hw_initialized) {
@@ -540,10 +538,6 @@ static int lis3dh_acc_device_power_on(struct lis3dh_acc_data *acc)
return err;
}
- if (gpio_is_valid(acc->pdata->gpio_int1))
- enable_irq(acc->irq1);
- if (gpio_is_valid(acc->pdata->gpio_int2))
- enable_irq(acc->irq2);
msleep(20);
@@ -774,6 +768,10 @@ static int lis3dh_acc_enable(struct lis3dh_acc_data *acc)
int err;
if (!atomic_cmpxchg(&acc->enabled, 0, 1)) {
+ if (pinctrl_select_state(acc->pinctrl, acc->pin_default))
+ dev_err(&acc->client->dev,
+ "Can't select pinctrl default state\n");
+
err = lis3dh_acc_device_power_on(acc);
if (err < 0) {
atomic_set(&acc->enabled, 0);
@@ -791,6 +789,9 @@ static int lis3dh_acc_disable(struct lis3dh_acc_data *acc)
if (atomic_cmpxchg(&acc->enabled, 1, 0)) {
cancel_delayed_work_sync(&acc->input_work);
lis3dh_acc_device_power_off(acc);
+ if (pinctrl_select_state(acc->pinctrl, acc->pin_sleep))
+ dev_err(&acc->client->dev,
+ "Can't select pinctrl sleep state\n");
}
return 0;
@@ -1300,6 +1301,33 @@ static void lis3dh_acc_input_cleanup(struct lis3dh_acc_data *acc)
input_free_device(acc->input_dev);
}
+static int lis3dh_pinctrl_init(struct lis3dh_acc_data *acc)
+{
+ struct i2c_client *client = acc->client;
+
+ acc->pinctrl = devm_pinctrl_get(&client->dev);
+ if (IS_ERR_OR_NULL(acc->pinctrl)) {
+ dev_err(&client->dev, "Failed to get pinctrl\n");
+ return PTR_ERR(acc->pinctrl);
+ }
+
+ acc->pin_default =
+ pinctrl_lookup_state(acc->pinctrl, "lis3dh_default");
+ if (IS_ERR_OR_NULL(acc->pin_default)) {
+ dev_err(&client->dev, "Failed to look up default state\n");
+ return PTR_ERR(acc->pin_default);
+ }
+
+ acc->pin_sleep =
+ pinctrl_lookup_state(acc->pinctrl, "lis3dh_sleep");
+ if (IS_ERR_OR_NULL(acc->pin_sleep)) {
+ dev_err(&client->dev, "Failed to look up sleep state\n");
+ return PTR_ERR(acc->pin_sleep);
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_OF
static int lis3dh_parse_dt(struct device *dev,
struct lis3dh_acc_platform_data *pdata)
@@ -1454,6 +1482,18 @@ static int lis3dh_acc_probe(struct i2c_client *client,
goto exit_kfree_pdata;
}
+ /* initialize pinctrl */
+ err = lis3dh_pinctrl_init(acc);
+ if (err) {
+ dev_err(&client->dev, "Can't initialize pinctrl\n");
+ goto exit_kfree_pdata;
+ }
+ err = pinctrl_select_state(acc->pinctrl, acc->pin_default);
+ if (err) {
+ dev_err(&client->dev,
+ "Can't select pinctrl default state\n");
+ goto exit_kfree_pdata;
+ }
if (acc->pdata->init) {
err = acc->pdata->init();
@@ -1579,6 +1619,10 @@ static int lis3dh_acc_probe(struct i2c_client *client,
disable_irq_nosync(acc->irq2);
}
+ if (pinctrl_select_state(acc->pinctrl, acc->pin_sleep))
+ dev_err(&client->dev,
+ "Can't select pinctrl sleep state\n");
+
mutex_unlock(&acc->lock);
dev_dbg(&client->dev, "%s: probed\n", LIS3DH_ACC_DEV_NAME);
diff --git a/drivers/misc/apds993x.c b/drivers/misc/apds993x.c
index fe76eb99d310..1305cb6c94d9 100644
--- a/drivers/misc/apds993x.c
+++ b/drivers/misc/apds993x.c
@@ -214,6 +214,9 @@ struct apds993x_data {
struct regulator *vio;
struct sensors_classdev als_cdev;
struct sensors_classdev ps_cdev;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pin_default;
+ struct pinctrl_state *pin_sleep;
struct apds993x_platform_data *platform_data;
int irq;
@@ -2097,9 +2100,22 @@ static int sensor_regulator_power_on(struct apds993x_data *data, bool on)
static int sensor_platform_hw_power_on(bool on)
{
+ int err;
+
if (pdev_data == NULL)
return -ENODEV;
+ if (!IS_ERR_OR_NULL(pdev_data->pinctrl)) {
+ if (on)
+ err = pinctrl_select_state(pdev_data->pinctrl,
+ pdev_data->pin_default);
+ else
+ err = pinctrl_select_state(pdev_data->pinctrl,
+ pdev_data->pin_sleep);
+ if (err)
+ dev_err(&pdev_data->client->dev,
+ "Can't select pinctrl state\n");
+ }
sensor_regulator_power_on(pdev_data, on);
return 0;
@@ -2153,6 +2169,33 @@ static void sensor_platform_hw_exit(void)
gpio_free(data->platform_data->irq_gpio);
}
+static int apds993x_pinctrl_init(struct apds993x_data *data)
+{
+ struct i2c_client *client = data->client;
+
+ data->pinctrl = devm_pinctrl_get(&client->dev);
+ if (IS_ERR_OR_NULL(data->pinctrl)) {
+ dev_err(&client->dev, "Failed to get pinctrl\n");
+ return PTR_ERR(data->pinctrl);
+ }
+
+ data->pin_default =
+ pinctrl_lookup_state(data->pinctrl, "default");
+ if (IS_ERR_OR_NULL(data->pin_default)) {
+ dev_err(&client->dev, "Failed to look up default state\n");
+ return PTR_ERR(data->pin_default);
+ }
+
+ data->pin_sleep =
+ pinctrl_lookup_state(data->pinctrl, "sleep");
+ if (IS_ERR_OR_NULL(data->pin_sleep)) {
+ dev_err(&client->dev, "Failed to look up sleep state\n");
+ return PTR_ERR(data->pin_sleep);
+ }
+
+ return 0;
+}
+
static int sensor_parse_dt(struct device *dev,
struct apds993x_platform_data *pdata)
{
@@ -2300,6 +2343,19 @@ static int apds993x_probe(struct i2c_client *client,
data->client = client;
apds993x_i2c_client = client;
+ /* initialize pinctrl */
+ err = apds993x_pinctrl_init(data);
+ if (err) {
+ dev_err(&client->dev, "Can't initialize pinctrl\n");
+ goto exit_kfree;
+ }
+ err = pinctrl_select_state(data->pinctrl, data->pin_default);
+ if (err) {
+ dev_err(&client->dev,
+ "Can't select pinctrl default state\n");
+ goto exit_kfree;
+ }
+
/* h/w initialization */
if (pdata->init)
err = pdata->init();
@@ -2344,14 +2400,14 @@ static int apds993x_probe(struct i2c_client *client,
err = apds993x_init_client(client);
if (err) {
pr_err("%s: Failed to init apds993x\n", __func__);
- goto exit_kfree;
+ goto exit_uninit;
}
err = request_irq(data->irq, apds993x_interrupt, IRQF_TRIGGER_FALLING,
APDS993X_DRV_NAME, (void *)client);
if (err < 0) {
pr_err("%s: Could not allocate APDS993X_INT !\n", __func__);
- goto exit_kfree;
+ goto exit_uninit;
}
irq_set_irq_wake(client->irq, 1);
@@ -2456,12 +2512,12 @@ exit_free_dev_ps:
exit_free_dev_als:
exit_free_irq:
free_irq(data->irq, client);
-exit_kfree:
+exit_uninit:
if (pdata->power_on)
pdata->power_on(false);
if (pdata->exit)
pdata->exit();
-
+exit_kfree:
kfree(data);
pdev_data = NULL;
exit: