blob: d02ea2614895bcf3ba3c9c966de792899d0fef24 [file] [log] [blame]
Ram Chandrasekar6d44a342016-07-07 11:09:52 -06001/*
2 * Copyright (C) 2012 Intel Corp
3 * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
4 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 */
19
20#include <linux/thermal.h>
21#include <trace/events/thermal.h>
22
23#include "thermal_core.h"
24
25static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
26{
27 int trip_temp, trip_hyst;
28 enum thermal_trip_type trip_type;
29 struct thermal_instance *instance;
30 bool throttle;
31 int old_target;
32
33 tz->ops->get_trip_temp(tz, trip, &trip_temp);
34 tz->ops->get_trip_type(tz, trip, &trip_type);
35 if (tz->ops->get_trip_hyst) {
36 tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
37 trip_hyst = trip_temp + trip_hyst;
38 } else {
39 trip_hyst = trip_temp;
40 }
41
42 mutex_lock(&tz->lock);
43
44 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
45 if (instance->trip != trip)
46 continue;
47
48 if ((tz->temperature <= trip_temp) ||
49 (instance->target != THERMAL_NO_TARGET
Ram Chandrasekar14f93182017-10-17 17:34:21 -060050 && tz->temperature < trip_hyst))
Ram Chandrasekar6d44a342016-07-07 11:09:52 -060051 throttle = true;
52 else
53 throttle = false;
54
55 dev_dbg(&tz->device,
56 "Trip%d[type=%d,temp=%d,hyst=%d],throttle=%d\n",
57 trip, trip_type, trip_temp, trip_hyst, throttle);
58
59 old_target = instance->target;
60 instance->target = (throttle) ? instance->upper
61 : THERMAL_NO_TARGET;
62 dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
63 old_target, (int)instance->target);
64
Manaf Meethalavalappu Pallikunhi6df7a422018-05-29 14:56:28 +053065 if (instance->initialized && old_target == instance->target)
Ram Chandrasekar6d44a342016-07-07 11:09:52 -060066 continue;
67
Manaf Meethalavalappu Pallikunhi6df7a422018-05-29 14:56:28 +053068 if (!instance->initialized) {
69 if (instance->target != THERMAL_NO_TARGET) {
70 trace_thermal_zone_trip(tz, trip, trip_type,
71 true);
72 tz->passive += 1;
73 }
74 } else {
75 if (old_target == THERMAL_NO_TARGET &&
Ram Chandrasekar6d44a342016-07-07 11:09:52 -060076 instance->target != THERMAL_NO_TARGET) {
Manaf Meethalavalappu Pallikunhi6df7a422018-05-29 14:56:28 +053077 trace_thermal_zone_trip(tz, trip, trip_type,
78 true);
79 tz->passive += 1;
80 } else if (old_target != THERMAL_NO_TARGET &&
Ram Chandrasekar6d44a342016-07-07 11:09:52 -060081 instance->target == THERMAL_NO_TARGET) {
Manaf Meethalavalappu Pallikunhi6df7a422018-05-29 14:56:28 +053082 trace_thermal_zone_trip(tz, trip, trip_type,
83 false);
84 tz->passive -= 1;
85 }
Ram Chandrasekar6d44a342016-07-07 11:09:52 -060086 }
87
Manaf Meethalavalappu Pallikunhi6df7a422018-05-29 14:56:28 +053088 instance->initialized = true;
Ram Chandrasekar6d44a342016-07-07 11:09:52 -060089 instance->cdev->updated = false; /* cdev needs update */
90 }
91
92 mutex_unlock(&tz->lock);
93}
94
95/**
96 * low_limits_throttle - throttles devices associated with the given zone
97 * @tz - thermal_zone_device
98 * @trip - the trip point
99 *
100 * Throttling Logic: If the sensor reading goes below a trip point, the
101 * pre-defined mitigation will be applied for the cooling device.
102 * If the sensor reading goes above the trip hysteresis, the
103 * mitigation will be removed.
104 */
105static int low_limits_throttle(struct thermal_zone_device *tz, int trip)
106{
107 struct thermal_instance *instance;
108
109 thermal_zone_trip_update(tz, trip);
110
111 mutex_lock(&tz->lock);
112
113 list_for_each_entry(instance, &tz->thermal_instances, tz_node)
114 thermal_cdev_update(instance->cdev);
115
116 mutex_unlock(&tz->lock);
117
118 return 0;
119}
120
121static struct thermal_governor thermal_gov_low_limits_floor = {
122 .name = "low_limits_floor",
123 .throttle = low_limits_throttle,
124 .min_state_throttle = 1,
125};
126
Ram Chandrasekar0dac0c12017-03-13 17:58:39 -0600127static struct thermal_governor thermal_gov_low_limits_cap = {
128 .name = "low_limits_cap",
129 .throttle = low_limits_throttle,
130};
131
Ram Chandrasekar6d44a342016-07-07 11:09:52 -0600132int thermal_gov_low_limits_register(void)
133{
Ram Chandrasekar0dac0c12017-03-13 17:58:39 -0600134 thermal_register_governor(&thermal_gov_low_limits_cap);
Ram Chandrasekar6d44a342016-07-07 11:09:52 -0600135 return thermal_register_governor(&thermal_gov_low_limits_floor);
136}
137
138void thermal_gov_low_limits_unregister(void)
139{
Ram Chandrasekar0dac0c12017-03-13 17:58:39 -0600140 thermal_unregister_governor(&thermal_gov_low_limits_cap);
Ram Chandrasekar6d44a342016-07-07 11:09:52 -0600141 thermal_unregister_governor(&thermal_gov_low_limits_floor);
142}