#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/device_cooling.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
* that will trigger cooling action when crossed.
*/
#define IMX_TEMP_PASSIVE 85000
+#define IMX_TEMP_PASSIVE_COOL_DELTA 10000
#define IMX_POLLING_DELAY 2000 /* millisecond */
#define IMX_PASSIVE_DELAY 1000
struct imx_thermal_data {
struct thermal_zone_device *tz;
- struct thermal_cooling_device *cdev;
+ struct thermal_cooling_device *cdev[2];
enum thermal_device_mode mode;
struct regmap *tempmon;
u32 c1, c2; /* See formula in imx_get_sensor_data() */
return 0;
}
-static struct thermal_zone_device_ops imx_tz_ops = {
+static int imx_get_trend(struct thermal_zone_device *tz,
+ int trip, enum thermal_trend *trend)
+{
+ int ret;
+ unsigned long trip_temp;
+
+ ret = imx_get_trip_temp(tz, trip, &trip_temp);
+ if (ret < 0)
+ return ret;
+
+ if (tz->temperature >= (trip_temp - IMX_TEMP_PASSIVE_COOL_DELTA))
+ *trend = THERMAL_TREND_RAISE_FULL;
+ else
+ *trend = THERMAL_TREND_DROP_FULL;
+
+ return 0;
+}
+
+static const struct thermal_zone_device_ops imx_tz_ops = {
.bind = imx_bind,
.unbind = imx_unbind,
.get_temp = imx_get_temp,
.get_trip_type = imx_get_trip_type,
.get_trip_temp = imx_get_trip_temp,
.get_crit_temp = imx_get_crit_temp,
+ .get_trend = imx_get_trend,
.set_trip_temp = imx_set_trip_temp,
};
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
cpumask_set_cpu(0, &clip_cpus);
- data->cdev = cpufreq_cooling_register(&clip_cpus);
- if (IS_ERR(data->cdev)) {
- ret = PTR_ERR(data->cdev);
+ data->cdev[0] = cpufreq_cooling_register(&clip_cpus);
+ if (IS_ERR(data->cdev[0])) {
+ ret = PTR_ERR(data->cdev[0]);
dev_err(&pdev->dev,
"failed to register cpufreq cooling device: %d\n", ret);
return ret;
}
+ data->cdev[1] = devfreq_cooling_register();
+ if (IS_ERR(data->cdev[1])) {
+ ret = PTR_ERR(data->cdev[1]);
+ dev_err(&pdev->dev,
+ "failed to register devfreq cooling device: %d\n", ret);
+ return ret;
+ }
+
+ data->trip_temp[IMX_TRIP_PASSIVE] = IMX_TEMP_PASSIVE;
+ data->trip_temp[IMX_TRIP_CRITICAL] = IMX_TEMP_CRITICAL;
data->tz = thermal_zone_device_register("imx_thermal_zone",
IMX_TRIP_NUM,
BIT(IMX_TRIP_PASSIVE), data,
ret = PTR_ERR(data->tz);
dev_err(&pdev->dev,
"failed to register thermal zone device %d\n", ret);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ devfreq_cooling_unregister(data->cdev[1]);
return ret;
}
clk_disable_unprepare(data->thermal_clk);
thermal_zone_device_unregister(data->tz);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ devfreq_cooling_unregister(data->cdev[1]);
return 0;
}