Lines Matching +full:clock +full:- +full:frequency
1 // SPDX-License-Identifier: GPL-2.0-only
26 * struct clock_cooling_device - data for cooling device with clock
30 * clock frequencies.
33 * @clk_rate_change_nb: reference to notifier block used to receive clock
35 * @freq_table: frequency table used to keep track of available frequencies.
36 * @clock_state: integer value representing the current state of clock
39 * frequency.
40 * @clk: struct clk reference used to enforce clock limits.
62 /* Below code defines functions to be used for clock as cooling device */
71 * clock_cooling_get_property - fetch a property of interest for a give cpu.
72 * @ccdev: clock cooling device reference
75 * @property: type of query (frequency, level, max level)
78 * 1. get maximum clock cooling states
79 * 2. translate frequency to cooling state
80 * 3. translate cooling state to frequency
87 * Return: 0 on success, -EINVAL when invalid parameters are passed.
97 int descend = -1; in clock_cooling_get_property()
98 struct cpufreq_frequency_table *pos, *table = ccdev->freq_table; in clock_cooling_get_property()
101 return -EINVAL; in clock_cooling_get_property()
104 return -EINVAL; in clock_cooling_get_property()
108 if (freq == pos->frequency) in clock_cooling_get_property()
111 /* get the frequency order */ in clock_cooling_get_property()
112 if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) in clock_cooling_get_property()
113 descend = freq > pos->frequency; in clock_cooling_get_property()
115 freq = pos->frequency; in clock_cooling_get_property()
119 /* No valid cpu frequency entry */ in clock_cooling_get_property()
121 return -EINVAL; in clock_cooling_get_property()
124 max_level--; in clock_cooling_get_property()
133 level = descend ? input : (max_level - input); in clock_cooling_get_property()
138 if (freq == pos->frequency) in clock_cooling_get_property()
141 /* now we have a valid frequency entry */ in clock_cooling_get_property()
142 freq = pos->frequency; in clock_cooling_get_property()
145 /* get level by frequency */ in clock_cooling_get_property()
146 *output = descend ? i : (max_level - i); in clock_cooling_get_property()
150 /* get frequency by level */ in clock_cooling_get_property()
157 return -EINVAL; in clock_cooling_get_property()
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
174 struct clock_cooling_device *ccdev = cdev->devdata; in clock_cooling_get_level()
186 * clock_cooling_get_frequency - get the absolute value of frequency from level.
187 * @ccdev: clock cooling device reference
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
195 * Return: 0 on error, the corresponding frequency otherwise.
212 * clock_cooling_apply - function to apply frequency clipping.
213 * @ccdev: clock_cooling_device pointer containing frequency clipping data.
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.
220 * Return: 0 on success, an error code otherwise (-EINVAL in case wrong
231 if (ccdev->clock_state == cooling_state) in clock_cooling_apply()
236 return -EINVAL; in clock_cooling_apply()
238 cur_freq = clk_get_rate(ccdev->clk); in clock_cooling_apply()
240 mutex_lock(&ccdev->lock); in clock_cooling_apply()
241 ccdev->clock_state = cooling_state; in clock_cooling_apply()
242 ccdev->clock_val = clip_freq; in clock_cooling_apply()
243 /* enforce clock level */ in clock_cooling_apply()
245 ret = clk_set_rate(ccdev->clk, clip_freq); in clock_cooling_apply()
246 mutex_unlock(&ccdev->lock); in clock_cooling_apply()
252 * clock_cooling_clock_notifier - notifier callback on clock rate changes.
254 * @event: value showing clock event for which this function invoked.
255 * @data: callback-specific data
257 * Callback to hijack the notification on clock transition.
258 * Every time there is a clock change, we intercept all pre change events
275 * layer is also hijacking clock pre notifications. in clock_cooling_clock_notifier()
277 if (ndata->new_rate > ccdev->clock_val) in clock_cooling_clock_notifier()
287 /* clock cooling device thermal callback functions are defined below */
290 * clock_cooling_get_max_state - callback function to get the max cooling state.
294 * Callback for the thermal cooling device to return the clock
302 struct clock_cooling_device *ccdev = cdev->devdata; in clock_cooling_get_max_state()
314 * clock_cooling_get_cur_state - function to get the current cooling state.
318 * Callback for the thermal cooling device to return the clock
326 struct clock_cooling_device *ccdev = cdev->devdata; in clock_cooling_get_cur_state()
328 *state = ccdev->clock_state; in clock_cooling_get_cur_state()
334 * clock_cooling_set_cur_state - function to set the current cooling state.
338 * Callback for the thermal cooling device to change the clock cooling
346 struct clock_cooling_device *clock_device = cdev->devdata; in clock_cooling_set_cur_state()
351 /* Bind clock callbacks to thermal cooling device ops */
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.
363 * This interface function registers the clock cooling device with the name
364 * "thermal-clock-%x". The cooling device is based on clock frequencies.
367 * the referred device. The ordered frequency table is used to control
368 * the clock cooling device cooling states and to limit clock transitions
384 return ERR_PTR(-ENOMEM); in clock_cooling_register()
386 mutex_init(&ccdev->lock); in clock_cooling_register()
387 ccdev->dev = dev; in clock_cooling_register()
388 ccdev->clk = devm_clk_get(dev, clock_name); in clock_cooling_register()
389 if (IS_ERR(ccdev->clk)) in clock_cooling_register()
390 return ERR_CAST(ccdev->clk); in clock_cooling_register()
395 ccdev->id = ret; in clock_cooling_register()
397 snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); in clock_cooling_register()
402 ida_simple_remove(&clock_ida, ccdev->id); in clock_cooling_register()
403 return ERR_PTR(-EINVAL); in clock_cooling_register()
405 ccdev->cdev = cdev; in clock_cooling_register()
406 ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier; in clock_cooling_register()
409 ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); in clock_cooling_register()
411 ida_simple_remove(&clock_ida, ccdev->id); in clock_cooling_register()
414 ccdev->clock_state = 0; in clock_cooling_register()
415 ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0); in clock_cooling_register()
417 clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb); in clock_cooling_register()
424 * clock_cooling_unregister - function to remove clock cooling device.
427 * This interface function unregisters the "thermal-clock-%x" cooling device.
436 ccdev = cdev->devdata; in clock_cooling_unregister()
438 clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb); in clock_cooling_unregister()
439 dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); in clock_cooling_unregister()
441 thermal_cooling_device_unregister(ccdev->cdev); in clock_cooling_unregister()
442 ida_simple_remove(&clock_ida, ccdev->id); in clock_cooling_unregister()