* @polling_delay: zone polling interval
* @slope: slope of the temperature adjustment curve
* @offset: offset of the temperature adjustment curve
+ * @prev_low_trip: previous low trip point temperature
+ * @prev_high_trip: previous high trip point temperature
* @ntrips: number of trip points
* @trips: an array of trip points (0..ntrips - 1)
* @num_tbps: number of thermal bind params
int polling_delay;
int slope;
int offset;
+ int prev_low_trip, prev_high_trip;
/* trip data */
int ntrips;
const struct thermal_zone_of_device_ops *ops;
};
+/*** Automatic trip handling ***/
+
+static int of_thermal_set_trips(struct thermal_zone_device *tz, int temp)
+{
+ struct __thermal_zone *data = tz->devdata;
+ int low = INT_MIN, high = INT_MAX;
+ int i;
+
+ /* Hardware trip points not supported */
+ if (!data->ops->set_trips)
+ return 0;
+
+ /* No need to change trip points */
+ if (temp > data->prev_low_trip && temp < data->prev_high_trip)
+ return 0;
+
+ for (i = 0; i < data->ntrips; ++i) {
+ struct thermal_trip *trip = data->trips + i;
+ int trip_low = trip->temperature - trip->hysteresis;
+
+ if (trip_low < temp && trip_low > low)
+ low = trip_low;
+
+ if (trip->temperature > temp && trip->temperature < high)
+ high = trip->temperature;
+ }
+
+ dev_dbg(&tz->device,
+ "temperature %d, updating trip points to %d, %d\n",
+ temp, low, high);
+
+ data->prev_low_trip = low;
+ data->prev_high_trip = high;
+
+ return data->ops->set_trips(data->sensor_data, low, high);
+}
+
/*** DT thermal zone device callbacks ***/
static int of_thermal_get_temp(struct thermal_zone_device *tz,
int *temp)
{
struct __thermal_zone *data = tz->devdata;
+ int err;
if (!data->ops->get_temp)
return -EINVAL;
- return data->ops->get_temp(data->sensor_data, temp);
+ err = data->ops->get_temp(data->sensor_data, temp);
+ if (err)
+ return err;
+
+ err = of_thermal_set_trips(tz, *temp);
+ if (err)
+ return err;
+
+ return 0;
}
/**
return 0;
}
+static int of_thermal_update_trips(struct thermal_zone_device *tz)
+{
+ int temp;
+ int err;
+
+ err = of_thermal_get_temp(tz, &temp);
+ if (err)
+ return err;
+
+ err = of_thermal_set_trips(tz, temp);
+ if (err)
+ return err;
+
+ return 0;
+}
+
static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
enum thermal_trip_type *type)
{
int temp)
{
struct __thermal_zone *data = tz->devdata;
+ int err;
if (trip >= data->ntrips || trip < 0)
return -EDOM;
/* thermal framework should take care of data->mask & (1 << trip) */
data->trips[trip].temperature = temp;
+ err = of_thermal_update_trips(tz);
+ if (err)
+ return err;
+
return 0;
}
int hyst)
{
struct __thermal_zone *data = tz->devdata;
+ int err;
if (trip >= data->ntrips || trip < 0)
return -EDOM;
/* thermal framework should take care of data->mask & (1 << trip) */
data->trips[trip].hysteresis = hyst;
+ err = of_thermal_update_trips(tz);
+ if (err)
+ return err;
+
return 0;
}
tz->ops = ops;
tz->sensor_data = data;
+ of_thermal_update_trips(tzd);
+
tzd->ops->get_temp = of_thermal_get_temp;
tzd->ops->get_trend = of_thermal_get_trend;
tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
/* trips */
child = of_get_child_by_name(np, "trips");
+ tz->prev_high_trip = INT_MIN;
+ tz->prev_low_trip = INT_MAX;
+
/* No trips provided */
if (!child)
goto finish;