Skip to content

Commit 4cf2ddf

Browse files
oleremdlezcano
authored andcommitted
thermal/drivers/imx: Implement runtime PM support
Starting with commit d92ed2c ("thermal: imx: Use driver's local data to decide whether to run a measurement") this driver stared using irq_enabled flag to make decision to power on/off the thermal core. This triggered a regression, where after reaching critical temperature, alarm IRQ handler set irq_enabled to false, disabled thermal core and was not able read temperature and disable cooling sequence. In case the cooling device is "CPU/GPU freq", the system will run with reduce performance until next reboot. To solve this issue, we need to move all parts implementing hand made runtime power management and let it handle actual runtime PM framework. Fixes: d92ed2c ("thermal: imx: Use driver's local data to decide whether to run a measurement") Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Tested-by: Petr Beneš <petr.benes@ysoft.com> Link: https://lore.kernel.org/r/20211117103426.81813-1-o.rempel@pengutronix.de Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
1 parent fa55b7d commit 4cf2ddf

File tree

1 file changed

+91
-54
lines changed

1 file changed

+91
-54
lines changed

drivers/thermal/imx_thermal.c

Lines changed: 91 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/regmap.h>
1616
#include <linux/thermal.h>
1717
#include <linux/nvmem-consumer.h>
18+
#include <linux/pm_runtime.h>
1819

1920
#define REG_SET 0x4
2021
#define REG_CLR 0x8
@@ -194,6 +195,7 @@ static struct thermal_soc_data thermal_imx7d_data = {
194195
};
195196

196197
struct imx_thermal_data {
198+
struct device *dev;
197199
struct cpufreq_policy *policy;
198200
struct thermal_zone_device *tz;
199201
struct thermal_cooling_device *cdev;
@@ -252,44 +254,15 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
252254
const struct thermal_soc_data *soc_data = data->socdata;
253255
struct regmap *map = data->tempmon;
254256
unsigned int n_meas;
255-
bool wait, run_measurement;
256257
u32 val;
258+
int ret;
257259

258-
run_measurement = !data->irq_enabled;
259-
if (!run_measurement) {
260-
/* Check if a measurement is currently in progress */
261-
regmap_read(map, soc_data->temp_data, &val);
262-
wait = !(val & soc_data->temp_valid_mask);
263-
} else {
264-
/*
265-
* Every time we measure the temperature, we will power on the
266-
* temperature sensor, enable measurements, take a reading,
267-
* disable measurements, power off the temperature sensor.
268-
*/
269-
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
270-
soc_data->power_down_mask);
271-
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
272-
soc_data->measure_temp_mask);
273-
274-
wait = true;
275-
}
276-
277-
/*
278-
* According to the temp sensor designers, it may require up to ~17us
279-
* to complete a measurement.
280-
*/
281-
if (wait)
282-
usleep_range(20, 50);
260+
ret = pm_runtime_resume_and_get(data->dev);
261+
if (ret < 0)
262+
return ret;
283263

284264
regmap_read(map, soc_data->temp_data, &val);
285265

286-
if (run_measurement) {
287-
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
288-
soc_data->measure_temp_mask);
289-
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
290-
soc_data->power_down_mask);
291-
}
292-
293266
if ((val & soc_data->temp_valid_mask) == 0) {
294267
dev_dbg(&tz->device, "temp measurement never finished\n");
295268
return -EAGAIN;
@@ -328,31 +301,25 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
328301
enable_irq(data->irq);
329302
}
330303

304+
pm_runtime_put(data->dev);
305+
331306
return 0;
332307
}
333308

334309
static int imx_change_mode(struct thermal_zone_device *tz,
335310
enum thermal_device_mode mode)
336311
{
337312
struct imx_thermal_data *data = tz->devdata;
338-
struct regmap *map = data->tempmon;
339-
const struct thermal_soc_data *soc_data = data->socdata;
340313

341314
if (mode == THERMAL_DEVICE_ENABLED) {
342-
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
343-
soc_data->power_down_mask);
344-
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
345-
soc_data->measure_temp_mask);
315+
pm_runtime_get(data->dev);
346316

347317
if (!data->irq_enabled) {
348318
data->irq_enabled = true;
349319
enable_irq(data->irq);
350320
}
351321
} else {
352-
regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
353-
soc_data->measure_temp_mask);
354-
regmap_write(map, soc_data->sensor_ctrl + REG_SET,
355-
soc_data->power_down_mask);
322+
pm_runtime_put(data->dev);
356323

357324
if (data->irq_enabled) {
358325
disable_irq(data->irq);
@@ -393,6 +360,11 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
393360
int temp)
394361
{
395362
struct imx_thermal_data *data = tz->devdata;
363+
int ret;
364+
365+
ret = pm_runtime_resume_and_get(data->dev);
366+
if (ret < 0)
367+
return ret;
396368

397369
/* do not allow changing critical threshold */
398370
if (trip == IMX_TRIP_CRITICAL)
@@ -406,6 +378,8 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
406378

407379
imx_set_alarm_temp(data, temp);
408380

381+
pm_runtime_put(data->dev);
382+
409383
return 0;
410384
}
411385

