]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
misc: nct1008: Add new suspend mode for Tegra LP1
authorDaniel Solomon <daniels@nvidia.com>
Thu, 4 Apr 2013 00:53:12 +0000 (17:53 -0700)
committerDan Willemsen <dwillemsen@nvidia.com>
Sat, 14 Sep 2013 20:13:41 +0000 (13:13 -0700)
For Tegra devices, it is desirable to keep the NCT1008/72
device awake during some suspend states.

Add new "suspend mode" to support this feature, if
CONFIG_TEGRA_LP1_LOW_COREVOLTAGE is set. Required
parameters are passed in through board file data.

Bug 1261915

Change-Id: Ibae7e6a661d817c0cc514373b934665d68d063b7
Signed-off-by: Daniel Solomon <daniels@nvidia.com>
Reviewed-on: http://git-master/r/216368
(Cherry picked from e02beb3f82f4164c834797a1855e716645abaf7a)
Reviewed-on: http://git-master/r/226484
Reviewed-by: Karthik Ramakrishnan <karthikr@nvidia.com>
Tested-by: Karthik Ramakrishnan <karthikr@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
GVS: Gerrit_Virtual_Submit

drivers/misc/nct1008.c

index 8ff03402120e3ecd41d7a6cf4a9aee46a680d70c..2f3e4870da9bf9a137c6c8b2eadd5f3052a49275 100644 (file)
@@ -1224,7 +1224,7 @@ static void nct1008_shutdown(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int nct1008_suspend(struct device *dev)
+static int nct1008_suspend_powerdown(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        int err;
@@ -1237,11 +1237,83 @@ static int nct1008_suspend(struct device *dev)
        return err;
 }
 
-static int nct1008_resume(struct device *dev)
+static int nct1008_suspend_wakeup(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        int err;
        struct nct1008_data *data = i2c_get_clientdata(client);
+       long ext_temp;
+
+       err = nct1008_get_temp(dev, &ext_temp, 0);
+       if (err)
+               goto error;
+
+       if (ext_temp > data->plat_data.suspend_ext_limit_lo)
+               err = nct1008_thermal_set_limits(data,
+                       data->plat_data.suspend_ext_limit_lo,
+                       NCT1008_MAX_TEMP * 1000);
+       else
+               err = nct1008_thermal_set_limits(data,
+                       NCT1008_MIN_TEMP * 1000,
+                       data->plat_data.suspend_ext_limit_hi);
+
+       if (err)
+               goto error;
+
+       /* Enable NCT wake */
+       err = enable_irq_wake(client->irq);
+       if (err)
+               dev_err(&client->dev, "Error: %s, error=%d. failed to enable NCT "
+                               "wakeup\n", __func__, err);
+
+
+       return err;
+
+error:
+       dev_err(&client->dev, "\n error in file=: %s %s() line=%d: "
+               "error=%d. Can't set correct LP1 alarm limits or set wakeup irq, "
+               "shutting down device", __FILE__, __func__, __LINE__, err);
+
+       return nct1008_suspend_powerdown(dev);
+}
+
+static int nct1008_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct nct1008_data *data = i2c_get_clientdata(client);
+
+       if (data->plat_data.suspend_with_wakeup &&
+               data->plat_data.suspend_with_wakeup())
+               return nct1008_suspend_wakeup(dev);
+       else
+               return nct1008_suspend_powerdown(dev);
+}
+
+
+static int nct1008_resume_wakeup(struct device *dev)
+{
+       int err = 0;
+       struct i2c_client *client = to_i2c_client(dev);
+
+       err = disable_irq_wake(client->irq);
+       if (err) {
+               dev_err(&client->dev, "Error: %s, error=%d. failed to disable NCT "
+                               "wakeup\n", __func__, err);
+               return err;
+       }
+
+       /* NCT wasn't powered down, so IRQ is still enabled. */
+       /* Disable it before calling update */
+       disable_irq(client->irq);
+
+       return err;
+}
+
+static int nct1008_resume_powerdown(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int err = 0;
+       struct nct1008_data *data = i2c_get_clientdata(client);
 
        nct1008_power_control(data, true);
        nct1008_configure_sensor(data);
@@ -1251,6 +1323,25 @@ static int nct1008_resume(struct device *dev)
                        __func__, err);
                return err;
        }
+
+       return err;
+}
+
+static int nct1008_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int err;
+       struct nct1008_data *data = i2c_get_clientdata(client);
+
+       if (data->plat_data.suspend_with_wakeup &&
+               data->plat_data.suspend_with_wakeup())
+               err = nct1008_resume_wakeup(dev);
+       else
+               err = nct1008_resume_powerdown(dev);
+
+       if (err)
+               return err;
+
        nct1008_update(data);
        enable_irq(client->irq);