0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/thermal.h>
0014 #include <linux/minmax.h>
0015 #include <trace/events/thermal.h>
0016
0017 #include "thermal_core.h"
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 static unsigned long get_target_state(struct thermal_instance *instance,
0039 enum thermal_trend trend, bool throttle)
0040 {
0041 struct thermal_cooling_device *cdev = instance->cdev;
0042 unsigned long cur_state;
0043 unsigned long next_target;
0044
0045
0046
0047
0048
0049
0050 cdev->ops->get_cur_state(cdev, &cur_state);
0051 next_target = instance->target;
0052 dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
0053
0054 if (!instance->initialized) {
0055 if (throttle) {
0056 next_target = clamp((cur_state + 1), instance->lower, instance->upper);
0057 } else {
0058 next_target = THERMAL_NO_TARGET;
0059 }
0060
0061 return next_target;
0062 }
0063
0064 switch (trend) {
0065 case THERMAL_TREND_RAISING:
0066 if (throttle) {
0067 next_target = clamp((cur_state + 1), instance->lower, instance->upper);
0068 }
0069 break;
0070 case THERMAL_TREND_DROPPING:
0071 if (cur_state <= instance->lower) {
0072 if (!throttle)
0073 next_target = THERMAL_NO_TARGET;
0074 } else {
0075 if (!throttle) {
0076 next_target = clamp((cur_state - 1), instance->lower, instance->upper);
0077 }
0078 }
0079 break;
0080 default:
0081 break;
0082 }
0083
0084 return next_target;
0085 }
0086
0087 static void update_passive_instance(struct thermal_zone_device *tz,
0088 enum thermal_trip_type type, int value)
0089 {
0090
0091
0092
0093
0094 if (type == THERMAL_TRIP_PASSIVE)
0095 tz->passive += value;
0096 }
0097
0098 static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
0099 {
0100 int trip_temp;
0101 enum thermal_trip_type trip_type;
0102 enum thermal_trend trend;
0103 struct thermal_instance *instance;
0104 bool throttle = false;
0105 int old_target;
0106
0107 tz->ops->get_trip_temp(tz, trip, &trip_temp);
0108 tz->ops->get_trip_type(tz, trip, &trip_type);
0109
0110 trend = get_tz_trend(tz, trip);
0111
0112 if (tz->temperature >= trip_temp) {
0113 throttle = true;
0114 trace_thermal_zone_trip(tz, trip, trip_type);
0115 }
0116
0117 dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
0118 trip, trip_type, trip_temp, trend, throttle);
0119
0120 mutex_lock(&tz->lock);
0121
0122 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
0123 if (instance->trip != trip)
0124 continue;
0125
0126 old_target = instance->target;
0127 instance->target = get_target_state(instance, trend, throttle);
0128 dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
0129 old_target, (int)instance->target);
0130
0131 if (instance->initialized && old_target == instance->target)
0132 continue;
0133
0134
0135 if (old_target == THERMAL_NO_TARGET &&
0136 instance->target != THERMAL_NO_TARGET)
0137 update_passive_instance(tz, trip_type, 1);
0138
0139 else if (old_target != THERMAL_NO_TARGET &&
0140 instance->target == THERMAL_NO_TARGET)
0141 update_passive_instance(tz, trip_type, -1);
0142
0143 instance->initialized = true;
0144 mutex_lock(&instance->cdev->lock);
0145 instance->cdev->updated = false;
0146 mutex_unlock(&instance->cdev->lock);
0147 }
0148
0149 mutex_unlock(&tz->lock);
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
0164 {
0165 struct thermal_instance *instance;
0166
0167 thermal_zone_trip_update(tz, trip);
0168
0169 mutex_lock(&tz->lock);
0170
0171 list_for_each_entry(instance, &tz->thermal_instances, tz_node)
0172 thermal_cdev_update(instance->cdev);
0173
0174 mutex_unlock(&tz->lock);
0175
0176 return 0;
0177 }
0178
0179 static struct thermal_governor thermal_gov_step_wise = {
0180 .name = "step_wise",
0181 .throttle = step_wise_throttle,
0182 };
0183 THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);