diff mbox

thermal: imx: correct suspend/resume flow

Message ID 1387831918-17028-1-git-send-email-b20788@freescale.com (mailing list archive)
State Superseded, archived
Delegated to: Zhang Rui
Headers show

Commit Message

Anson Huang Dec. 23, 2013, 8:51 p.m. UTC
Current imx thermal sensor's suspend function will return fail if
thermal sensor is always enabled, but because alarm function is enabled,
thermal sensor will be always enabled as well, hence break system's suspend,
this patch will disable thermal sensor before suspend and re-enable it
after resume, it fixes the failure of suspend/resume caused by thermal driver.

Signed-off-by: Anson Huang <b20788@freescale.com>
---
 drivers/thermal/imx_thermal.c |   31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

Comments

Shawn Guo Dec. 23, 2013, 2:29 p.m. UTC | #1
On Mon, Dec 23, 2013 at 03:51:58PM -0500, Anson Huang wrote:
> Current imx thermal sensor's suspend function will return fail if
> thermal sensor is always enabled, but because alarm function is enabled,
> thermal sensor will be always enabled as well, hence break system's suspend,
> this patch will disable thermal sensor before suspend and re-enable it
> after resume, it fixes the failure of suspend/resume caused by thermal driver.

We should probably make it clear in the commit log that it's a
regression caused by commit 37713a1 (thermal: imx: implement thermal
alarm interrupt handling).

> 
> Signed-off-by: Anson Huang <b20788@freescale.com>
> ---
>  drivers/thermal/imx_thermal.c |   31 +++++++++++++++++--------------
>  1 file changed, 17 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
> index cbb16f3..9a9a6c2 100644
> --- a/drivers/thermal/imx_thermal.c
> +++ b/drivers/thermal/imx_thermal.c
> @@ -510,27 +510,30 @@ static int imx_thermal_suspend(struct device *dev)
>  {
>  	struct imx_thermal_data *data = dev_get_drvdata(dev);
>  	struct regmap *map = data->tempmon;
> -	u32 val;
>  
> -	regmap_read(map, TEMPSENSE0, &val);
> -	if ((val & TEMPSENSE0_POWER_DOWN) == 0) {
> -		/*
> -		 * If a measurement is taking place, wait for a long enough
> -		 * time for it to finish, and then check again.  If it still
> -		 * does not finish, something must go wrong.
> -		 */
> -		udelay(50);
> -		regmap_read(map, TEMPSENSE0, &val);
> -		if ((val & TEMPSENSE0_POWER_DOWN) == 0)
> -			return -ETIMEDOUT;
> -	}
> +	/*
> +	 * Need to disable thermal sensor, otherwise, when thermal core
> +	 * try to get temperature before thermal sensor resume, a wrong
> +	 * temperature will be read as the thermal sensor is powered
> +	 * down.
> +	 */
> +	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
> +	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
> +	data->mode = THERMAL_DEVICE_DISABLED;

Is it really necessary to update data->mode through suspend/resume
cycle?

Shawn

>  
>  	return 0;
>  }
>  
>  static int imx_thermal_resume(struct device *dev)
>  {
> -	/* Nothing to do for now */
> +	struct imx_thermal_data *data = dev_get_drvdata(dev);
> +	struct regmap *map = data->tempmon;
> +
> +	/* Enabled thermal sensor after resume */
> +	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
> +	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
> +	data->mode = THERMAL_DEVICE_ENABLED;
> +
>  	return 0;
>  }
>  #endif
> -- 
> 1.7.9.5
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anson.Huang@freescale.com Dec. 23, 2013, 2:33 p.m. UTC | #2
Sent from Anson's iPhone

> ? 2013?12?23??22:28?"Shawn Guo" <shawn.guo@linaro.org> ???

> 

>> On Mon, Dec 23, 2013 at 03:51:58PM -0500, Anson Huang wrote:

>> Current imx thermal sensor's suspend function will return fail if

>> thermal sensor is always enabled, but because alarm function is enabled,

>> thermal sensor will be always enabled as well, hence break system's suspend,

>> this patch will disable thermal sensor before suspend and re-enable it

>> after resume, it fixes the failure of suspend/resume caused by thermal driver.

> 

> We should probably make it clear in the commit log that it's a

