Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  step_wise.c - A step-by-step Thermal throttling governor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2012 Intel Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/thermal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <trace/events/thermal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "thermal_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * If the temperature is higher than a trip point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *       state for this trip point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *    b. if the trend is THERMAL_TREND_DROPPING, do nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *    c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *       for this trip point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *       for this trip point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * If the temperature is lower than a trip point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *    a. if the trend is THERMAL_TREND_RAISING, do nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *       state for this trip point, if the cooling state already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  *       equals lower limit, deactivate the thermal instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *    c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *       if the cooling state already equals lower limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *       deactivate the thermal instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static unsigned long get_target_state(struct thermal_instance *instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 				enum thermal_trend trend, bool throttle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct thermal_cooling_device *cdev = instance->cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	unsigned long cur_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	unsigned long next_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	 * We keep this instance the way it is by default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	 * Otherwise, we use the current state of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	 * cdev in use to determine the next_target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	cdev->ops->get_cur_state(cdev, &cur_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	next_target = instance->target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	if (!instance->initialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		if (throttle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			next_target = (cur_state + 1) >= instance->upper ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 					instance->upper :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 					((cur_state + 1) < instance->lower ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 					instance->lower : (cur_state + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			next_target = THERMAL_NO_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return next_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	switch (trend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	case THERMAL_TREND_RAISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		if (throttle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			next_target = cur_state < instance->upper ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 				    (cur_state + 1) : instance->upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			if (next_target < instance->lower)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 				next_target = instance->lower;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	case THERMAL_TREND_RAISE_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		if (throttle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			next_target = instance->upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	case THERMAL_TREND_DROPPING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		if (cur_state <= instance->lower) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			if (!throttle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 				next_target = THERMAL_NO_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			if (!throttle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				next_target = cur_state - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 				if (next_target > instance->upper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 					next_target = instance->upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	case THERMAL_TREND_DROP_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		if (cur_state == instance->lower) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			if (!throttle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				next_target = THERMAL_NO_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			next_target = instance->lower;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	return next_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void update_passive_instance(struct thermal_zone_device *tz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 				enum thermal_trip_type type, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	 * If value is +1, activate a passive instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	 * If value is -1, deactivate a passive instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		tz->passive += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	int trip_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	enum thermal_trip_type trip_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	enum thermal_trend trend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	struct thermal_instance *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	bool throttle = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	int old_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (trip == THERMAL_TRIPS_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		trip_temp = tz->forced_passive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		trip_type = THERMAL_TRIPS_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		tz->ops->get_trip_temp(tz, trip, &trip_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		tz->ops->get_trip_type(tz, trip, &trip_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	trend = get_tz_trend(tz, trip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (tz->temperature >= trip_temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		throttle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		trace_thermal_zone_trip(tz, trip, trip_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 				trip, trip_type, trip_temp, trend, throttle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	mutex_lock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		if (instance->trip != trip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		old_target = instance->target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		instance->target = get_target_state(instance, trend, throttle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 					old_target, (int)instance->target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		if (instance->initialized && old_target == instance->target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		/* Activate a passive thermal instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		if (old_target == THERMAL_NO_TARGET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			instance->target != THERMAL_NO_TARGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			update_passive_instance(tz, trip_type, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		/* Deactivate a passive thermal instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		else if (old_target != THERMAL_NO_TARGET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			instance->target == THERMAL_NO_TARGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			update_passive_instance(tz, trip_type, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		instance->initialized = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		mutex_lock(&instance->cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		instance->cdev->updated = false; /* cdev needs update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		mutex_unlock(&instance->cdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	mutex_unlock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * step_wise_throttle - throttles devices associated with the given zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * @tz: thermal_zone_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * @trip: trip point index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * Throttling Logic: This uses the trend of the thermal zone to throttle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * If the thermal zone is 'heating up' this throttles all the cooling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * devices associated with the zone and its particular trip point, by one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * step. If the zone is 'cooling down' it brings back the performance of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * the devices by one step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	struct thermal_instance *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	thermal_zone_trip_update(tz, trip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (tz->forced_passive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	mutex_lock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		thermal_cdev_update(instance->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	mutex_unlock(&tz->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct thermal_governor thermal_gov_step_wise = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	.name		= "step_wise",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	.throttle	= step_wise_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);