@@ -681,6 +655,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
681655
if (!data)
682656
return -ENOMEM;
683657

658+
data->dev = &pdev->dev;
659+
684660
map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
685661
if (IS_ERR(map)) {
686662
ret = PTR_ERR(map);
@@ -800,6 +776,16 @@ static int imx_thermal_probe(struct platform_device *pdev)
800776
data->socdata->power_down_mask);
801777
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
802778
data->socdata->measure_temp_mask);
779+
/* After power up, we need a delay before first access can be done. */
780+
usleep_range(20, 50);
781+
782+
/* the core was configured and enabled just before */
783+
pm_runtime_set_active(&pdev->dev);
784+
pm_runtime_enable(data->dev);
785+
786+
ret = pm_runtime_resume_and_get(data->dev);
787+
if (ret < 0)
788+
goto disable_runtime_pm;
803789

804790
data->irq_enabled = true;
805791
ret = thermal_zone_device_enable(data->tz);
@@ -814,10 +800,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
814800
goto thermal_zone_unregister;
815801
}
816802

803+
pm_runtime_put(data->dev);
804+
817805
return 0;
818806

819807
thermal_zone_unregister:
820808
thermal_zone_device_unregister(data->tz);
809+
disable_runtime_pm:
810+
pm_runtime_put_noidle(data->dev);
811+
pm_runtime_disable(data->dev);
821812
clk_disable:
822813
clk_disable_unprepare(data->thermal_clk);
823814
legacy_cleanup:
@@ -829,13 +820,9 @@ static int imx_thermal_probe(struct platform_device *pdev)
829820
static int imx_thermal_remove(struct platform_device *pdev)
830821
{
831822
struct imx_thermal_data *data = platform_get_drvdata(pdev);
832-
struct regmap *map = data->tempmon;
833823

834-
/* Disable measurements */
835-
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
836-
data->socdata->power_down_mask);
837-
if (!IS_ERR(data->thermal_clk))
838-
clk_disable_unprepare(data->thermal_clk);
824+
pm_runtime_put_noidle(data->dev);
825+
pm_runtime_disable(data->dev);
839826

840827
thermal_zone_device_unregister(data->tz);
841828
imx_thermal_unregister_legacy_cooling(data);
@@ -858,29 +845,79 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev)
858845
ret = thermal_zone_device_disable(data->tz);
859846
if (ret)
860847
return ret;
848+
849+
return pm_runtime_force_suspend(data->dev);
850+
}
851+
852+
static int __maybe_unused imx_thermal_resume(struct device *dev)
853+
{
854+
struct imx_thermal_data *data = dev_get_drvdata(dev);
855+
int ret;
856+
857+
ret = pm_runtime_force_resume(data->dev);
858+
if (ret)
859+
return ret;
860+
/* Enabled thermal sensor after resume */
861+
return thermal_zone_device_enable(data->tz);
862+
}
863+
864+
static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev)
865+
{
866+
struct imx_thermal_data *data = dev_get_drvdata(dev);
867+
const struct thermal_soc_data *socdata = data->socdata;
868+
struct regmap *map = data->tempmon;
869+
int ret;
870+
871+
ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
872+
socdata->measure_temp_mask);
873+
if (ret)
874+
return ret;
875+
876+
ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
877+
socdata->power_down_mask);
878+
if (ret)
879+
return ret;
880+
861881
clk_disable_unprepare(data->thermal_clk);
862882

863883
return 0;
864884
}
865885

866-
static int __maybe_unused imx_thermal_resume(struct device *dev)
886+
static int __maybe_unused imx_thermal_runtime_resume(struct device *dev)
867887
{
868888
struct imx_thermal_data *data = dev_get_drvdata(dev);
889+
const struct thermal_soc_data *socdata = data->socdata;
890+
struct regmap *map = data->tempmon;
869891
int ret;
870892

871893
ret = clk_prepare_enable(data->thermal_clk);
872894
if (ret)
873895
return ret;
874-
/* Enabled thermal sensor after resume */
875-
ret = thermal_zone_device_enable(data->tz);
896+
897+
ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
898+
socdata->power_down_mask);
899+
if (ret)
900+
return ret;
901+
902+
ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
903+
socdata->measure_temp_mask);
876904
if (ret)
877905
return ret;
878906

907+
/*
908+
* According to the temp sensor designers, it may require up to ~17us
909+
* to complete a measurement.
910+
*/
911+
usleep_range(20, 50);
912+
879913
return 0;
880914
}
881915

882-
static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
883-
imx_thermal_suspend, imx_thermal_resume);
916+
static const struct dev_pm_ops imx_thermal_pm_ops = {
917+
SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)
918+
SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend,
919+
imx_thermal_runtime_resume, NULL)
920+
};
884921

885922
static struct platform_driver imx_thermal = {
886923
.driver = {

0 commit comments

Comments
 (0)