From eeaabccc1c7b5220d8d5674669662e8ca0c07ec0 Mon Sep 17 00:00:00 2001 From: Bingzhe Cai Date: Tue, 6 May 2014 19:26:33 +0800 Subject: 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 --- .../devicetree/bindings/input/misc/apds993x.txt | 7 +++ .../devicetree/bindings/input/misc/lis3dh_acc.txt | 15 +++-- arch/arm/boot/dts/qcom/msm8916-mtp.dts | 34 ------------ arch/arm/boot/dts/qcom/msm8916-qrd-skuh.dtsi | 19 ++++--- drivers/input/misc/lis3dh_acc.c | 62 ++++++++++++++++++--- drivers/misc/apds993x.c | 64 ++++++++++++++++++++-- 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: -- cgit v1.2.3