1 From 346632bc00fe71c269709702fecb474bb22e933e Mon Sep 17 00:00:00 2001
2 From: Sascha Hauer <s.hauer@pengutronix.de>
3 Date: Wed, 13 May 2015 10:52:39 +0200
4 Subject: [PATCH 20/76] thermal: thermal: Add support for hardware-tracked
7 This adds support for hardware-tracked trip points to the device tree
8 thermal sensor framework.
10 The framework supports an arbitrary number of trip points. Whenever
11 the current temperature is updated, the trip points immediately
12 below and above the current temperature are found. A .set_trips
13 callback is then called with the temperatures. If there is no trip
14 point above or below the current temperature, the passed trip
15 temperature will be -INT_MAX or INT_MAX respectively. In this callback,
16 the driver should program the hardware such that it is notified
17 when either of these trip points are triggered. When a trip point
18 is triggered, the driver should call `thermal_zone_device_update'
19 for the respective thermal zone. This will cause the trip points
22 If .set_trips is not implemented, the framework behaves as before.
24 This patch is based on an earlier version from Mikko Perttunen
25 <mikko.perttunen@kapsi.fi>
27 Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
29 drivers/thermal/thermal_core.c | 43 ++++++++++++++++++++++++++++++++++++++++
30 include/linux/thermal.h | 3 +++
31 2 files changed, 46 insertions(+)
33 --- a/drivers/thermal/thermal_core.c
34 +++ b/drivers/thermal/thermal_core.c
35 @@ -453,6 +453,45 @@ int thermal_zone_get_temp(struct thermal
37 EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
39 +static void thermal_zone_set_trips(struct thermal_zone_device *tz)
43 + int trip_temp, hysteresis;
44 + int temp = tz->temperature;
47 + if (!tz->ops->set_trips)
50 + /* No need to change trip points */
51 + if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
54 + for (i = 0; i < tz->trips; i++) {
57 + tz->ops->get_trip_temp(tz, i, &trip_temp);
58 + tz->ops->get_trip_hyst(tz, i, &hysteresis);
60 + trip_low = trip_temp - hysteresis;
62 + if (trip_low < temp && trip_low > low)
65 + if (trip_temp > temp && trip_temp < high)
69 + tz->prev_low_trip = low;
70 + tz->prev_high_trip = high;
72 + dev_dbg(&tz->device, "new temperature boundaries: %d < x < %d\n",
75 + tz->ops->set_trips(tz, low, high);
78 void thermal_zone_device_update(struct thermal_zone_device *tz)
81 @@ -479,6 +518,8 @@ void thermal_zone_device_update(struct t
82 dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
83 tz->last_temperature, tz->temperature);
85 + thermal_zone_set_trips(tz);
87 for (count = 0; count < tz->trips; count++)
88 handle_thermal_trip(tz, count);
90 @@ -1494,6 +1535,8 @@ struct thermal_zone_device *thermal_zone
92 tz->passive_delay = passive_delay;
93 tz->polling_delay = polling_delay;
94 + tz->prev_low_trip = INT_MAX;
95 + tz->prev_high_trip = -INT_MAX;
97 dev_set_name(&tz->device, "thermal_zone%d", tz->id);
98 result = device_register(&tz->device);
99 --- a/include/linux/thermal.h
100 +++ b/include/linux/thermal.h
101 @@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
102 int (*unbind) (struct thermal_zone_device *,
103 struct thermal_cooling_device *);
104 int (*get_temp) (struct thermal_zone_device *, int *);
105 + int (*set_trips) (struct thermal_zone_device *, int, int);
106 int (*get_mode) (struct thermal_zone_device *,
107 enum thermal_device_mode *);
108 int (*set_mode) (struct thermal_zone_device *,
109 @@ -180,6 +181,8 @@ struct thermal_zone_device {
110 int last_temperature;
111 int emul_temperature;
114 + int prev_high_trip;
115 unsigned int forced_passive;
116 const struct thermal_zone_device_ops *ops;
117 const struct thermal_zone_params *tzp;