input: touch: sharp: fix power sequence/leakage
David Pu [Fri, 21 Aug 2015 21:30:33 +0000 (14:30 -0700)]
added dynamic spi4 pinmux controll to avoid power sequence violation and
power leakage.

Bug 1650903
Bug 200129779

Change-Id: I3c33c42376c687fff2fe5573a679f86aafaa6a98
Signed-off-by: David Pu <dpu@nvidia.com>
Reviewed-on: http://git-master/r/787576
(cherry picked from commit 0f80768cd1fc6cb30b6075991ab2dce8ae9faab1)
Reviewed-on: http://git-master/r/804356
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jordan Nien <jnien@nvidia.com>
Tested-by: Jordan Nien <jnien@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>

drivers/input/touchscreen/lr388k7_ts.c

index a38e014..64485b2 100644 (file)
@@ -2,6 +2,7 @@
  * LR388K7 touchscreen driver
  *
  * Copyright (C) 2014, Sharp Corporation
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
  *
  * Author: Makoto Itsuki <itsuki.makoto@sharp.co.jp>
  *
@@ -133,6 +134,10 @@ struct lr388k7 {
        struct spi_device       *spi;
        struct device           *dev;
        struct input_dev        *idev;
+       struct pinctrl          *pinctrl;
+       struct pinctrl_state    *spi_intf_en;
+       struct pinctrl_state    *spi_intf_dis;
+
 #if defined(ACTIVE_ENABLE)
        struct input_dev        *idev_active;
        int                     tool;
@@ -2163,6 +2168,38 @@ static struct lr388k7_platform_data *lr388k7_parse_dt(struct device *dev,
        return ERR_PTR(ret);
 }
 
+static void init_spi_pinctrl(struct lr388k7 *ts, struct device *dev)
+{
+       struct pinctrl *pin = NULL;
+       struct pinctrl_state *active, *inactive;
+
+       pin = devm_pinctrl_get(dev);
+       if (IS_ERR(pin)) {
+               dev_err(dev, "missing pinctrl device\n");
+               return;
+       }
+       ts->pinctrl = pin;
+
+       active = pinctrl_lookup_state(pin, "spi_intf_normal");
+       if (IS_ERR_OR_NULL(active)) {
+               dev_err(dev, "missing spi_intf_normal state\n");
+               goto out;
+       }
+       ts->spi_intf_en = active;
+       inactive = pinctrl_lookup_state(pin, "spi_intf_lowpower");
+       if (IS_ERR_OR_NULL(active)) {
+               dev_err(dev, "missing spi_intf_lowpower state\n");
+               goto out;
+       }
+       ts->spi_intf_dis = inactive;
+
+       return;
+out:
+       if (ts->pinctrl)
+               ts->pinctrl = NULL;
+
+}
+
 static int lr388k7_probe(struct spi_device *spi)
 {
        struct lr388k7_platform_data *pdata;/* = spi->dev.platform_data;*/
@@ -2284,6 +2321,8 @@ static int lr388k7_probe(struct spi_device *spi)
        gpio_set_value(ts->gpio_reset, 0);
        g_st_state.b_is_reset = true;
 
+       init_spi_pinctrl(ts, dev);
+
        /* regulator */
        ts->regulator_3v3 = devm_regulator_get(&g_spi->dev, "avdd");
        if (IS_ERR(ts->regulator_3v3)) {
@@ -2619,6 +2658,10 @@ static void lr388k7_start(struct lr388k7 *ts)
 
        usleep_range(5000, 6000);
 
+       if (ts->spi_intf_en)
+               pinctrl_select_state(ts->pinctrl,
+                       ts->spi_intf_en);
+
        /*
         * Enable clock, if necessary
         */
@@ -2664,6 +2707,12 @@ static void lr388k7_ctrl_suspend(struct lr388k7 *ts)
                return;
        }
 
+       gpio_set_value(ts->gpio_reset, 0);
+
+       if (ts->spi_intf_dis)
+               pinctrl_select_state(ts->pinctrl,
+                               ts->spi_intf_dis);
+
        /* Disable (3.3V) */
        if (ts->regulator_3v3) {
                error = regulator_disable(ts->regulator_3v3);