1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/drivers/cpufreq/freq_table.c 4 * 5 * Copyright (C) 2002 - 2003 Dominik Brodowski 6 */ 7 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10 #include <linux/cpufreq.h> 11 #include <linux/module.h> 12 13 /********************************************************************* 14 * FREQUENCY TABLE HELPERS * 15 *********************************************************************/ 16 17 static bool policy_has_boost_freq(struct cpufreq_policy *policy) 18 { 19 struct cpufreq_frequency_table *pos, *table = policy->freq_table; 20 21 if (!table) 22 return false; 23 24 cpufreq_for_each_valid_entry(pos, table) 25 if (pos->flags & CPUFREQ_BOOST_FREQ) 26 return true; 27 28 return false; 29 } 30 31 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 32 struct cpufreq_frequency_table *table) 33 { 34 struct cpufreq_frequency_table *pos; 35 unsigned int min_freq = ~0; 36 unsigned int max_freq = 0; 37 unsigned int freq; 38 39 cpufreq_for_each_valid_entry(pos, table) { 40 freq = pos->frequency; 41 42 if ((!cpufreq_boost_enabled() || !policy->boost_enabled) 43 && (pos->flags & CPUFREQ_BOOST_FREQ)) 44 continue; 45 46 pr_debug("table entry %u: %u kHz\n", (int)(pos - table), freq); 47 if (freq < min_freq) 48 min_freq = freq; 49 if (freq > max_freq) 50 max_freq = freq; 51 } 52 53 policy->min = policy->cpuinfo.min_freq = min_freq; 54 policy->max = max_freq; 55 /* 56 * If the driver has set its own cpuinfo.max_freq above max_freq, leave 57 * it as is. 58 */ 59 if (policy->cpuinfo.max_freq < max_freq) 60 policy->max = policy->cpuinfo.max_freq = max_freq; 61 62 if (policy->min == ~0) 63 return -EINVAL; 64 else 65 return 0; 66 } 67 68 int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy, 69 struct cpufreq_frequency_table *table) 70 { 71 struct cpufreq_frequency_table *pos; 72 unsigned int freq, prev_smaller = 0; 73 bool found = false; 74 75 pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", 76 policy->min, policy->max, policy->cpu); 77 78 cpufreq_verify_within_cpu_limits(policy); 79 80 cpufreq_for_each_valid_entry(pos, table) { 81 freq = pos->frequency; 82 83 if ((freq >= policy->min) && (freq <= policy->max)) { 84 found = true; 85 break; 86 } 87 88 if ((prev_smaller < freq) && (freq <= policy->max)) 89 prev_smaller = freq; 90 } 91 92 if (!found) { 93 policy->max = prev_smaller; 94 cpufreq_verify_within_cpu_limits(policy); 95 } 96 97 pr_debug("verification lead to (%u - %u kHz) for cpu %u\n", 98 policy->min, policy->max, policy->cpu); 99 100 return 0; 101 } 102 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); 103 104 /* 105 * Generic routine to verify policy & frequency table, requires driver to set 106 * policy->freq_table prior to it. 107 */ 108 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy) 109 { 110 if (!policy->freq_table) 111 return -ENODEV; 112 113 return cpufreq_frequency_table_verify(policy, policy->freq_table); 114 } 115 EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); 116 117 int cpufreq_table_index_unsorted(struct cpufreq_policy *policy, 118 unsigned int target_freq, 119 unsigned int relation) 120 { 121 struct cpufreq_frequency_table optimal = { 122 .driver_data = ~0, 123 .frequency = 0, 124 }; 125 struct cpufreq_frequency_table suboptimal = { 126 .driver_data = ~0, 127 .frequency = 0, 128 }; 129 struct cpufreq_frequency_table *pos; 130 struct cpufreq_frequency_table *table = policy->freq_table; 131 unsigned int freq, diff, i = 0; 132 int index; 133 134 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", 135 target_freq, relation, policy->cpu); 136 137 switch (relation) { 138 case CPUFREQ_RELATION_H: 139 suboptimal.frequency = ~0; 140 break; 141 case CPUFREQ_RELATION_L: 142 case CPUFREQ_RELATION_C: 143 optimal.frequency = ~0; 144 break; 145 } 146 147 cpufreq_for_each_valid_entry_idx(pos, table, i) { 148 freq = pos->frequency; 149 150 if ((freq < policy->min) || (freq > policy->max)) 151 continue; 152 if (freq == target_freq) { 153 optimal.driver_data = i; 154 break; 155 } 156 switch (relation) { 157 case CPUFREQ_RELATION_H: 158 if (freq < target_freq) { 159 if (freq >= optimal.frequency) { 160 optimal.frequency = freq; 161 optimal.driver_data = i; 162 } 163 } else { 164 if (freq <= suboptimal.frequency) { 165 suboptimal.frequency = freq; 166 suboptimal.driver_data = i; 167 } 168 } 169 break; 170 case CPUFREQ_RELATION_L: 171 if (freq > target_freq) { 172 if (freq <= optimal.frequency) { 173 optimal.frequency = freq; 174 optimal.driver_data = i; 175 } 176 } else { 177 if (freq >= suboptimal.frequency) { 178 suboptimal.frequency = freq; 179 suboptimal.driver_data = i; 180 } 181 } 182 break; 183 case CPUFREQ_RELATION_C: 184 diff = abs(freq - target_freq); 185 if (diff < optimal.frequency || 186 (diff == optimal.frequency && 187 freq > table[optimal.driver_data].frequency)) { 188 optimal.frequency = diff; 189 optimal.driver_data = i; 190 } 191 break; 192 } 193 } 194 if (optimal.driver_data > i) { 195 if (suboptimal.driver_data > i) { 196 WARN(1, "Invalid frequency table: %u\n", policy->cpu); 197 return 0; 198 } 199 200 index = suboptimal.driver_data; 201 } else 202 index = optimal.driver_data; 203 204 pr_debug("target index is %u, freq is:%u kHz\n", index, 205 table[index].frequency); 206 return index; 207 } 208 EXPORT_SYMBOL_GPL(cpufreq_table_index_unsorted); 209 210 int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, 211 unsigned int freq) 212 { 213 struct cpufreq_frequency_table *pos, *table = policy->freq_table; 214 int idx; 215 216 if (unlikely(!table)) { 217 pr_debug("%s: Unable to find frequency table\n", __func__); 218 return -ENOENT; 219 } 220 221 cpufreq_for_each_valid_entry_idx(pos, table, idx) 222 if (pos->frequency == freq) 223 return idx; 224 225 return -EINVAL; 226 } 227 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); 228 229 /* 230 * show_available_freqs - show available frequencies for the specified CPU 231 */ 232 static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, 233 bool show_boost) 234 { 235 ssize_t count = 0; 236 struct cpufreq_frequency_table *pos, *table = policy->freq_table; 237 238 if (!table) 239 return -ENODEV; 240 241 cpufreq_for_each_valid_entry(pos, table) { 242 /* 243 * show_boost = true and driver_data = BOOST freq 244 * display BOOST freqs 245 * 246 * show_boost = false and driver_data = BOOST freq 247 * show_boost = true and driver_data != BOOST freq 248 * continue - do not display anything 249 * 250 * show_boost = false and driver_data != BOOST freq 251 * display NON BOOST freqs 252 */ 253 if (show_boost ^ (pos->flags & CPUFREQ_BOOST_FREQ)) 254 continue; 255 256 count += sprintf(&buf[count], "%u ", pos->frequency); 257 } 258 count += sprintf(&buf[count], "\n"); 259 260 return count; 261 262 } 263 264 #define cpufreq_attr_available_freq(_name) \ 265 struct freq_attr cpufreq_freq_attr_##_name##_freqs = \ 266 __ATTR_RO(_name##_frequencies) 267 268 /* 269 * scaling_available_frequencies_show - show available normal frequencies for 270 * the specified CPU 271 */ 272 static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy, 273 char *buf) 274 { 275 return show_available_freqs(policy, buf, false); 276 } 277 cpufreq_attr_available_freq(scaling_available); 278 279 /* 280 * scaling_boost_frequencies_show - show available boost frequencies for 281 * the specified CPU 282 */ 283 static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy, 284 char *buf) 285 { 286 return show_available_freqs(policy, buf, true); 287 } 288 cpufreq_attr_available_freq(scaling_boost); 289 290 static int set_freq_table_sorted(struct cpufreq_policy *policy) 291 { 292 struct cpufreq_frequency_table *pos, *table = policy->freq_table; 293 struct cpufreq_frequency_table *prev = NULL; 294 int ascending = 0; 295 296 policy->freq_table_sorted = CPUFREQ_TABLE_UNSORTED; 297 298 cpufreq_for_each_valid_entry(pos, table) { 299 if (!prev) { 300 prev = pos; 301 continue; 302 } 303 304 if (pos->frequency == prev->frequency) { 305 pr_warn("Duplicate freq-table entries: %u\n", 306 pos->frequency); 307 return -EINVAL; 308 } 309 310 /* Frequency increased from prev to pos */ 311 if (pos->frequency > prev->frequency) { 312 /* But frequency was decreasing earlier */ 313 if (ascending < 0) { 314 pr_debug("Freq table is unsorted\n"); 315 return 0; 316 } 317 318 ascending++; 319 } else { 320 /* Frequency decreased from prev to pos */ 321 322 /* But frequency was increasing earlier */ 323 if (ascending > 0) { 324 pr_debug("Freq table is unsorted\n"); 325 return 0; 326 } 327 328 ascending--; 329 } 330 331 prev = pos; 332 } 333 334 if (ascending > 0) 335 policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_ASCENDING; 336 else 337 policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_DESCENDING; 338 339 pr_debug("Freq table is sorted in %s order\n", 340 ascending > 0 ? "ascending" : "descending"); 341 342 return 0; 343 } 344 345 int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy) 346 { 347 int ret; 348 349 if (!policy->freq_table) { 350 /* Freq table must be passed by drivers with target_index() */ 351 if (has_target_index()) 352 return -EINVAL; 353 354 return 0; 355 } 356 357 ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); 358 if (ret) 359 return ret; 360 361 /* Driver's may have set this field already */ 362 if (policy_has_boost_freq(policy)) 363 policy->boost_supported = true; 364 365 return set_freq_table_sorted(policy); 366 } 367 368 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); 369 MODULE_DESCRIPTION("CPUfreq frequency table helpers"); 370