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 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 22 struct cpufreq_frequency_table *table) 23 { 24 unsigned int min_freq = ~0; 25 unsigned int max_freq = 0; 26 unsigned int i; 27 28 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { 29 unsigned int freq = table[i].frequency; 30 if (freq == CPUFREQ_ENTRY_INVALID) { 31 pr_debug("table entry %u is invalid, skipping\n", i); 32 33 continue; 34 } 35 if (!cpufreq_boost_enabled() 36 && table[i].driver_data == CPUFREQ_BOOST_FREQ) 37 continue; 38 39 pr_debug("table entry %u: %u kHz, %u driver_data\n", 40 i, freq, table[i].driver_data); 41 if (freq < min_freq) 42 min_freq = freq; 43 if (freq > max_freq) 44 max_freq = freq; 45 } 46 47 policy->min = policy->cpuinfo.min_freq = min_freq; 48 policy->max = policy->cpuinfo.max_freq = max_freq; 49 50 if (policy->min == ~0) 51 return -EINVAL; 52 else 53 return 0; 54 } 55 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo); 56 57 58 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, 59 struct cpufreq_frequency_table *table) 60 { 61 unsigned int next_larger = ~0, freq, i = 0; 62 bool found = false; 63 64 pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", 65 policy->min, policy->max, policy->cpu); 66 67 cpufreq_verify_within_cpu_limits(policy); 68 69 for (; freq = table[i].frequency, freq != CPUFREQ_TABLE_END; i++) { 70 if (freq == CPUFREQ_ENTRY_INVALID) 71 continue; 72 if ((freq >= policy->min) && (freq <= policy->max)) { 73 found = true; 74 break; 75 } 76 77 if ((next_larger > freq) && (freq > policy->max)) 78 next_larger = freq; 79 } 80 81 if (!found) { 82 policy->max = next_larger; 83 cpufreq_verify_within_cpu_limits(policy); 84 } 85 86 pr_debug("verification lead to (%u - %u kHz) for cpu %u\n", 87 policy->min, policy->max, policy->cpu); 88 89 return 0; 90 } 91 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); 92 93 /* 94 * Generic routine to verify policy & frequency table, requires driver to call 95 * cpufreq_frequency_table_get_attr() prior to it. 96 */ 97 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) 98 { 99 struct cpufreq_frequency_table *table = 100 cpufreq_frequency_get_table(policy->cpu); 101 if (!table) 102 return -ENODEV; 103 104 return cpufreq_frequency_table_verify(policy, table); 105 } 106 EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); 107 108 int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 109 struct cpufreq_frequency_table *table, 110 unsigned int target_freq, 111 unsigned int relation, 112 unsigned int *index) 113 { 114 struct cpufreq_frequency_table optimal = { 115 .driver_data = ~0, 116 .frequency = 0, 117 }; 118 struct cpufreq_frequency_table suboptimal = { 119 .driver_data = ~0, 120 .frequency = 0, 121 }; 122 unsigned int i; 123 124 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", 125 target_freq, relation, policy->cpu); 126 127 switch (relation) { 128 case CPUFREQ_RELATION_H: 129 suboptimal.frequency = ~0; 130 break; 131 case CPUFREQ_RELATION_L: 132 optimal.frequency = ~0; 133 break; 134 } 135 136 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { 137 unsigned int freq = table[i].frequency; 138 if (freq == CPUFREQ_ENTRY_INVALID) 139 continue; 140 if ((freq < policy->min) || (freq > policy->max)) 141 continue; 142 switch (relation) { 143 case CPUFREQ_RELATION_H: 144 if (freq <= target_freq) { 145 if (freq >= optimal.frequency) { 146 optimal.frequency = freq; 147 optimal.driver_data = i; 148 } 149 } else { 150 if (freq <= suboptimal.frequency) { 151 suboptimal.frequency = freq; 152 suboptimal.driver_data = i; 153 } 154 } 155 break; 156 case CPUFREQ_RELATION_L: 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 } 170 } 171 if (optimal.driver_data > i) { 172 if (suboptimal.driver_data > i) 173 return -EINVAL; 174 *index = suboptimal.driver_data; 175 } else 176 *index = optimal.driver_data; 177 178 pr_debug("target is %u (%u kHz, %u)\n", *index, table[*index].frequency, 179 table[*index].driver_data); 180 181 return 0; 182 } 183 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); 184 185 int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, 186 unsigned int freq) 187 { 188 struct cpufreq_frequency_table *table; 189 int i; 190 191 table = cpufreq_frequency_get_table(policy->cpu); 192 if (unlikely(!table)) { 193 pr_debug("%s: Unable to find frequency table\n", __func__); 194 return -ENOENT; 195 } 196 197 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { 198 if (table[i].frequency == freq) 199 return i; 200 } 201 202 return -EINVAL; 203 } 204 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); 205 206 static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); 207 208 /** 209 * show_available_freqs - show available frequencies for the specified CPU 210 */ 211 static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, 212 bool show_boost) 213 { 214 unsigned int i = 0; 215 unsigned int cpu = policy->cpu; 216 ssize_t count = 0; 217 struct cpufreq_frequency_table *table; 218 219 if (!per_cpu(cpufreq_show_table, cpu)) 220 return -ENODEV; 221 222 table = per_cpu(cpufreq_show_table, cpu); 223 224 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { 225 if (table[i].frequency == CPUFREQ_ENTRY_INVALID) 226 continue; 227 /* 228 * show_boost = true and driver_data = BOOST freq 229 * display BOOST freqs 230 * 231 * show_boost = false and driver_data = BOOST freq 232 * show_boost = true and driver_data != BOOST freq 233 * continue - do not display anything 234 * 235 * show_boost = false and driver_data != BOOST freq 236 * display NON BOOST freqs 237 */ 238 if (show_boost ^ (table[i].driver_data == CPUFREQ_BOOST_FREQ)) 239 continue; 240 241 count += sprintf(&buf[count], "%d ", table[i].frequency); 242 } 243 count += sprintf(&buf[count], "\n"); 244 245 return count; 246 247 } 248 249 #define cpufreq_attr_available_freq(_name) \ 250 struct freq_attr cpufreq_freq_attr_##_name##_freqs = \ 251 __ATTR_RO(_name##_frequencies) 252 253 /** 254 * show_scaling_available_frequencies - show available normal frequencies for 255 * the specified CPU 256 */ 257 static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy, 258 char *buf) 259 { 260 return show_available_freqs(policy, buf, false); 261 } 262 cpufreq_attr_available_freq(scaling_available); 263 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); 264 265 /** 266 * show_available_boost_freqs - show available boost frequencies for 267 * the specified CPU 268 */ 269 static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy, 270 char *buf) 271 { 272 return show_available_freqs(policy, buf, true); 273 } 274 cpufreq_attr_available_freq(scaling_boost); 275 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs); 276 277 struct freq_attr *cpufreq_generic_attr[] = { 278 &cpufreq_freq_attr_scaling_available_freqs, 279 #ifdef CONFIG_CPU_FREQ_BOOST_SW 280 &cpufreq_freq_attr_scaling_boost_freqs, 281 #endif 282 NULL, 283 }; 284 EXPORT_SYMBOL_GPL(cpufreq_generic_attr); 285 286 /* 287 * if you use these, you must assure that the frequency table is valid 288 * all the time between get_attr and put_attr! 289 */ 290 void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 291 unsigned int cpu) 292 { 293 pr_debug("setting show_table for cpu %u to %p\n", cpu, table); 294 per_cpu(cpufreq_show_table, cpu) = table; 295 } 296 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); 297 298 void cpufreq_frequency_table_put_attr(unsigned int cpu) 299 { 300 pr_debug("clearing show_table for cpu %u\n", cpu); 301 per_cpu(cpufreq_show_table, cpu) = NULL; 302 } 303 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); 304 305 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, 306 struct cpufreq_frequency_table *table) 307 { 308 int ret = cpufreq_frequency_table_cpuinfo(policy, table); 309 310 if (!ret) 311 cpufreq_frequency_table_get_attr(table, policy->cpu); 312 313 return ret; 314 } 315 EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); 316 317 void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy) 318 { 319 pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n", 320 policy->cpu, policy->last_cpu); 321 per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table, 322 policy->last_cpu); 323 per_cpu(cpufreq_show_table, policy->last_cpu) = NULL; 324 } 325 326 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) 327 { 328 return per_cpu(cpufreq_show_table, cpu); 329 } 330 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); 331 332 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); 333 MODULE_DESCRIPTION("CPUfreq frequency table helpers"); 334 MODULE_LICENSE("GPL"); 335