1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
|
/*
* include/linux/therm_est.h
*
* Copyright (c) 2010-2021, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _LINUX_THERM_EST_H
#define _LINUX_THERM_EST_H
#include <linux/workqueue.h>
#include <linux/thermal.h>
#include <linux/pwm.h>
#define HIST_LEN (20)
#define MAX_ACTIVE_STATES 10
#define MAX_TIMER_TRIPS 10
#define MAX_SUBDEVICE_GROUP 2
struct therm_est_sub_thz {
struct thermal_zone_device *thz;
long hist[HIST_LEN];
};
struct therm_est_coeffs {
long toffset;
s32 (*coeffs)[HIST_LEN];
};
struct therm_est_subdevice {
struct therm_est_sub_thz *sub_thz;
struct therm_est_coeffs *coeffs_set;
int num_devs;
int num_coeffs;
int active_coeffs;
int ntemp;
};
/*
* Timer trip provides a way to change trip temp dynamically based on timestamp
* when the trip is enabled.
* - Timer trip can be various numbers on a trip.
* - If the trip is enabled, then timer will be started with time_after delay
* in the corresponding timer trip. After the timer expires, trip_temp and
* hysteresis in the corresponding timer trip will be used to trip_temp for
* the trip.
* - When the timer has expired, index of timer trip will be increased a step
* and then start the timer with time_after delay in newly indexed timer trip.
* - When temp is below trip temp, index of timer trip will be decreased a step
* and then stop the timer and start the timer with time_after delay in newly
* indexed timer trip.
* - The timer will be stopped if there is no more next timer trip on the trip,
* or the trip is disabled.
*/
struct therm_est_timer_trip {
long time_after; /* in msec */
long trip_temp;
long hysteresis;
};
struct therm_est_timer_trip_info {
int trip; /* trip point on thermal zone to apply timer trip */
int num_timers;
struct therm_est_timer_trip timers[MAX_TIMER_TRIPS];
int cur; /* index of current timer trip */
s64 last_tripped; /* timestamp when the trip is enabled, in msec */
};
struct therm_est_data {
/* trip point info */
int num_trips;
struct thermal_trip_info *trips;
/* timer trip info */
int num_timer_trips;
struct therm_est_timer_trip_info *timer_trips;
/* zone parameters */
struct thermal_zone_params *tzp;
long polling_period;
int passive_delay;
int tc1;
int tc2;
struct therm_est_subdevice subdevice;
int use_activator;
};
struct therm_fan_est_subdevice {
const char *dev_data;
int (*get_temp)(const char *, int *);
int group;
/*
* as we read coeffs array from the device tree,
* specify type that has known width - 32 bits
*
* 'long' does not work, as its size if arch-dependent
*/
s32 coeffs[HIST_LEN];
int hist[HIST_LEN];
};
struct therm_fan_est_data {
long toffset;
long polling_period;
int ndevs;
char *cdev_type;
int active_trip_temps[MAX_ACTIVE_STATES];
int active_hysteresis[MAX_ACTIVE_STATES];
struct thermal_zone_params *tzp;
struct therm_fan_est_subdevice devs[];
};
struct fan_dev_data {
int next_state;
int active_steps;
int *fan_rpm;
int *fan_pwm;
int *fan_rru;
int *fan_rrd;
int *fan_state_cap_lookup;
int num_profiles;
int current_profile;
const char **fan_profile_names;
int **fan_profile_pwms;
int *fan_profile_caps;
struct workqueue_struct *workqueue;
int fan_temp_control_flag;
struct pwm_device *pwm_dev;
bool pwm_legacy_api;
int fan_cap_pwm;
int fan_cur_pwm;
int next_target_pwm;
struct thermal_cooling_device *cdev;
struct delayed_work fan_ramp_work;
struct delayed_work fan_hyst_work;
int step_time;
long long precision_multiplier;
struct mutex fan_state_lock;
int pwm_period;
int fan_pwm_max;
struct device *dev;
int tach_gpio;
int tach_irq;
atomic_t tach_enabled;
int fan_state_cap;
int pwm_gpio;
int pwm_id;
int fan_startup_pwm;
int fan_startup_time;
bool fan_kickstart; /*flag to check if fan is kickstart*/
bool kickstart_en; /*flag to check if kickstart feature is enabled*/
enum pwm_polarity fan_pwm_polarity;
int suspend_state;
const char *name;
const char *regulator_name;
struct regulator *fan_reg;
bool is_fan_reg_enabled;
struct dentry *debugfs_root;
/* for tach feedback */
atomic64_t rpm_measured;
struct delayed_work fan_tach_work;
struct workqueue_struct *tach_workqueue;
int tach_period;
spinlock_t irq_lock;
int irq_count;
u64 first_irq;
u64 last_irq;
u64 old_irq;
struct device_node *of_node_tach;
bool use_tach_feedback;
int rpm_diff_tolerance;
int fan_rpm_target_hit_count;
int fan_rpm_ramp_index;
int next_target_rpm;
int fan_ramp_time_ms;
struct delayed_work fan_ramp_pwm_work;
struct delayed_work fan_ramp_rpm_work;
struct device *pwm_tach_dev;
struct completion pwm_set;
bool fan_rpm_in_limits;
int rpm_valid_retry_delay;
int rpm_invalid_retry_delay;
int rpm_valid_retry_count;
bool continuous_gov;
bool is_tmargin;
bool is_always_on;
};
#define DEBUG 0
#define MULTIQP (100)
#define DEFERRED_RESUME_TIME 3000
#define THERMAL_GOV_PID "pid_thermal_gov"
#define THERMAL_CONTINUOUS_GOV "continuous_therm_gov"
struct therm_fan_estimator {
long cur_temp;
long pre_temp;
#if DEBUG
long cur_temp_debug;
#endif
long polling_period;
struct workqueue_struct *workqueue;
struct delayed_work therm_fan_est_work;
long toffset;
int ntemp;
int ndevs;
struct therm_fan_est_subdevice *devs;
struct thermal_zone_device *thz;
int current_trip_level;
const char *cdev_type;
rwlock_t state_lock;
int num_profiles;
int current_profile;
const char **fan_profile_names;
s32 **fan_profile_trip_temps;
s32 **fan_profile_trip_hysteresis;
s32 active_trip_temps[MAX_ACTIVE_STATES];
s32 active_hysteresis[MAX_ACTIVE_STATES];
struct thermal_zone_params *tzp;
int num_resources;
int trip_length;
const char *name;
bool is_pid_gov;
bool reset_trip_index;
/* allow cooling device to turn off at higher temperature if sleep */
bool sleep_mode;
int nonsleep_hyst;
bool use_tmargin;
long crit_temp[MAX_SUBDEVICE_GROUP];
bool is_continuous_gov;
};
#if IS_ENABLED(CONFIG_GENERIC_PWM_TACHOMETER)
int pwm_tach_capture_rpm(struct device *dev);
struct device *pwm_get_tach_dev(void);
#else
static inline int pwm_tach_capture_rpm(struct device *dev)
{
return 0;
}
static inline struct device *pwm_get_tach_dev(void)
{
return NULL;
}
#endif
#if IS_ENABLED(CONFIG_THERMAL_GOV_CONTINUOUS)
int continuous_thermal_gov_update_params(struct thermal_zone_params *tzp,
struct device_node *np);
#else
static inline int continuous_thermal_gov_update_params(
struct thermal_zone_params *tzp, struct device_node *np)
{
return 0;
}
#endif
#endif /* _LINUX_THERM_EST_H */
|