Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01ffea27 authored by Lina Iyer's avatar Lina Iyer Committed by Ram Chandrasekar
Browse files

drivers: of-thermal: aggregate threshold of type across siblings



Iterate through the siblings of a TZ to figure out the trip point of a
given trip type. Find the min of the next higher temperature and
the max of the next lower temperature around the current temperature
helps set points of interest on the sensor.

This is particularly helpful for a sensor capable of polling for
temperature in the hardware and triggering an interrupt when those
thresholds are crossed.

Aggregate the trip thresholds across the sibling thermal zones inside
the set_trips callback in of thermal. This will ensure that when the
sensor drivers set_trips callback is called, it has the aggregated trip
high and trip low threshold of all sibling thermal zones.

Change-Id: I74fa57f81e9a691ede6b8d46a2e51f02bef91b6f
Signed-off-by: default avatarLina Iyer <ilina@codeaurora.org>
parent d29230b5
Loading
Loading
Loading
Loading
+92 −2
Original line number Diff line number Diff line
@@ -62,11 +62,16 @@ struct __thermal_bind_params {
 * struct __sensor_param - Holds individual sensor data
 * @sensor_data: sensor driver private data passed as input argument
 * @ops: sensor driver ops
 * @trip_high: last trip high value programmed in the sensor driver
 * @trip_low: last trip low value programmed in the sensor driver
 * @lock: mutex lock acquired before updating the trip temperatures
 * @first_tz: list head pointing the first thermal zone
 */
struct __sensor_param {
	void *sensor_data;
	const struct thermal_zone_of_device_ops *ops;
	int trip_high, trip_low;
	struct mutex lock;
	struct list_head first_tz;
};

@@ -107,6 +112,9 @@ struct __thermal_zone {
	struct __sensor_param *senps;
};

static int of_thermal_aggregate_trip_types(struct thermal_zone_device *tz,
		unsigned int trip_type_mask, int *low, int *high);

/***   DT thermal zone device callbacks   ***/

static int of_thermal_get_temp(struct thermal_zone_device *tz,
@@ -121,14 +129,29 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
}

static int of_thermal_set_trips(struct thermal_zone_device *tz,
				int low, int high)
				int inp_low, int inp_high)
{
	struct __thermal_zone *data = tz->devdata;
	int high = INT_MAX, low = INT_MIN, ret = 0;

	if (!data->senps || !data->senps->ops->set_trips)
		return -EINVAL;

	return data->senps->ops->set_trips(data->senps->sensor_data, low, high);
	mutex_lock(&data->senps->lock);
	of_thermal_aggregate_trip_types(tz, GENMASK(THERMAL_TRIP_CRITICAL, 0),
					&low, &high);
	if (low == data->senps->trip_low
		&& high == data->senps->trip_high)
		goto set_trips_exit;

	data->senps->trip_low = low;
	data->senps->trip_high = high;
	ret = data->senps->ops->set_trips(data->senps->sensor_data,
					  low, high);

set_trips_exit:
	mutex_unlock(&data->senps->lock);
	return ret;
}

/**
@@ -405,6 +428,70 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
	return -EINVAL;
}

static int of_thermal_aggregate_trip_types(struct thermal_zone_device *tz,
		unsigned int trip_type_mask, int *low, int *high)
{
	int min = INT_MIN;
	int max = INT_MAX;
	int tt, th, trip;
	int temp = tz->temperature;
	struct thermal_zone_device *zone = NULL;
	struct __thermal_zone *data = tz->devdata;
	struct list_head *head;
	enum thermal_trip_type type = 0;

	head = &data->senps->first_tz;
	for_each_tz_sibling(data, head) {
		zone = data->tzd;
		for (trip = 0; trip < data->ntrips; trip++) {
			of_thermal_get_trip_type(zone, trip, &type);
			if (!(BIT(type) & trip_type_mask))
				continue;

			if (!zone->tzp->tracks_low) {
				tt = data->trips[trip].temperature;
				if (tt > temp && tt < max)
					max = tt;
				th = tt - data->trips[trip].hysteresis;
				if (th < temp && th > min)
					min = th;
			} else {
				tt = data->trips[trip].temperature;
				if (tt < temp && tt > min)
					min = tt;
				th = tt + data->trips[trip].hysteresis;
				if (th > temp && th < max)
					max = th;
			}
		}
	}

	*high = max;
	*low = min;

	return 0;
}

/*
 * of_thermal_aggregate_trip - aggregate trip temperatures across sibling
 *				thermal zones.
 * @tz: pointer to the primary thermal zone.
 * @type: the thermal trip type to be aggregated upon
 * @low: the low trip threshold which the most lesser than the @temp
 * @high: the high trip threshold which is the least greater than the @temp
 */
int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
				enum thermal_trip_type type,
				int *low, int *high)
{
	if (type <= THERMAL_TRIP_CRITICAL)
		return of_thermal_aggregate_trip_types(tz, BIT(type), low,
						       high);

	return -EINVAL;
}
EXPORT_SYMBOL(of_thermal_aggregate_trip);

static struct thermal_zone_device_ops of_thermal_ops = {
	.get_mode = of_thermal_get_mode,
	.set_mode = of_thermal_set_mode,
@@ -518,6 +605,9 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
	sens_param->sensor_data = data;
	sens_param->ops = ops;
	INIT_LIST_HEAD(&sens_param->first_tz);
	sens_param->trip_high = INT_MAX;
	sens_param->trip_low = INT_MIN;
	mutex_init(&sens_param->lock);
	sensor_np = of_node_get(dev->of_node);

	for_each_available_child_of_node(np, child) {
+9 −0
Original line number Diff line number Diff line
@@ -105,6 +105,9 @@ int of_thermal_get_ntrips(struct thermal_zone_device *);
bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *);
int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
			      enum thermal_trip_type type,
			      int *low, int *high);
#else
static inline int of_parse_thermal_zones(void) { return 0; }
static inline void of_thermal_destroy_zones(void) { }
@@ -122,6 +125,12 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz)
{
	return NULL;
}
static inline int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
					    enum thermal_trip_type type,
					    int *low, int *high)
{
	return -ENODEV;
}
#endif

#endif /* __THERMAL_CORE_H__ */