123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- From 346632bc00fe71c269709702fecb474bb22e933e Mon Sep 17 00:00:00 2001
- From: Sascha Hauer <[email protected]>
- Date: Wed, 13 May 2015 10:52:39 +0200
- Subject: [PATCH 20/76] thermal: thermal: Add support for hardware-tracked
- trip points
- This adds support for hardware-tracked trip points to the device tree
- thermal sensor framework.
- The framework supports an arbitrary number of trip points. Whenever
- the current temperature is updated, the trip points immediately
- below and above the current temperature are found. A .set_trips
- callback is then called with the temperatures. If there is no trip
- point above or below the current temperature, the passed trip
- temperature will be -INT_MAX or INT_MAX respectively. In this callback,
- the driver should program the hardware such that it is notified
- when either of these trip points are triggered. When a trip point
- is triggered, the driver should call `thermal_zone_device_update'
- for the respective thermal zone. This will cause the trip points
- to be updated again.
- If .set_trips is not implemented, the framework behaves as before.
- This patch is based on an earlier version from Mikko Perttunen
- <[email protected]>
- Signed-off-by: Sascha Hauer <[email protected]>
- ---
- drivers/thermal/thermal_core.c | 43 ++++++++++++++++++++++++++++++++++++++++
- include/linux/thermal.h | 3 +++
- 2 files changed, 46 insertions(+)
- --- a/drivers/thermal/thermal_core.c
- +++ b/drivers/thermal/thermal_core.c
- @@ -456,6 +456,45 @@ int thermal_zone_get_temp(struct thermal
- }
- EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
-
- +static void thermal_zone_set_trips(struct thermal_zone_device *tz)
- +{
- + int low = -INT_MAX;
- + int high = INT_MAX;
- + int trip_temp, hysteresis;
- + int temp = tz->temperature;
- + int i;
- +
- + if (!tz->ops->set_trips)
- + return;
- +
- + /* No need to change trip points */
- + if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
- + return;
- +
- + for (i = 0; i < tz->trips; i++) {
- + int trip_low;
- +
- + tz->ops->get_trip_temp(tz, i, &trip_temp);
- + tz->ops->get_trip_hyst(tz, i, &hysteresis);
- +
- + trip_low = trip_temp - hysteresis;
- +
- + if (trip_low < temp && trip_low > low)
- + low = trip_low;
- +
- + if (trip_temp > temp && trip_temp < high)
- + high = trip_temp;
- + }
- +
- + tz->prev_low_trip = low;
- + tz->prev_high_trip = high;
- +
- + dev_dbg(&tz->device, "new temperature boundaries: %d < x < %d\n",
- + low, high);
- +
- + tz->ops->set_trips(tz, low, high);
- +}
- +
- void thermal_zone_device_update(struct thermal_zone_device *tz)
- {
- int temp, ret, count;
- @@ -489,6 +528,8 @@ void thermal_zone_device_update(struct t
- dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
- tz->last_temperature, tz->temperature);
-
- + thermal_zone_set_trips(tz);
- +
- for (count = 0; count < tz->trips; count++)
- handle_thermal_trip(tz, count);
- }
- @@ -1522,6 +1563,8 @@ struct thermal_zone_device *thermal_zone
- tz->trips = trips;
- tz->passive_delay = passive_delay;
- tz->polling_delay = polling_delay;
- + tz->prev_low_trip = INT_MAX;
- + tz->prev_high_trip = -INT_MAX;
- /* A new thermal zone needs to be updated anyway. */
- atomic_set(&tz->need_update, 1);
-
- --- a/include/linux/thermal.h
- +++ b/include/linux/thermal.h
- @@ -90,6 +90,7 @@ struct thermal_zone_device_ops {
- int (*unbind) (struct thermal_zone_device *,
- struct thermal_cooling_device *);
- int (*get_temp) (struct thermal_zone_device *, int *);
- + int (*set_trips) (struct thermal_zone_device *, int, int);
- int (*get_mode) (struct thermal_zone_device *,
- enum thermal_device_mode *);
- int (*set_mode) (struct thermal_zone_device *,
- @@ -184,6 +185,8 @@ struct thermal_zone_device {
- int last_temperature;
- int emul_temperature;
- int passive;
- + int prev_low_trip;
- + int prev_high_trip;
- unsigned int forced_passive;
- atomic_t need_update;
- const struct thermal_zone_device_ops *ops;
|