1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/cpufreq/freq_table.c
5 * Copyright (C) 2002 - 2003 Dominik Brodowski
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/cpufreq.h>
11 #include <linux/module.h>
13 /*********************************************************************
14 * FREQUENCY TABLE HELPERS *
15 *********************************************************************/
17 bool policy_has_boost_freq(struct cpufreq_policy
*policy
)
19 struct cpufreq_frequency_table
*pos
, *table
= policy
->freq_table
;
24 cpufreq_for_each_valid_entry(pos
, table
)
25 if (pos
->flags
& CPUFREQ_BOOST_FREQ
)
30 EXPORT_SYMBOL_GPL(policy_has_boost_freq
);
32 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy
*policy
,
33 struct cpufreq_frequency_table
*table
)
35 struct cpufreq_frequency_table
*pos
;
36 unsigned int min_freq
= ~0;
37 unsigned int max_freq
= 0;
40 cpufreq_for_each_valid_entry(pos
, table
) {
41 freq
= pos
->frequency
;
43 if ((!cpufreq_boost_enabled() || !policy
->boost_enabled
)
44 && (pos
->flags
& CPUFREQ_BOOST_FREQ
))
47 pr_debug("table entry %u: %u kHz\n", (int)(pos
- table
), freq
);
54 policy
->min
= policy
->cpuinfo
.min_freq
= min_freq
;
55 policy
->max
= max_freq
;
57 * If the driver has set its own cpuinfo.max_freq above max_freq, leave
60 if (policy
->cpuinfo
.max_freq
< max_freq
)
61 policy
->max
= policy
->cpuinfo
.max_freq
= max_freq
;
63 if (policy
->min
== ~0)
69 int cpufreq_frequency_table_verify(struct cpufreq_policy_data
*policy
,
70 struct cpufreq_frequency_table
*table
)
72 struct cpufreq_frequency_table
*pos
;
73 unsigned int freq
, prev_smaller
= 0;
76 pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
77 policy
->min
, policy
->max
, policy
->cpu
);
79 cpufreq_verify_within_cpu_limits(policy
);
81 cpufreq_for_each_valid_entry(pos
, table
) {
82 freq
= pos
->frequency
;
84 if ((freq
>= policy
->min
) && (freq
<= policy
->max
)) {
89 if ((prev_smaller
< freq
) && (freq
<= policy
->max
))
94 policy
->max
= prev_smaller
;
95 cpufreq_verify_within_cpu_limits(policy
);
98 pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
99 policy
->min
, policy
->max
, policy
->cpu
);
103 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify
);
106 * Generic routine to verify policy & frequency table, requires driver to set
107 * policy->freq_table prior to it.
109 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data
*policy
)
111 if (!policy
->freq_table
)
114 return cpufreq_frequency_table_verify(policy
, policy
->freq_table
);
116 EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify
);
118 int cpufreq_table_index_unsorted(struct cpufreq_policy
*policy
,
119 unsigned int target_freq
,
120 unsigned int relation
)
122 struct cpufreq_frequency_table optimal
= {
126 struct cpufreq_frequency_table suboptimal
= {
130 struct cpufreq_frequency_table
*pos
;
131 struct cpufreq_frequency_table
*table
= policy
->freq_table
;
132 unsigned int freq
, diff
, i
= 0;
135 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
136 target_freq
, relation
, policy
->cpu
);
139 case CPUFREQ_RELATION_H
:
140 suboptimal
.frequency
= ~0;
142 case CPUFREQ_RELATION_L
:
143 case CPUFREQ_RELATION_C
:
144 optimal
.frequency
= ~0;
148 cpufreq_for_each_valid_entry_idx(pos
, table
, i
) {
149 freq
= pos
->frequency
;
151 if ((freq
< policy
->min
) || (freq
> policy
->max
))
153 if (freq
== target_freq
) {
154 optimal
.driver_data
= i
;
158 case CPUFREQ_RELATION_H
:
159 if (freq
< target_freq
) {
160 if (freq
>= optimal
.frequency
) {
161 optimal
.frequency
= freq
;
162 optimal
.driver_data
= i
;
165 if (freq
<= suboptimal
.frequency
) {
166 suboptimal
.frequency
= freq
;
167 suboptimal
.driver_data
= i
;
171 case CPUFREQ_RELATION_L
:
172 if (freq
> target_freq
) {
173 if (freq
<= optimal
.frequency
) {
174 optimal
.frequency
= freq
;
175 optimal
.driver_data
= i
;
178 if (freq
>= suboptimal
.frequency
) {
179 suboptimal
.frequency
= freq
;
180 suboptimal
.driver_data
= i
;
184 case CPUFREQ_RELATION_C
:
185 diff
= abs(freq
- target_freq
);
186 if (diff
< optimal
.frequency
||
187 (diff
== optimal
.frequency
&&
188 freq
> table
[optimal
.driver_data
].frequency
)) {
189 optimal
.frequency
= diff
;
190 optimal
.driver_data
= i
;
195 if (optimal
.driver_data
> i
) {
196 if (suboptimal
.driver_data
> i
) {
197 WARN(1, "Invalid frequency table: %u\n", policy
->cpu
);
201 index
= suboptimal
.driver_data
;
203 index
= optimal
.driver_data
;
205 pr_debug("target index is %u, freq is:%u kHz\n", index
,
206 table
[index
].frequency
);
209 EXPORT_SYMBOL_GPL(cpufreq_table_index_unsorted
);
211 int cpufreq_frequency_table_get_index(struct cpufreq_policy
*policy
,
214 struct cpufreq_frequency_table
*pos
, *table
= policy
->freq_table
;
217 if (unlikely(!table
)) {
218 pr_debug("%s: Unable to find frequency table\n", __func__
);
222 cpufreq_for_each_valid_entry_idx(pos
, table
, idx
)
223 if (pos
->frequency
== freq
)
228 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index
);
231 * show_available_freqs - show available frequencies for the specified CPU
233 static ssize_t
show_available_freqs(struct cpufreq_policy
*policy
, char *buf
,
237 struct cpufreq_frequency_table
*pos
, *table
= policy
->freq_table
;
242 cpufreq_for_each_valid_entry(pos
, table
) {
244 * show_boost = true and driver_data = BOOST freq
245 * display BOOST freqs
247 * show_boost = false and driver_data = BOOST freq
248 * show_boost = true and driver_data != BOOST freq
249 * continue - do not display anything
251 * show_boost = false and driver_data != BOOST freq
252 * display NON BOOST freqs
254 if (show_boost
^ (pos
->flags
& CPUFREQ_BOOST_FREQ
))
257 count
+= sprintf(&buf
[count
], "%u ", pos
->frequency
);
259 count
+= sprintf(&buf
[count
], "\n");
265 #define cpufreq_attr_available_freq(_name) \
266 struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
267 __ATTR_RO(_name##_frequencies)
270 * scaling_available_frequencies_show - show available normal frequencies for
273 static ssize_t
scaling_available_frequencies_show(struct cpufreq_policy
*policy
,
276 return show_available_freqs(policy
, buf
, false);
278 cpufreq_attr_available_freq(scaling_available
);
279 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs
);
282 * scaling_boost_frequencies_show - show available boost frequencies for
285 static ssize_t
scaling_boost_frequencies_show(struct cpufreq_policy
*policy
,
288 return show_available_freqs(policy
, buf
, true);
290 cpufreq_attr_available_freq(scaling_boost
);
291 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs
);
293 struct freq_attr
*cpufreq_generic_attr
[] = {
294 &cpufreq_freq_attr_scaling_available_freqs
,
297 EXPORT_SYMBOL_GPL(cpufreq_generic_attr
);
299 static int set_freq_table_sorted(struct cpufreq_policy
*policy
)
301 struct cpufreq_frequency_table
*pos
, *table
= policy
->freq_table
;
302 struct cpufreq_frequency_table
*prev
= NULL
;
305 policy
->freq_table_sorted
= CPUFREQ_TABLE_UNSORTED
;
307 cpufreq_for_each_valid_entry(pos
, table
) {
313 if (pos
->frequency
== prev
->frequency
) {
314 pr_warn("Duplicate freq-table entries: %u\n",
319 /* Frequency increased from prev to pos */
320 if (pos
->frequency
> prev
->frequency
) {
321 /* But frequency was decreasing earlier */
323 pr_debug("Freq table is unsorted\n");
329 /* Frequency decreased from prev to pos */
331 /* But frequency was increasing earlier */
333 pr_debug("Freq table is unsorted\n");
344 policy
->freq_table_sorted
= CPUFREQ_TABLE_SORTED_ASCENDING
;
346 policy
->freq_table_sorted
= CPUFREQ_TABLE_SORTED_DESCENDING
;
348 pr_debug("Freq table is sorted in %s order\n",
349 ascending
> 0 ? "ascending" : "descending");
354 int cpufreq_table_validate_and_sort(struct cpufreq_policy
*policy
)
358 if (!policy
->freq_table
) {
359 /* Freq table must be passed by drivers with target_index() */
360 if (has_target_index())
366 ret
= cpufreq_frequency_table_cpuinfo(policy
, policy
->freq_table
);
370 return set_freq_table_sorted(policy
);
373 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
374 MODULE_DESCRIPTION("CPUfreq frequency table helpers");