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