summaryrefslogtreecommitdiff
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
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>
-rw-r--r--Documentation/devicetree/bindings/input/misc/apds993x.txt7
-rw-r--r--Documentation/devicetree/bindings/input/misc/lis3dh_acc.txt15
-rw-r--r--arch/arm/boot/dts/qcom/msm8916-mtp.dts34
-rw-r--r--arch/arm/boot/dts/qcom/msm8916-qrd-skuh.dtsi19
-rw-r--r--drivers/input/misc/lis3dh_acc.c62
-rw-r--r--drivers/misc/apds993x.c64
6 files changed, 142 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/input/misc/apds993x.txt b/Documentation/devicetree/bindings/input/misc/apds993x.txt
index f1050bc0be19..a371e698b0c8 100644
--- a/Documentation/devicetree/bindings/input/misc/apds993x.txt
+++ b/Documentation/devicetree/bindings/input/misc/apds993x.txt
@@ -4,6 +4,10 @@ Required properties:
- compatible : Should be "avago,apds9930" or "avago,apds9900".
- reg : i2c slave address of the device.
+ - pinctrl-names : The pinctrl configration names of this sensor driver. Should be
+ "default" and "sleep".
+ - pinctrl-0 : Should specify pin control groups used for this controller.
+ - pinctrl-1 : Should specify pin control groups used for this controller.
- interrupt-parent : Parent of interrupt.
- interupts : L/P sample interrupt to indicate new data ready.
- vdd-supply : Power supply needed to power up the device.
@@ -26,6 +30,9 @@ Required properties:
avago@39 {
compatible = "avago,apds9930";
reg = <0x39>;
+ pinctrl-names = "default","sleep";
+ pinctrl-0 = <&apds99xx_default>;
+ pinctrl-1 = <&apds99xx_sleep>;
interrupt-parent = <&msmgpio>;
interrupts = <80 0x2>;
vdd-supply = <&pm8110_l19>;
diff --git a/Documentation/devicetree/bindings/input/misc/lis3dh_acc.txt b/Documentation/devicetree/bindings/input/misc/lis3dh_acc.txt
index f16d1e33660e..29643917f4ee 100644
--- a/Documentation/devicetree/bindings/input/misc/lis3dh_acc.txt
+++ b/Documentation/devicetree/bindings/input/misc/lis3dh_acc.txt
@@ -4,6 +4,10 @@ Required properties:
- compatible : Should be "st,lis3dh".
- reg : i2c slave address of the device.
+ - pinctrl-names : The pinctrl configration names of this sensor driver. Should be
+ "lis3dh_default" and "lis3dh_sleep".
+ - pinctrl-0 : Should specify pin control groups used for this controller.
+ - pinctrl-1 : Should specify pin control groups used for this controller.
- interrupt-parent : Parent of interrupt.
- interrupts : Accelerometer sample interrupt to indicate new data ready.
- vdd-supply : Analog power supply needed to power device.
@@ -55,19 +59,20 @@ Example:
st@18 {
compatible = "st,lis3dh";
reg = <0x18>;
- pinctrl-names = "default";
+ pinctrl-names = "lis3dh_default","lis3dh_sleep";
pinctrl-0 = <&lis3dh_int1_default>;
- interrupt-parent = <&msm_gpio 115 0x2002>;
+ pinctrl-1 = <&lis3dh_int1_sleep>;
+ interrupt-parent = <&msm_gpio>;
interrupts = <115 0x2002>;
- vdd-supply = <&pm8110_l19>;
- vddio-supply = <&pm8110_l14>;
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
st,min-interval = <5>;
st,init-interval = <200>;
st,axis-map-x = <1>;
st,axis-map-y = <0>;
st,axis-map-z = <2>;
st,g-range = <2>;
- st,gpio-int1 = <&msmgpio 81 0x2>;
+ st,gpio-int1 = <&msm_gpio 115 0x2002>;
st,negate-x;
st,negate-y;
st,negate-z;
diff --git a/arch/arm/boot/dts/qcom/msm8916-mtp.dts b/arch/arm/boot/dts/qcom/msm8916-mtp.dts
index fb15f9c2def2..9026595ee521 100644
--- a/arch/arm/boot/dts/qcom/msm8916-mtp.dts
+++ b/arch/arm/boot/dts/qcom/msm8916-mtp.dts
@@ -20,37 +20,3 @@
qcom,board-id = <8 0>;
};
-&tlmm_pinmux {
- apds9930_int_pin {
- qcom,pins = <&gp 113>;
- qcom,pin-func = <0>;
- qcom,num-grp-pins = <1>;
- label = "apds9930-irq";
- apds9930_default: apds9930_default {
- drive-strenghth = <6>;
- bias-pull-up;
- };
- };
-};
-
-&i2c_0 { /* BLSP1 QUP2 */
- avago@39 {
- compatible = "avago,apds9930";
- reg = <0x39>;
- pinctrl-names = "default";
- pinctrl-0 = <&apds9930_default>;
- interrupt-parent = <&msm_gpio>;
- interrupts = <113 0x2>;
- vdd-supply = <&pm8916_l17>;
- vio-supply = <&pm8916_l6>;
- avago,irq-gpio = <&msm_gpio 113 0x2>;
- avago,ps_threshold = <600>;
- avago,ps_hysteresis_threshold = <500>;
- avago,ps_pulse = <8>;
- avago,ps_pgain = <0>;
- avago,als_B = <223>;
- avago,als_C = <70>;
- avago,als_D = <142>;
- avago,ga_value = <48>;
- };
-};
diff --git a/arch/arm/boot/dts/qcom/msm8916-qrd-skuh.dtsi b/arch/arm/boot/dts/qcom/msm8916-qrd-skuh.dtsi
index ae3779503263..3d48561d13f8 100644
--- a/arch/arm/boot/dts/qcom/msm8916-qrd-skuh.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8916-qrd-skuh.dtsi
@@ -21,12 +21,12 @@
qcom,num-grp-pins = <1>;
label = "akm_reset_pin";
akm_default: akm_default {
- drive-strength = <16>;
- bias-pull-up;
+ drive-strength = <6>;
+ bias-pull-up;
};
akm_sleep: akm_sleep {
- drive-strength = <16>;
- bias-pull-down;
+ drive-strength = <2>;
+ bias-pull-down;
};
};
@@ -35,8 +35,12 @@
qcom,num-grp-pins = <1>;
label = "lis3dh_int_pin";
lis3dh_int1_default: int1_default {
- drive-strength = <6>;
- bias-pull-up;
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+ lis3dh_int1_sleep: int1_sleep {
+ drive-strength = <2>;
+ bias-pull-down;
};
};
@@ -108,8 +112,9 @@
st@18 {
compatible = "st,lis3dh";
reg = <0x18>;
- pinctrl-names = "default";
+ pinctrl-names = "lis3dh_default","lis3dh_sleep";
pinctrl-0 = <&lis3dh_int1_default>;
+ pinctrl-1 = <&lis3dh_int1_sleep>;
interrupt-parent = <&msm_gpio>;
vdd-supply = <&pm8916_l17>;
vddio-supply = <&pm8916_l6>;
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: