1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * thermal.h ($Revision: 0 $) |
4 | * |
5 | * Copyright (C) 2008 Intel Corp |
6 | * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com> |
7 | * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com> |
8 | */ |
9 | |
10 | #ifndef __THERMAL_H__ |
11 | #define __THERMAL_H__ |
12 | |
13 | #include <linux/of.h> |
14 | #include <linux/idr.h> |
15 | #include <linux/device.h> |
16 | #include <linux/sysfs.h> |
17 | #include <linux/workqueue.h> |
18 | #include <uapi/linux/thermal.h> |
19 | |
20 | /* invalid cooling state */ |
21 | #define THERMAL_CSTATE_INVALID -1UL |
22 | |
23 | /* No upper/lower limit requirement */ |
24 | #define THERMAL_NO_LIMIT ((u32)~0) |
25 | |
26 | /* Default weight of a bound cooling device */ |
27 | #define THERMAL_WEIGHT_DEFAULT 0 |
28 | |
29 | /* use value, which < 0K, to indicate an invalid/uninitialized temperature */ |
30 | #define THERMAL_TEMP_INVALID -274000 |
31 | |
32 | struct thermal_zone_device; |
33 | struct thermal_cooling_device; |
34 | struct thermal_instance; |
35 | struct thermal_attr; |
36 | |
37 | enum thermal_trend { |
38 | THERMAL_TREND_STABLE, /* temperature is stable */ |
39 | THERMAL_TREND_RAISING, /* temperature is raising */ |
40 | THERMAL_TREND_DROPPING, /* temperature is dropping */ |
41 | }; |
42 | |
43 | /* Thermal notification reason */ |
44 | enum thermal_notify_event { |
45 | THERMAL_EVENT_UNSPECIFIED, /* Unspecified event */ |
46 | THERMAL_EVENT_TEMP_SAMPLE, /* New Temperature sample */ |
47 | THERMAL_TRIP_VIOLATED, /* TRIP Point violation */ |
48 | THERMAL_TRIP_CHANGED, /* TRIP Point temperature changed */ |
49 | THERMAL_DEVICE_DOWN, /* Thermal device is down */ |
50 | THERMAL_DEVICE_UP, /* Thermal device is up after a down event */ |
51 | THERMAL_DEVICE_POWER_CAPABILITY_CHANGED, /* power capability changed */ |
52 | THERMAL_TABLE_CHANGED, /* Thermal table(s) changed */ |
53 | THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */ |
54 | }; |
55 | |
56 | /** |
57 | * struct thermal_trip - representation of a point in temperature domain |
58 | * @temperature: temperature value in miliCelsius |
59 | * @hysteresis: relative hysteresis in miliCelsius |
60 | * @type: trip point type |
61 | * @priv: pointer to driver data associated with this trip |
62 | */ |
63 | struct thermal_trip { |
64 | int temperature; |
65 | int hysteresis; |
66 | enum thermal_trip_type type; |
67 | void *priv; |
68 | }; |
69 | |
70 | struct thermal_zone_device_ops { |
71 | int (*bind) (struct thermal_zone_device *, |
72 | struct thermal_cooling_device *); |
73 | int (*unbind) (struct thermal_zone_device *, |
74 | struct thermal_cooling_device *); |
75 | int (*get_temp) (struct thermal_zone_device *, int *); |
76 | int (*set_trips) (struct thermal_zone_device *, int, int); |
77 | int (*change_mode) (struct thermal_zone_device *, |
78 | enum thermal_device_mode); |
79 | int (*set_trip_temp) (struct thermal_zone_device *, int, int); |
80 | int (*set_trip_hyst) (struct thermal_zone_device *, int, int); |
81 | int (*get_crit_temp) (struct thermal_zone_device *, int *); |
82 | int (*set_emul_temp) (struct thermal_zone_device *, int); |
83 | int (*get_trend) (struct thermal_zone_device *, |
84 | const struct thermal_trip *, enum thermal_trend *); |
85 | void (*hot)(struct thermal_zone_device *); |
86 | void (*critical)(struct thermal_zone_device *); |
87 | }; |
88 | |
89 | struct thermal_cooling_device_ops { |
90 | int (*get_max_state) (struct thermal_cooling_device *, unsigned long *); |
91 | int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *); |
92 | int (*set_cur_state) (struct thermal_cooling_device *, unsigned long); |
93 | int (*get_requested_power)(struct thermal_cooling_device *, u32 *); |
94 | int (*state2power)(struct thermal_cooling_device *, unsigned long, u32 *); |
95 | int (*power2state)(struct thermal_cooling_device *, u32, unsigned long *); |
96 | }; |
97 | |
98 | struct thermal_cooling_device { |
99 | int id; |
100 | char *type; |
101 | unsigned long max_state; |
102 | struct device device; |
103 | struct device_node *np; |
104 | void *devdata; |
105 | void *stats; |
106 | const struct thermal_cooling_device_ops *ops; |
107 | bool updated; /* true if the cooling device does not need update */ |
108 | struct mutex lock; /* protect thermal_instances list */ |
109 | struct list_head thermal_instances; |
110 | struct list_head node; |
111 | }; |
112 | |
113 | /** |
114 | * struct thermal_zone_device - structure for a thermal zone |
115 | * @id: unique id number for each thermal zone |
116 | * @type: the thermal zone device type |
117 | * @device: &struct device for this thermal zone |
118 | * @trip_temp_attrs: attributes for trip points for sysfs: trip temperature |
119 | * @trip_type_attrs: attributes for trip points for sysfs: trip type |
120 | * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis |
121 | * @mode: current mode of this thermal zone |
122 | * @devdata: private pointer for device private data |
123 | * @trips: an array of struct thermal_trip |
124 | * @num_trips: number of trip points the thermal zone supports |
125 | * @passive_delay_jiffies: number of jiffies to wait between polls when |
126 | * performing passive cooling. |
127 | * @polling_delay_jiffies: number of jiffies to wait between polls when |
128 | * checking whether trip points have been crossed (0 for |
129 | * interrupt driven systems) |
130 | * @temperature: current temperature. This is only for core code, |
131 | * drivers should use thermal_zone_get_temp() to get the |
132 | * current temperature |
133 | * @last_temperature: previous temperature read |
134 | * @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION |
135 | * @passive: 1 if you've crossed a passive trip point, 0 otherwise. |
136 | * @prev_low_trip: the low current temperature if you've crossed a passive |
137 | trip point. |
138 | * @prev_high_trip: the above current temperature if you've crossed a |
139 | passive trip point. |
140 | * @need_update: if equals 1, thermal_zone_device_update needs to be invoked. |
141 | * @ops: operations this &thermal_zone_device supports |
142 | * @tzp: thermal zone parameters |
143 | * @governor: pointer to the governor for this thermal zone |
144 | * @governor_data: private pointer for governor data |
145 | * @thermal_instances: list of &struct thermal_instance of this thermal zone |
146 | * @ida: &struct ida to generate unique id for this zone's cooling |
147 | * devices |
148 | * @lock: lock to protect thermal_instances list |
149 | * @node: node in thermal_tz_list (in thermal_core.c) |
150 | * @poll_queue: delayed work for polling |
151 | * @notify_event: Last notification event |
152 | */ |
153 | struct thermal_zone_device { |
154 | int id; |
155 | char type[THERMAL_NAME_LENGTH]; |
156 | struct device device; |
157 | struct attribute_group trips_attribute_group; |
158 | struct thermal_attr *trip_temp_attrs; |
159 | struct thermal_attr *trip_type_attrs; |
160 | struct thermal_attr *trip_hyst_attrs; |
161 | enum thermal_device_mode mode; |
162 | void *devdata; |
163 | struct thermal_trip *trips; |
164 | int num_trips; |
165 | unsigned long passive_delay_jiffies; |
166 | unsigned long polling_delay_jiffies; |
167 | int temperature; |
168 | int last_temperature; |
169 | int emul_temperature; |
170 | int passive; |
171 | int prev_low_trip; |
172 | int prev_high_trip; |
173 | atomic_t need_update; |
174 | struct thermal_zone_device_ops *ops; |
175 | struct thermal_zone_params *tzp; |
176 | struct thermal_governor *governor; |
177 | void *governor_data; |
178 | struct list_head thermal_instances; |
179 | struct ida ida; |
180 | struct mutex lock; |
181 | struct list_head node; |
182 | struct delayed_work poll_queue; |
183 | enum thermal_notify_event notify_event; |
184 | }; |
185 | |
186 | /** |
187 | * struct thermal_governor - structure that holds thermal governor information |
188 | * @name: name of the governor |
189 | * @bind_to_tz: callback called when binding to a thermal zone. If it |
190 | * returns 0, the governor is bound to the thermal zone, |
191 | * otherwise it fails. |
192 | * @unbind_from_tz: callback called when a governor is unbound from a |
193 | * thermal zone. |
194 | * @throttle: callback called for every trip point even if temperature is |
195 | * below the trip point temperature |
196 | * @governor_list: node in thermal_governor_list (in thermal_core.c) |
197 | */ |
198 | struct thermal_governor { |
199 | char name[THERMAL_NAME_LENGTH]; |
200 | int (*bind_to_tz)(struct thermal_zone_device *tz); |
201 | void (*unbind_from_tz)(struct thermal_zone_device *tz); |
202 | int (*throttle)(struct thermal_zone_device *tz, |
203 | const struct thermal_trip *trip); |
204 | struct list_head governor_list; |
205 | }; |
206 | |
207 | /* Structure to define Thermal Zone parameters */ |
208 | struct thermal_zone_params { |
209 | char governor_name[THERMAL_NAME_LENGTH]; |
210 | |
211 | /* |
212 | * a boolean to indicate if the thermal to hwmon sysfs interface |
213 | * is required. when no_hwmon == false, a hwmon sysfs interface |
214 | * will be created. when no_hwmon == true, nothing will be done |
215 | */ |
216 | bool no_hwmon; |
217 | |
218 | /* |
219 | * Sustainable power (heat) that this thermal zone can dissipate in |
220 | * mW |
221 | */ |
222 | u32 sustainable_power; |
223 | |
224 | /* |
225 | * Proportional parameter of the PID controller when |
226 | * overshooting (i.e., when temperature is below the target) |
227 | */ |
228 | s32 k_po; |
229 | |
230 | /* |
231 | * Proportional parameter of the PID controller when |
232 | * undershooting |
233 | */ |
234 | s32 k_pu; |
235 | |
236 | /* Integral parameter of the PID controller */ |
237 | s32 k_i; |
238 | |
239 | /* Derivative parameter of the PID controller */ |
240 | s32 k_d; |
241 | |
242 | /* threshold below which the error is no longer accumulated */ |
243 | s32 integral_cutoff; |
244 | |
245 | /* |
246 | * @slope: slope of a linear temperature adjustment curve. |
247 | * Used by thermal zone drivers. |
248 | */ |
249 | int slope; |
250 | /* |
251 | * @offset: offset of a linear temperature adjustment curve. |
252 | * Used by thermal zone drivers (default 0). |
253 | */ |
254 | int offset; |
255 | }; |
256 | |
257 | /* Function declarations */ |
258 | #ifdef CONFIG_THERMAL_OF |
259 | struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int id, void *data, |
260 | const struct thermal_zone_device_ops *ops); |
261 | |
262 | void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz); |
263 | |
264 | #else |
265 | |
266 | static inline |
267 | struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int id, void *data, |
268 | const struct thermal_zone_device_ops *ops) |
269 | { |
270 | return ERR_PTR(-ENOTSUPP); |
271 | } |
272 | |
273 | static inline void devm_thermal_of_zone_unregister(struct device *dev, |
274 | struct thermal_zone_device *tz) |
275 | { |
276 | } |
277 | #endif |
278 | |
279 | int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, |
280 | struct thermal_trip *trip); |
281 | int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, |
282 | struct thermal_trip *trip); |
283 | |
284 | int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id, |
285 | const struct thermal_trip *trip); |
286 | |
287 | int for_each_thermal_trip(struct thermal_zone_device *tz, |
288 | int (*cb)(struct thermal_trip *, void *), |
289 | void *data); |
290 | int thermal_zone_for_each_trip(struct thermal_zone_device *tz, |
291 | int (*cb)(struct thermal_trip *, void *), |
292 | void *data); |
293 | int thermal_zone_get_num_trips(struct thermal_zone_device *tz); |
294 | |
295 | int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp); |
296 | |
297 | #ifdef CONFIG_THERMAL_ACPI |
298 | int thermal_acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp); |
299 | int thermal_acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp); |
300 | int thermal_acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp); |
301 | int thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp); |
302 | #endif |
303 | |
304 | #ifdef CONFIG_THERMAL |
305 | struct thermal_zone_device *thermal_zone_device_register_with_trips( |
306 | const char *type, |
307 | struct thermal_trip *trips, |
308 | int num_trips, int mask, |
309 | void *devdata, |
310 | struct thermal_zone_device_ops *ops, |
311 | const struct thermal_zone_params *tzp, |
312 | int passive_delay, int polling_delay); |
313 | |
314 | struct thermal_zone_device *thermal_tripless_zone_device_register( |
315 | const char *type, |
316 | void *devdata, |
317 | struct thermal_zone_device_ops *ops, |
318 | const struct thermal_zone_params *tzp); |
319 | |
320 | void thermal_zone_device_unregister(struct thermal_zone_device *tz); |
321 | |
322 | void *thermal_zone_device_priv(struct thermal_zone_device *tzd); |
323 | const char *thermal_zone_device_type(struct thermal_zone_device *tzd); |
324 | int thermal_zone_device_id(struct thermal_zone_device *tzd); |
325 | struct device *thermal_zone_device(struct thermal_zone_device *tzd); |
326 | |
327 | int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, |
328 | const struct thermal_trip *trip, |
329 | struct thermal_cooling_device *cdev, |
330 | unsigned long upper, unsigned long lower, |
331 | unsigned int weight); |
332 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, |
333 | struct thermal_cooling_device *, |
334 | unsigned long, unsigned long, |
335 | unsigned int); |
336 | int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, |
337 | const struct thermal_trip *trip, |
338 | struct thermal_cooling_device *cdev); |
339 | int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, |
340 | struct thermal_cooling_device *); |
341 | void thermal_zone_device_update(struct thermal_zone_device *, |
342 | enum thermal_notify_event); |
343 | |
344 | struct thermal_cooling_device *thermal_cooling_device_register(const char *, |
345 | void *, const struct thermal_cooling_device_ops *); |
346 | struct thermal_cooling_device * |
347 | thermal_of_cooling_device_register(struct device_node *np, const char *, void *, |
348 | const struct thermal_cooling_device_ops *); |
349 | struct thermal_cooling_device * |
350 | devm_thermal_of_cooling_device_register(struct device *dev, |
351 | struct device_node *np, |
352 | char *type, void *devdata, |
353 | const struct thermal_cooling_device_ops *ops); |
354 | void thermal_cooling_device_update(struct thermal_cooling_device *); |
355 | void thermal_cooling_device_unregister(struct thermal_cooling_device *); |
356 | struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name); |
357 | int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); |
358 | int thermal_zone_get_slope(struct thermal_zone_device *tz); |
359 | int thermal_zone_get_offset(struct thermal_zone_device *tz); |
360 | |
361 | int thermal_zone_device_enable(struct thermal_zone_device *tz); |
362 | int thermal_zone_device_disable(struct thermal_zone_device *tz); |
363 | void thermal_zone_device_critical(struct thermal_zone_device *tz); |
364 | #else |
365 | static inline struct thermal_zone_device *thermal_zone_device_register_with_trips( |
366 | const char *type, |
367 | struct thermal_trip *trips, |
368 | int num_trips, int mask, |
369 | void *devdata, |
370 | struct thermal_zone_device_ops *ops, |
371 | const struct thermal_zone_params *tzp, |
372 | int passive_delay, int polling_delay) |
373 | { return ERR_PTR(-ENODEV); } |
374 | |
375 | static inline struct thermal_zone_device *thermal_tripless_zone_device_register( |
376 | const char *type, |
377 | void *devdata, |
378 | struct thermal_zone_device_ops *ops, |
379 | const struct thermal_zone_params *tzp) |
380 | { return ERR_PTR(-ENODEV); } |
381 | |
382 | static inline void thermal_zone_device_unregister(struct thermal_zone_device *tz) |
383 | { } |
384 | |
385 | static inline struct thermal_cooling_device * |
386 | thermal_cooling_device_register(const char *type, void *devdata, |
387 | const struct thermal_cooling_device_ops *ops) |
388 | { return ERR_PTR(-ENODEV); } |
389 | static inline struct thermal_cooling_device * |
390 | thermal_of_cooling_device_register(struct device_node *np, |
391 | const char *type, void *devdata, |
392 | const struct thermal_cooling_device_ops *ops) |
393 | { return ERR_PTR(-ENODEV); } |
394 | static inline struct thermal_cooling_device * |
395 | devm_thermal_of_cooling_device_register(struct device *dev, |
396 | struct device_node *np, |
397 | char *type, void *devdata, |
398 | const struct thermal_cooling_device_ops *ops) |
399 | { |
400 | return ERR_PTR(-ENODEV); |
401 | } |
402 | static inline void thermal_cooling_device_unregister( |
403 | struct thermal_cooling_device *cdev) |
404 | { } |
405 | static inline struct thermal_zone_device *thermal_zone_get_zone_by_name( |
406 | const char *name) |
407 | { return ERR_PTR(-ENODEV); } |
408 | static inline int thermal_zone_get_temp( |
409 | struct thermal_zone_device *tz, int *temp) |
410 | { return -ENODEV; } |
411 | static inline int thermal_zone_get_slope( |
412 | struct thermal_zone_device *tz) |
413 | { return -ENODEV; } |
414 | static inline int thermal_zone_get_offset( |
415 | struct thermal_zone_device *tz) |
416 | { return -ENODEV; } |
417 | |
418 | static inline void *thermal_zone_device_priv(struct thermal_zone_device *tz) |
419 | { |
420 | return NULL; |
421 | } |
422 | |
423 | static inline const char *thermal_zone_device_type(struct thermal_zone_device *tzd) |
424 | { |
425 | return NULL; |
426 | } |
427 | |
428 | static inline int thermal_zone_device_id(struct thermal_zone_device *tzd) |
429 | { |
430 | return -ENODEV; |
431 | } |
432 | |
433 | static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) |
434 | { return -ENODEV; } |
435 | |
436 | static inline int thermal_zone_device_disable(struct thermal_zone_device *tz) |
437 | { return -ENODEV; } |
438 | #endif /* CONFIG_THERMAL */ |
439 | |
440 | #endif /* __THERMAL_H__ */ |
441 | |