From 244b2c5ca8b14627e4a17755e5922221e121c771 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 09 Oct 2024 06:15:07 +0000
Subject: [PATCH] change system file
---
kernel/drivers/thermal/imx_thermal.c | 293 +++++++++++++++++++++++++++++++---------------------------
1 files changed, 156 insertions(+), 137 deletions(-)
diff --git a/kernel/drivers/thermal/imx_thermal.c b/kernel/drivers/thermal/imx_thermal.c
index aa452ac..1666337 100644
--- a/kernel/drivers/thermal/imx_thermal.c
+++ b/kernel/drivers/thermal/imx_thermal.c
@@ -3,25 +3,19 @@
// Copyright 2013 Freescale Semiconductor, Inc.
#include <linux/clk.h>
-#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpu_cooling.h>
#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/platform_device.h>
#include <linux/regmap.h>
-#include <linux/slab.h>
#include <linux/thermal.h>
-#include <linux/types.h>
#include <linux/nvmem-consumer.h>
+#include <linux/pm_runtime.h>
#define REG_SET 0x4
#define REG_CLR 0x8
@@ -201,10 +195,10 @@
};
struct imx_thermal_data {
+ struct device *dev;
struct cpufreq_policy *policy;
struct thermal_zone_device *tz;
struct thermal_cooling_device *cdev;
- enum thermal_device_mode mode;
struct regmap *tempmon;
u32 c1, c2; /* See formula in imx_init_calib() */
int temp_passive;
@@ -260,42 +254,14 @@
const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
unsigned int n_meas;
- bool wait;
u32 val;
+ int ret;
- if (data->mode == THERMAL_DEVICE_ENABLED) {
- /* Check if a measurement is currently in progress */
- regmap_read(map, soc_data->temp_data, &val);
- wait = !(val & soc_data->temp_valid_mask);
- } else {
- /*
- * Every time we measure the temperature, we will power on the
- * temperature sensor, enable measurements, take a reading,
- * disable measurements, power off the temperature sensor.
- */
- regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
- soc_data->power_down_mask);
- regmap_write(map, soc_data->sensor_ctrl + REG_SET,
- soc_data->measure_temp_mask);
-
- wait = true;
- }
-
- /*
- * According to the temp sensor designers, it may require up to ~17us
- * to complete a measurement.
- */
- if (wait)
- usleep_range(20, 50);
+ ret = pm_runtime_resume_and_get(data->dev);
+ if (ret < 0)
+ return ret;
regmap_read(map, soc_data->temp_data, &val);
-
- if (data->mode != THERMAL_DEVICE_ENABLED) {
- regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
- soc_data->measure_temp_mask);
- regmap_write(map, soc_data->sensor_ctrl + REG_SET,
- soc_data->power_down_mask);
- }
if ((val & soc_data->temp_valid_mask) == 0) {
dev_dbg(&tz->device, "temp measurement never finished\n");
@@ -335,56 +301,31 @@
enable_irq(data->irq);
}
- return 0;
-}
-
-static int imx_get_mode(struct thermal_zone_device *tz,
- enum thermal_device_mode *mode)
-{
- struct imx_thermal_data *data = tz->devdata;
-
- *mode = data->mode;
+ pm_runtime_put(data->dev);
return 0;
}
-static int imx_set_mode(struct thermal_zone_device *tz,
- enum thermal_device_mode mode)
+static int imx_change_mode(struct thermal_zone_device *tz,
+ enum thermal_device_mode mode)
{
struct imx_thermal_data *data = tz->devdata;
- struct regmap *map = data->tempmon;
- const struct thermal_soc_data *soc_data = data->socdata;
if (mode == THERMAL_DEVICE_ENABLED) {
- tz->polling_delay = IMX_POLLING_DELAY;
- tz->passive_delay = IMX_PASSIVE_DELAY;
-
- regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
- soc_data->power_down_mask);
- regmap_write(map, soc_data->sensor_ctrl + REG_SET,
- soc_data->measure_temp_mask);
+ pm_runtime_get(data->dev);
if (!data->irq_enabled) {
data->irq_enabled = true;
enable_irq(data->irq);
}
} else {
- regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
- soc_data->measure_temp_mask);
- regmap_write(map, soc_data->sensor_ctrl + REG_SET,
- soc_data->power_down_mask);
-
- tz->polling_delay = 0;
- tz->passive_delay = 0;
+ pm_runtime_put(data->dev);
if (data->irq_enabled) {
disable_irq(data->irq);
data->irq_enabled = false;
}
}
-
- data->mode = mode;
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
return 0;
}
@@ -419,6 +360,11 @@
int temp)
{
struct imx_thermal_data *data = tz->devdata;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(data->dev);
+ if (ret < 0)
+ return ret;
/* do not allow changing critical threshold */
if (trip == IMX_TRIP_CRITICAL)
@@ -431,6 +377,8 @@
data->temp_passive = temp;
imx_set_alarm_temp(data, temp);
+
+ pm_runtime_put(data->dev);
return 0;
}
@@ -474,8 +422,7 @@
.bind = imx_bind,
.unbind = imx_unbind,
.get_temp = imx_get_temp,
- .get_mode = imx_get_mode,
- .set_mode = imx_set_mode,
+ .change_mode = imx_change_mode,
.get_trip_type = imx_get_trip_type,
.get_trip_temp = imx_get_trip_temp,
.get_crit_temp = imx_get_crit_temp,
@@ -648,26 +595,54 @@
};
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
+#ifdef CONFIG_CPU_FREQ
/*
* Create cooling device in case no #cooling-cells property is available in
* CPU node
*/
static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
{
- struct device_node *np = of_get_cpu_node(data->policy->cpu, NULL);
- int ret;
+ struct device_node *np;
+ int ret = 0;
+
+ data->policy = cpufreq_cpu_get(0);
+ if (!data->policy) {
+ pr_debug("%s: CPUFreq policy not found\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ np = of_get_cpu_node(data->policy->cpu, NULL);
if (!np || !of_find_property(np, "#cooling-cells", NULL)) {
data->cdev = cpufreq_cooling_register(data->policy);
if (IS_ERR(data->cdev)) {
ret = PTR_ERR(data->cdev);
cpufreq_cpu_put(data->policy);
- return ret;
}
}
+ of_node_put(np);
+
+ return ret;
+}
+
+static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
+{
+ cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cpu_put(data->policy);
+}
+
+#else
+
+static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
+{
return 0;
}
+
+static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
+{
+}
+#endif
static int imx_thermal_probe(struct platform_device *pdev)
{
@@ -679,6 +654,8 @@
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+
+ data->dev = &pdev->dev;
map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
if (IS_ERR(map)) {
@@ -715,17 +692,13 @@
if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
ret = imx_init_from_nvmem_cells(pdev);
- if (ret == -EPROBE_DEFER)
- return ret;
- if (ret) {
- dev_err(&pdev->dev, "failed to init from nvmem: %d\n",
- ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to init from nvmem\n");
} else {
ret = imx_init_from_tempmon_data(pdev);
if (ret) {
- dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n");
+ dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n");
return ret;
}
}
@@ -743,18 +716,10 @@
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
data->socdata->power_down_mask);
- data->policy = cpufreq_cpu_get(0);
- if (!data->policy) {
- pr_debug("%s: CPUFreq policy not found\n", __func__);
- return -EPROBE_DEFER;
- }
-
ret = imx_thermal_register_legacy_cooling(data);
- if (ret) {
- dev_err(&pdev->dev,
- "failed to register cpufreq cooling device: %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to register cpufreq cooling device\n");
data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->thermal_clk)) {
@@ -762,9 +727,7 @@
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to get thermal clk: %d\n", ret);
- cpufreq_cooling_unregister(data->cdev);
- cpufreq_cpu_put(data->policy);
- return ret;
+ goto legacy_cleanup;
}
/*
@@ -777,9 +740,7 @@
ret = clk_prepare_enable(data->thermal_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
- cpufreq_cooling_unregister(data->cdev);
- cpufreq_cpu_put(data->policy);
- return ret;
+ goto legacy_cleanup;
}
data->tz = thermal_zone_device_register("imx_thermal_zone",
@@ -792,10 +753,7 @@
ret = PTR_ERR(data->tz);
dev_err(&pdev->dev,
"failed to register thermal zone device %d\n", ret);
- clk_disable_unprepare(data->thermal_clk);
- cpufreq_cooling_unregister(data->cdev);
- cpufreq_cpu_put(data->policy);
- return ret;
+ goto clk_disable;
}
dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
@@ -818,87 +776,148 @@
data->socdata->power_down_mask);
regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
data->socdata->measure_temp_mask);
+ /* After power up, we need a delay before first access can be done. */
+ usleep_range(20, 50);
+
+ /* the core was configured and enabled just before */
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(data->dev);
+
+ ret = pm_runtime_resume_and_get(data->dev);
+ if (ret < 0)
+ goto disable_runtime_pm;
data->irq_enabled = true;
- data->mode = THERMAL_DEVICE_ENABLED;
+ ret = thermal_zone_device_enable(data->tz);
+ if (ret)
+ goto thermal_zone_unregister;
ret = devm_request_threaded_irq(&pdev->dev, data->irq,
imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
0, "imx_thermal", data);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
- clk_disable_unprepare(data->thermal_clk);
- thermal_zone_device_unregister(data->tz);
- cpufreq_cooling_unregister(data->cdev);
- cpufreq_cpu_put(data->policy);
- return ret;
+ goto thermal_zone_unregister;
}
+ pm_runtime_put(data->dev);
+
return 0;
+
+thermal_zone_unregister:
+ thermal_zone_device_unregister(data->tz);
+disable_runtime_pm:
+ pm_runtime_put_noidle(data->dev);
+ pm_runtime_disable(data->dev);
+clk_disable:
+ clk_disable_unprepare(data->thermal_clk);
+legacy_cleanup:
+ imx_thermal_unregister_legacy_cooling(data);
+
+ return ret;
}
static int imx_thermal_remove(struct platform_device *pdev)
{
struct imx_thermal_data *data = platform_get_drvdata(pdev);
- struct regmap *map = data->tempmon;
- /* Disable measurements */
- regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
- data->socdata->power_down_mask);
- if (!IS_ERR(data->thermal_clk))
- clk_disable_unprepare(data->thermal_clk);
+ pm_runtime_put_noidle(data->dev);
+ pm_runtime_disable(data->dev);
thermal_zone_device_unregister(data->tz);
- cpufreq_cooling_unregister(data->cdev);
- cpufreq_cpu_put(data->policy);
+ imx_thermal_unregister_legacy_cooling(data);
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int imx_thermal_suspend(struct device *dev)
+static int __maybe_unused imx_thermal_suspend(struct device *dev)
{
struct imx_thermal_data *data = dev_get_drvdata(dev);
- struct regmap *map = data->tempmon;
+ int ret;
/*
* 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.
+ * down. This is done in change_mode() operation called from
+ * thermal_zone_device_disable()
*/
- regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
- data->socdata->measure_temp_mask);
- regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
- data->socdata->power_down_mask);
- data->mode = THERMAL_DEVICE_DISABLED;
+ ret = thermal_zone_device_disable(data->tz);
+ if (ret)
+ return ret;
+
+ return pm_runtime_force_suspend(data->dev);
+}
+
+static int __maybe_unused imx_thermal_resume(struct device *dev)
+{
+ struct imx_thermal_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(data->dev);
+ if (ret)
+ return ret;
+ /* Enabled thermal sensor after resume */
+ return thermal_zone_device_enable(data->tz);
+}
+
+static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev)
+{
+ struct imx_thermal_data *data = dev_get_drvdata(dev);
+ const struct thermal_soc_data *socdata = data->socdata;
+ struct regmap *map = data->tempmon;
+ int ret;
+
+ ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
+ socdata->measure_temp_mask);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
+ socdata->power_down_mask);
+ if (ret)
+ return ret;
+
clk_disable_unprepare(data->thermal_clk);
return 0;
}
-static int imx_thermal_resume(struct device *dev)
+static int __maybe_unused imx_thermal_runtime_resume(struct device *dev)
{
struct imx_thermal_data *data = dev_get_drvdata(dev);
+ const struct thermal_soc_data *socdata = data->socdata;
struct regmap *map = data->tempmon;
int ret;
ret = clk_prepare_enable(data->thermal_clk);
if (ret)
return ret;
- /* Enabled thermal sensor after resume */
- regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
- data->socdata->power_down_mask);
- regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
- data->socdata->measure_temp_mask);
- data->mode = THERMAL_DEVICE_ENABLED;
+
+ ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
+ socdata->power_down_mask);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
+ socdata->measure_temp_mask);
+ if (ret)
+ return ret;
+
+ /*
+ * According to the temp sensor designers, it may require up to ~17us
+ * to complete a measurement.
+ */
+ usleep_range(20, 50);
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
- imx_thermal_suspend, imx_thermal_resume);
+static const struct dev_pm_ops imx_thermal_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)
+ SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend,
+ imx_thermal_runtime_resume, NULL)
+};
static struct platform_driver imx_thermal = {
.driver = {
--
Gitblit v1.6.2