> regression caused by commit 37713a1 (thermal: imx: implement thermal

> alarm interrupt handling).


agreed, will improve the commit log in V2.

> 

>> 

>> Signed-off-by: Anson Huang <b20788@freescale.com>

>> ---

>> drivers/thermal/imx_thermal.c |   31 +++++++++++++++++--------------

>> 1 file changed, 17 insertions(+), 14 deletions(-)

>> 

>> diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c

>> index cbb16f3..9a9a6c2 100644

>> --- a/drivers/thermal/imx_thermal.c

>> +++ b/drivers/thermal/imx_thermal.c

>> @@ -510,27 +510,30 @@ static int imx_thermal_suspend(struct device *dev)

>> {

>>    struct imx_thermal_data *data = dev_get_drvdata(dev);

>>    struct regmap *map = data->tempmon;

>> -    u32 val;

>> 

>> -    regmap_read(map, TEMPSENSE0, &val);

>> -    if ((val & TEMPSENSE0_POWER_DOWN) == 0) {

>> -        /*

>> -         * If a measurement is taking place, wait for a long enough

>> -         * time for it to finish, and then check again.  If it still

>> -         * does not finish, something must go wrong.

>> -         */

>> -        udelay(50);

>> -        regmap_read(map, TEMPSENSE0, &val);

>> -        if ((val & TEMPSENSE0_POWER_DOWN) == 0)

>> -            return -ETIMEDOUT;

>> -    }

>> +    /*

>> +     * Need to disable thermal sensor, otherwise, when thermal core

>> +     * try to get temperature before thermal sensor resume, a wrong

>> +     * temperature will be read as the thermal sensor is powered

>> +     * down.

>> +     */

>> +    regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);

>> +    regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);

>> +    data->mode = THERMAL_DEVICE_DISABLED;

> 

> Is it really necessary to update data->mode through suspend/resume

> cycle?


Yes, as the thermal core may try to get temperature before imx thermal sensor resume, if not setting its mode to disabled, thermal core will get a wrong temp and caused system power off by mistake, as the get_temp function will decide whether to power up thermal core according to its mode.

> 

> Shawn

> 

>> 

>>    return 0;

>> }

>> 

>> static int imx_thermal_resume(struct device *dev)

>> {

>> -    /* Nothing to do for now */

>> +    struct imx_thermal_data *data = dev_get_drvdata(dev);

>> +    struct regmap *map = data->tempmon;

>> +

>> +    /* Enabled thermal sensor after resume */

>> +    regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);

>> +    regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);

>> +    data->mode = THERMAL_DEVICE_ENABLED;

>> +

>>    return 0;

>> }

>> #endif

>> -- 

>> 1.7.9.5

>
diff mbox

Patch

diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index cbb16f3..9a9a6c2 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -510,27 +510,30 @@  static int imx_thermal_suspend(struct device *dev)
 {
 	struct imx_thermal_data *data = dev_get_drvdata(dev);
 	struct regmap *map = data->tempmon;
-	u32 val;
 
-	regmap_read(map, TEMPSENSE0, &val);
-	if ((val & TEMPSENSE0_POWER_DOWN) == 0) {
-		/*
-		 * If a measurement is taking place, wait for a long enough
-		 * time for it to finish, and then check again.  If it still
-		 * does not finish, something must go wrong.
-		 */
-		udelay(50);
-		regmap_read(map, TEMPSENSE0, &val);
-		if ((val & TEMPSENSE0_POWER_DOWN) == 0)
-			return -ETIMEDOUT;
-	}
+	/*
+	 * Need to disable thermal sensor, otherwise, when thermal core
+	 * try to get temperature before thermal sensor resume, a wrong
+	 * temperature will be read as the thermal sensor is powered
+	 * down.
+	 */
+	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
+	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+	data->mode = THERMAL_DEVICE_DISABLED;
 
 	return 0;
 }
 
 static int imx_thermal_resume(struct device *dev)
 {
-	/* Nothing to do for now */
+	struct imx_thermal_data *data = dev_get_drvdata(dev);
+	struct regmap *map = data->tempmon;
+
+	/* Enabled thermal sensor after resume */
+	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
+	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+	data->mode = THERMAL_DEVICE_ENABLED;
+
 	return 0;
 }
 #endif