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  */
clock_cooling_get_property(struct clock_cooling_device * ccdev,unsigned long input,unsigned long * output,enum clock_cooling_property property)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  */
clock_cooling_get_level(struct thermal_cooling_device * cdev,unsigned long freq)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
clock_cooling_get_frequency(struct clock_cooling_device * ccdev,unsigned long level)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  */
clock_cooling_apply(struct clock_cooling_device * ccdev,unsigned long cooling_state)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  */
clock_cooling_clock_notifier(struct notifier_block * nb,unsigned long event,void * data)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  */
clock_cooling_get_max_state(struct thermal_cooling_device * cdev,unsigned long * state)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  */
clock_cooling_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * state)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  */
clock_cooling_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)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 *
clock_cooling_register(struct device * dev,const char * clock_name)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  */
clock_cooling_unregister(struct thermal_cooling_device * cdev)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);
445