From 6e9b68133112f094d1b82b9ce854853b84480895 Mon Sep 17 00:00:00 2001 From: Bitan Biswas Date: Tue, 19 Jul 2011 18:11:58 +0530 Subject: hwmon: tegra: tsensor: lp0 save/restore configuration 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 Tested-by: Bitan Biswas Reviewed-by: Narendra Damahe Reviewed-by: Laxman Dewangan Rebase-Id: Raceac7154fc86486f2726cdd13637d7e8d1e6828 --- drivers/hwmon/tegra-tsensor.c | 71 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tegra-tsensor.c b/drivers/hwmon/tegra-tsensor.c index 7e0f002fc4dd..ae274474e1a7 100644 --- a/drivers/hwmon/tegra-tsensor.c +++ b/drivers/hwmon/tegra-tsensor.c @@ -174,6 +174,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 { @@ -1623,6 +1627,59 @@ static int __devexit 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) @@ -1630,13 +1687,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; @@ -1647,14 +1707,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; } -- cgit v1.2.3