Merge tag 'driver-core-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / drivers / thermal / clock_cooling.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  drivers/thermal/clock_cooling.c
4  *
5  *  Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com>
6  *
7  *  Copyright (C) 2013  Texas Instruments Inc.
8  *  Contact:  Eduardo Valentin <eduardo.valentin@ti.com>
9  *
10  *  Highly based on cpu_cooling.c.
11  *  Copyright (C) 2012  Samsung Electronics Co., Ltd(http://www.samsung.com)
12  *  Copyright (C) 2012  Amit Daniel <amit.kachhap@linaro.org>
13  */
14 #include <linux/clk.h>
15 #include <linux/cpufreq.h>
16 #include <linux/device.h>
17 #include <linux/err.h>
18 #include <linux/idr.h>
19 #include <linux/mutex.h>
20 #include <linux/pm_opp.h>
21 #include <linux/slab.h>
22 #include <linux/thermal.h>
23 #include <linux/clock_cooling.h>
24
25 /**
26  * struct clock_cooling_device - data for cooling device with clock
27  * @id: unique integer value corresponding to each clock_cooling_device
28  *      registered.
29  * @dev: struct device pointer to the device being used to cool off using
30  *       clock frequencies.
31  * @cdev: thermal_cooling_device pointer to keep track of the
32  *      registered cooling device.
33  * @clk_rate_change_nb: reference to notifier block used to receive clock
34  *                      rate changes.
35  * @freq_table: frequency table used to keep track of available frequencies.
36  * @clock_state: integer value representing the current state of clock
37  *      cooling devices.
38  * @clock_val: integer value representing the absolute value of the clipped
39  *      frequency.
40  * @clk: struct clk reference used to enforce clock limits.
41  * @lock: mutex lock to protect this struct.
42  *
43  * This structure is required for keeping information of each
44  * clock_cooling_device registered. In order to prevent corruption of this a
45  * mutex @lock is used.
46  */
47 struct clock_cooling_device {
48         int id;
49         struct device *dev;
50         struct thermal_cooling_device *cdev;
51         struct notifier_block clk_rate_change_nb;
52         struct cpufreq_frequency_table *freq_table;
53         unsigned long clock_state;
54         unsigned long clock_val;
55         struct clk *clk;
56         struct mutex lock; /* lock to protect the content of this struct */
57 };
58 #define to_clock_cooling_device(x) \
59                 container_of(x, struct clock_cooling_device, clk_rate_change_nb)
60 static DEFINE_IDA(clock_ida);
61
62 /* Below code defines functions to be used for clock as cooling device */
63
64 enum clock_cooling_property {
65         GET_LEVEL,
66         GET_FREQ,
67         GET_MAXL,
68 };
69
70 /**
71  * clock_cooling_get_property - fetch a property of interest for a give cpu.
72  * @ccdev: clock cooling device reference
73  * @input: query parameter
74  * @output: query return
75  * @property: type of query (frequency, level, max level)
76  *
77  * This is the common function to
78  * 1. get maximum clock cooling states
79  * 2. translate frequency to cooling state
80  * 3. translate cooling state to frequency
81  * Note that the code may be not in good shape
82  * but it is written in this way in order to:
83  * a) reduce duplicate code as most of the code can be shared.
84  * b) make sure the logic is consistent when translating between
85  *    cooling states and frequencies.
86  *
87  * Return: 0 on success, -EINVAL when invalid parameters are passed.
88  */
89 static int clock_cooling_get_property(struct clock_cooling_device *ccdev,
90                                       unsigned long input,
91                                       unsigned long *output,
92                                       enum clock_cooling_property property)
93 {
94         int i;
95         unsigned long max_level = 0, level = 0;
96         unsigned int freq = CPUFREQ_ENTRY_INVALID;
97         int descend = -1;
98         struct cpufreq_frequency_table *pos, *table = ccdev->freq_table;
99
100         if (!output)
101                 return -EINVAL;
102
103         if (!table)
104                 return -EINVAL;
105
106         cpufreq_for_each_valid_entry(pos, table) {
107                 /* ignore duplicate entry */
108                 if (freq == pos->frequency)
109                         continue;
110
111                 /* get the frequency order */
112                 if (freq != CPUFREQ_ENTRY_INVALID && descend == -1)
113                         descend = freq > pos->frequency;
114
115                 freq = pos->frequency;
116                 max_level++;
117         }
118
119         /* No valid cpu frequency entry */
120         if (max_level == 0)
121                 return -EINVAL;
122
123         /* max_level is an index, not a counter */
124         max_level--;
125
126         /* get max level */
127         if (property == GET_MAXL) {
128                 *output = max_level;
129                 return 0;
130         }
131
132         if (property == GET_FREQ)
133                 level = descend ? input : (max_level - input);
134
135         i = 0;
136         cpufreq_for_each_valid_entry(pos, table) {
137                 /* ignore duplicate entry */
138                 if (freq == pos->frequency)
139                         continue;
140
141                 /* now we have a valid frequency entry */
142                 freq = pos->frequency;
143
144                 if (property == GET_LEVEL && (unsigned int)input == freq) {
145                         /* get level by frequency */
146                         *output = descend ? i : (max_level - i);
147                         return 0;
148                 }
149                 if (property == GET_FREQ && level == i) {
150                         /* get frequency by level */
151                         *output = freq;
152                         return 0;
153                 }
154                 i++;
155         }
156
157         return -EINVAL;
158 }
159
160 /**
161  * clock_cooling_get_level - return the cooling level of given clock cooling.
162  * @cdev: reference of a thermal cooling device of used as clock cooling device
163  * @freq: the frequency of interest
164  *
165  * This function will match the cooling level corresponding to the
166  * requested @freq and return it.
167  *
168  * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID
169  * otherwise.
170  */
171 unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
172                                       unsigned long freq)
173 {
174         struct clock_cooling_device *ccdev = cdev->devdata;
175         unsigned long val;
176
177         if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val,
178                                        GET_LEVEL))
179                 return THERMAL_CSTATE_INVALID;
180
181         return val;
182 }
183 EXPORT_SYMBOL_GPL(clock_cooling_get_level);
184
185 /**
186  * clock_cooling_get_frequency - get the absolute value of frequency from level.
187  * @ccdev: clock cooling device reference
188  * @level: cooling level
189  *
190  * This function matches cooling level with frequency. Based on a cooling level
191  * of frequency, equals cooling state of cpu cooling device, it will return
192  * the corresponding frequency.
193  *      e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc
194  *
195  * Return: 0 on error, the corresponding frequency otherwise.
196  */
197 static unsigned long
198 clock_cooling_get_frequency(struct clock_cooling_device *ccdev,
199                             unsigned long level)
200 {
201         int ret = 0;
202         unsigned long freq;
203
204         ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ);
205         if (ret)
206                 return 0;
207
208         return freq;
209 }
210
211 /**
212  * clock_cooling_apply - function to apply frequency clipping.
213  * @ccdev: clock_cooling_device pointer containing frequency clipping data.
214  * @cooling_state: value of the cooling state.
215  *
216  * Function used to make sure the clock layer is aware of current thermal
217  * limits. The limits are applied by updating the clock rate in case it is
218  * higher than the corresponding frequency based on the requested cooling_state.
219  *
220  * Return: 0 on success, an error code otherwise (-EINVAL in case wrong
221  * cooling state).
222  */
223 static int clock_cooling_apply(struct clock_cooling_device *ccdev,
224                                unsigned long cooling_state)
225 {
226         unsigned long clip_freq, cur_freq;
227         int ret = 0;
228
229         /* Here we write the clipping */
230         /* Check if the old cooling action is same as new cooling action */
231         if (ccdev->clock_state == cooling_state)
232                 return 0;
233
234         clip_freq = clock_cooling_get_frequency(ccdev, cooling_state);
235         if (!clip_freq)
236                 return -EINVAL;
237
238         cur_freq = clk_get_rate(ccdev->clk);
239
240         mutex_lock(&ccdev->lock);
241         ccdev->clock_state = cooling_state;
242         ccdev->clock_val = clip_freq;
243         /* enforce clock level */
244         if (cur_freq > clip_freq)
245                 ret = clk_set_rate(ccdev->clk, clip_freq);
246         mutex_unlock(&ccdev->lock);
247
248         return ret;
249 }
250
251 /**
252  * clock_cooling_clock_notifier - notifier callback on clock rate changes.
253  * @nb: struct notifier_block * with callback info.
254  * @event: value showing clock event for which this function invoked.
255  * @data: callback-specific data
256  *
257  * Callback to hijack the notification on clock transition.
258  * Every time there is a clock change, we intercept all pre change events
259  * and block the transition in case the new rate infringes thermal limits.
260  *
261  * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit).
262  */
263 static int clock_cooling_clock_notifier(struct notifier_block *nb,
264                                         unsigned long event, void *data)
265 {
266         struct clk_notifier_data *ndata = data;
267         struct clock_cooling_device *ccdev = to_clock_cooling_device(nb);
268
269         switch (event) {
270         case PRE_RATE_CHANGE:
271                 /*
272                  * checks on current state
273                  * TODO: current method is not best we can find as it
274                  * allows possibly voltage transitions, in case DVFS
275                  * layer is also hijacking clock pre notifications.
276                  */
277                 if (ndata->new_rate > ccdev->clock_val)
278                         return NOTIFY_BAD;
279                 /* fall through */
280         case POST_RATE_CHANGE:
281         case ABORT_RATE_CHANGE:
282         default:
283                 return NOTIFY_DONE;
284         }
285 }
286
287 /* clock cooling device thermal callback functions are defined below */
288
289 /**
290  * clock_cooling_get_max_state - callback function to get the max cooling state.
291  * @cdev: thermal cooling device pointer.
292  * @state: fill this variable with the max cooling state.
293  *
294  * Callback for the thermal cooling device to return the clock
295  * max cooling state.
296  *
297  * Return: 0 on success, an error code otherwise.
298  */
299 static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev,
300                                        unsigned long *state)
301 {
302         struct clock_cooling_device *ccdev = cdev->devdata;
303         unsigned long count = 0;
304         int ret;
305
306         ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL);
307         if (!ret)
308                 *state = count;
309
310         return ret;
311 }
312
313 /**
314  * clock_cooling_get_cur_state - function to get the current cooling state.
315  * @cdev: thermal cooling device pointer.
316  * @state: fill this variable with the current cooling state.
317  *
318  * Callback for the thermal cooling device to return the clock
319  * current cooling state.
320  *
321  * Return: 0 (success)
322  */
323 static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev,
324                                        unsigned long *state)
325 {
326         struct clock_cooling_device *ccdev = cdev->devdata;
327
328         *state = ccdev->clock_state;
329
330         return 0;
331 }
332
333 /**
334  * clock_cooling_set_cur_state - function to set the current cooling state.
335  * @cdev: thermal cooling device pointer.
336  * @state: set this variable to the current cooling state.
337  *
338  * Callback for the thermal cooling device to change the clock cooling
339  * current cooling state.
340  *
341  * Return: 0 on success, an error code otherwise.
342  */
343 static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev,
344                                        unsigned long state)
345 {
346         struct clock_cooling_device *clock_device = cdev->devdata;
347
348         return clock_cooling_apply(clock_device, state);
349 }
350
351 /* Bind clock callbacks to thermal cooling device ops */
352 static struct thermal_cooling_device_ops const clock_cooling_ops = {
353         .get_max_state = clock_cooling_get_max_state,
354         .get_cur_state = clock_cooling_get_cur_state,
355         .set_cur_state = clock_cooling_set_cur_state,
356 };
357
358 /**
359  * clock_cooling_register - function to create clock cooling device.
360  * @dev: struct device pointer to the device used as clock cooling device.
361  * @clock_name: string containing the clock used as cooling mechanism.
362  *
363  * This interface function registers the clock cooling device with the name
364  * "thermal-clock-%x". The cooling device is based on clock frequencies.
365  * The struct device is assumed to be capable of DVFS transitions.
366  * The OPP layer is used to fetch and fill the available frequencies for
367  * the referred device. The ordered frequency table is used to control
368  * the clock cooling device cooling states and to limit clock transitions
369  * based on the cooling state requested by the thermal framework.
370  *
371  * Return: a valid struct thermal_cooling_device pointer on success,
372  * on failure, it returns a corresponding ERR_PTR().
373  */
374 struct thermal_cooling_device *
375 clock_cooling_register(struct device *dev, const char *clock_name)
376 {
377         struct thermal_cooling_device *cdev;
378         struct clock_cooling_device *ccdev = NULL;
379         char dev_name[THERMAL_NAME_LENGTH];
380         int ret = 0;
381
382         ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL);
383         if (!ccdev)
384                 return ERR_PTR(-ENOMEM);
385
386         mutex_init(&ccdev->lock);
387         ccdev->dev = dev;
388         ccdev->clk = devm_clk_get(dev, clock_name);
389         if (IS_ERR(ccdev->clk))
390                 return ERR_CAST(ccdev->clk);
391
392         ret = ida_simple_get(&clock_ida, 0, 0, GFP_KERNEL);
393         if (ret < 0)
394                 return ERR_PTR(ret);
395         ccdev->id = ret;
396
397         snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id);
398
399         cdev = thermal_cooling_device_register(dev_name, ccdev,
400                                                &clock_cooling_ops);
401         if (IS_ERR(cdev)) {
402                 ida_simple_remove(&clock_ida, ccdev->id);
403                 return ERR_PTR(-EINVAL);
404         }
405         ccdev->cdev = cdev;
406         ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier;
407
408         /* Assuming someone has already filled the opp table for this device */
409         ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table);
410         if (ret) {
411                 ida_simple_remove(&clock_ida, ccdev->id);
412                 return ERR_PTR(ret);
413         }
414         ccdev->clock_state = 0;
415         ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0);
416
417         clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb);
418
419         return cdev;
420 }
421 EXPORT_SYMBOL_GPL(clock_cooling_register);
422
423 /**
424  * clock_cooling_unregister - function to remove clock cooling device.
425  * @cdev: thermal cooling device pointer.
426  *
427  * This interface function unregisters the "thermal-clock-%x" cooling device.
428  */
429 void clock_cooling_unregister(struct thermal_cooling_device *cdev)
430 {
431         struct clock_cooling_device *ccdev;
432
433         if (!cdev)
434                 return;
435
436         ccdev = cdev->devdata;
437
438         clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb);
439         dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table);
440
441         thermal_cooling_device_unregister(ccdev->cdev);
442         ida_simple_remove(&clock_ida, ccdev->id);
443 }
444 EXPORT_SYMBOL_GPL(clock_cooling_unregister);