diff options
| author | Heiner Kallweit <heiner.kallweit@web.de> | 2014-11-08 14:35:54 -0500 |
|---|---|---|
| committer | Eduardo Valentin <edubezval@gmail.com> | 2014-11-09 14:42:53 -0500 |
| commit | 90a21ff5824c3ae8b49c1c0498b137792b935aab (patch) | |
| tree | 6ed150cd27b31178e040f3ed56fefd840da2ae1c | |
| parent | 1d6a27775762110d675f71d7192972c7357b99a7 (diff) | |
imx: thermal: imx_get_temp might be called before sensor clock is prepared
imx_get_temp might be called before the sensor clock is prepared
thus resulting in a timeout of the first attempt to read temp:
thermal thermal_zone0: failed to read out thermal zone 0
Happened to me on a Utilite Standard with IMX6 Dual SoC.
Reason is that in imx_thermal_probe thermal_zone_device_register
is called before the sensor clock is prepared.
thermal_zone_device_register however calls
thermal_zone_device_update which eventually calls imx_get_temp.
Fix this by preparing the clock before calling
thermal_zone_device_register.
Signed-off-by: Heiner Kallweit <heiner.kallweit@web.de>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
| -rw-r--r-- | drivers/thermal/imx_thermal.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 0e35999ad8b2..5a1f1070b702 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c | |||
| @@ -525,6 +525,30 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
| 525 | return ret; | 525 | return ret; |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | data->thermal_clk = devm_clk_get(&pdev->dev, NULL); | ||
| 529 | if (IS_ERR(data->thermal_clk)) { | ||
| 530 | ret = PTR_ERR(data->thermal_clk); | ||
| 531 | if (ret != -EPROBE_DEFER) | ||
| 532 | dev_err(&pdev->dev, | ||
| 533 | "failed to get thermal clk: %d\n", ret); | ||
| 534 | cpufreq_cooling_unregister(data->cdev); | ||
| 535 | return ret; | ||
| 536 | } | ||
| 537 | |||
| 538 | /* | ||
| 539 | * Thermal sensor needs clk on to get correct value, normally | ||
| 540 | * we should enable its clk before taking measurement and disable | ||
| 541 | * clk after measurement is done, but if alarm function is enabled, | ||
| 542 | * hardware will auto measure the temperature periodically, so we | ||
| 543 | * need to keep the clk always on for alarm function. | ||
| 544 | */ | ||
| 545 | ret = clk_prepare_enable(data->thermal_clk); | ||
| 546 | if (ret) { | ||
| 547 | dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret); | ||
| 548 | cpufreq_cooling_unregister(data->cdev); | ||
| 549 | return ret; | ||
| 550 | } | ||
| 551 | |||
| 528 | data->tz = thermal_zone_device_register("imx_thermal_zone", | 552 | data->tz = thermal_zone_device_register("imx_thermal_zone", |
| 529 | IMX_TRIP_NUM, | 553 | IMX_TRIP_NUM, |
| 530 | BIT(IMX_TRIP_PASSIVE), data, | 554 | BIT(IMX_TRIP_PASSIVE), data, |
| @@ -535,26 +559,11 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
| 535 | ret = PTR_ERR(data->tz); | 559 | ret = PTR_ERR(data->tz); |
| 536 | dev_err(&pdev->dev, | 560 | dev_err(&pdev->dev, |
| 537 | "failed to register thermal zone device %d\n", ret); | 561 | "failed to register thermal zone device %d\n", ret); |
| 562 | clk_disable_unprepare(data->thermal_clk); | ||
| 538 | cpufreq_cooling_unregister(data->cdev); | 563 | cpufreq_cooling_unregister(data->cdev); |
| 539 | return ret; | 564 | return ret; |
| 540 | } | 565 | } |
| 541 | 566 | ||
| 542 | data->thermal_clk = devm_clk_get(&pdev->dev, NULL); | ||
| 543 | if (IS_ERR(data->thermal_clk)) { | ||
| 544 | dev_warn(&pdev->dev, "failed to get thermal clk!\n"); | ||
| 545 | } else { | ||
| 546 | /* | ||
| 547 | * Thermal sensor needs clk on to get correct value, normally | ||
| 548 | * we should enable its clk before taking measurement and disable | ||
| 549 | * clk after measurement is done, but if alarm function is enabled, | ||
| 550 | * hardware will auto measure the temperature periodically, so we | ||
| 551 | * need to keep the clk always on for alarm function. | ||
| 552 | */ | ||
| 553 | ret = clk_prepare_enable(data->thermal_clk); | ||
| 554 | if (ret) | ||
| 555 | dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret); | ||
| 556 | } | ||
| 557 | |||
| 558 | /* Enable measurements at ~ 10 Hz */ | 567 | /* Enable measurements at ~ 10 Hz */ |
| 559 | regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); | 568 | regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); |
| 560 | measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ | 569 | measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ |
