hwmon: tegra: tsensor: lp0 save/restore configuration
Bitan Biswas [Tue, 19 Jul 2011 12:41:58 +0000 (17:41 +0530)]
tsensor configuration needs to be saved before lp0 and restored
after lp0 resume else POR values are seen after lp0 resume.
- Config0, Config1 and Config2 registers are saved and restored

bug 851791

Original-Change-Id: I95532d995af4fa71e169209bb1788fc4152290fe
Reviewed-on: http://git-master/r/41819
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Tested-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>

Rebase-Id: Raceac7154fc86486f2726cdd13637d7e8d1e6828

drivers/hwmon/tegra-tsensor.c

index 2088b2d..e695ab7 100644 (file)
@@ -176,6 +176,10 @@ struct tegra_tsensor_data {
        int sw_intr_temp;
        int hysteresis;
        unsigned int ts_state_saved[TSENSOR_COUNT];
+       /* save configuration before suspend and restore after resume */
+       unsigned int config0[TSENSOR_COUNT];
+       unsigned int config1[TSENSOR_COUNT];
+       unsigned int config2[TSENSOR_COUNT];
 };
 
 enum {
@@ -1625,6 +1629,59 @@ static int tegra_tsensor_remove(struct platform_device *pdev)
        return 0;
 }
 
+static void dump_a_tsensor_reg(struct tegra_tsensor_data *data,
+       unsigned int addr)
+{
+       dev_dbg(data->hwmon_dev, "\n tsensor[%d][0x%x]: 0x%x ", (addr >> 16),
+               addr & 0xFFFF, tsensor_readl(data, addr));
+}
+
+static void dump_tsensor_regs(struct tegra_tsensor_data *data)
+{
+       int i;
+       for (i = 0; i < TSENSOR_COUNT; i++) {
+               /* if STOP bit is set skip this check */
+               dump_a_tsensor_reg(data, ((i << 16) | SENSOR_CFG0));
+               dump_a_tsensor_reg(data, ((i << 16) | SENSOR_CFG1));
+               dump_a_tsensor_reg(data, ((i << 16) | SENSOR_CFG2));
+               dump_a_tsensor_reg(data, ((i << 16) | SENSOR_STATUS0));
+               dump_a_tsensor_reg(data, ((i << 16) | SENSOR_TS_STATUS1));
+               dump_a_tsensor_reg(data, ((i << 16) | SENSOR_TS_STATUS2));
+               dump_a_tsensor_reg(data, ((i << 16) | 0x0));
+               dump_a_tsensor_reg(data, ((i << 16) | 0x44));
+               dump_a_tsensor_reg(data, ((i << 16) | 0x50));
+               dump_a_tsensor_reg(data, ((i << 16) | 0x54));
+               dump_a_tsensor_reg(data, ((i << 16) | 0x64));
+               dump_a_tsensor_reg(data, ((i << 16) | 0x68));
+       }
+}
+
+static void save_tsensor_regs(struct tegra_tsensor_data *data)
+{
+       int i;
+       for (i = 0; i < TSENSOR_COUNT; i++) {
+               data->config0[i] = tsensor_readl(data,
+                       ((i << 16) | SENSOR_CFG0));
+               data->config1[i] = tsensor_readl(data,
+                       ((i << 16) | SENSOR_CFG1));
+               data->config2[i] = tsensor_readl(data,
+                       ((i << 16) | SENSOR_CFG2));
+       }
+}
+
+static void restore_tsensor_regs(struct tegra_tsensor_data *data)
+{
+       int i;
+       for (i = 0; i < TSENSOR_COUNT; i++) {
+               tsensor_writel(data, data->config0[i],
+                       ((i << 16) | SENSOR_CFG0));
+               tsensor_writel(data, data->config1[i],
+                       ((i << 16) | SENSOR_CFG1));
+               tsensor_writel(data, data->config2[i],
+                       ((i << 16) | SENSOR_CFG2));
+       }
+}
+
 #ifdef CONFIG_PM
 static int tsensor_suspend(struct platform_device *pdev,
        pm_message_t state)
@@ -1632,13 +1689,16 @@ static int tsensor_suspend(struct platform_device *pdev,
        struct tegra_tsensor_data *data = platform_get_drvdata(pdev);
        unsigned int config0;
        int i;
+       dev_dbg(data->hwmon_dev, "\n tsensor before suspend reg dump: ");
+       dump_tsensor_regs(data);
        /* set STOP bit, else OVERFLOW interrupt seen in LP1 */
        for (i = 0; i < TSENSOR_COUNT; i++) {
                config0 = tsensor_readl(data, ((i << 16) | SENSOR_CFG0));
                config0 |= (1 << SENSOR_CFG0_STOP_SHIFT);
                tsensor_writel(data, config0, ((i << 16) | SENSOR_CFG0));
        }
-       /* TBD: check anything else that could be needed for suspend */
+       /* save current settings before suspend, when STOP bit is set */
+       save_tsensor_regs(data);
        tsensor_clk_enable(data, false);
 
        return 0;
@@ -1649,14 +1709,19 @@ static int tsensor_resume(struct platform_device *pdev)
        struct tegra_tsensor_data *data = platform_get_drvdata(pdev);
        unsigned int config0;
        int i;
-       /* TBD: check anything else that could be needed for resume */
        tsensor_clk_enable(data, true);
-       /* clear STOP bit */
+       /* restore current settings before suspend, no need
+        * to clear STOP bit */
+       restore_tsensor_regs(data);
+       /* clear STOP bit, after restoring regs */
        for (i = 0; i < TSENSOR_COUNT; i++) {
                config0 = tsensor_readl(data, ((i << 16) | SENSOR_CFG0));
                config0 &= ~(1 << SENSOR_CFG0_STOP_SHIFT);
                tsensor_writel(data, config0, ((i << 16) | SENSOR_CFG0));
        }
+       msleep(1);
+       dev_dbg(data->hwmon_dev, "\n tsensor after resume reg dump: ");
+       dump_tsensor_regs(data);
 
        return 0;
 }