18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/drivers/cpufreq/freq_table.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2002 - 2003 Dominik Brodowski 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/cpufreq.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/********************************************************************* 148c2ecf20Sopenharmony_ci * FREQUENCY TABLE HELPERS * 158c2ecf20Sopenharmony_ci *********************************************************************/ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cibool policy_has_boost_freq(struct cpufreq_policy *policy) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos, *table = policy->freq_table; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (!table) 228c2ecf20Sopenharmony_ci return false; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry(pos, table) 258c2ecf20Sopenharmony_ci if (pos->flags & CPUFREQ_BOOST_FREQ) 268c2ecf20Sopenharmony_ci return true; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci return false; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(policy_has_boost_freq); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciint cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 338c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *table) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos; 368c2ecf20Sopenharmony_ci unsigned int min_freq = ~0; 378c2ecf20Sopenharmony_ci unsigned int max_freq = 0; 388c2ecf20Sopenharmony_ci unsigned int freq; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry(pos, table) { 418c2ecf20Sopenharmony_ci freq = pos->frequency; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if (!cpufreq_boost_enabled() 448c2ecf20Sopenharmony_ci && (pos->flags & CPUFREQ_BOOST_FREQ)) 458c2ecf20Sopenharmony_ci continue; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci pr_debug("table entry %u: %u kHz\n", (int)(pos - table), freq); 488c2ecf20Sopenharmony_ci if (freq < min_freq) 498c2ecf20Sopenharmony_ci min_freq = freq; 508c2ecf20Sopenharmony_ci if (freq > max_freq) 518c2ecf20Sopenharmony_ci max_freq = freq; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci policy->min = policy->cpuinfo.min_freq = min_freq; 558c2ecf20Sopenharmony_ci policy->max = max_freq; 568c2ecf20Sopenharmony_ci /* 578c2ecf20Sopenharmony_ci * If the driver has set its own cpuinfo.max_freq above max_freq, leave 588c2ecf20Sopenharmony_ci * it as is. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci if (policy->cpuinfo.max_freq < max_freq) 618c2ecf20Sopenharmony_ci policy->max = policy->cpuinfo.max_freq = max_freq; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (policy->min == ~0) 648c2ecf20Sopenharmony_ci return -EINVAL; 658c2ecf20Sopenharmony_ci else 668c2ecf20Sopenharmony_ci return 0; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciint cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy, 708c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *table) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos; 738c2ecf20Sopenharmony_ci unsigned int freq, next_larger = ~0; 748c2ecf20Sopenharmony_ci bool found = false; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", 778c2ecf20Sopenharmony_ci policy->min, policy->max, policy->cpu); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci cpufreq_verify_within_cpu_limits(policy); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry(pos, table) { 828c2ecf20Sopenharmony_ci freq = pos->frequency; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if ((freq >= policy->min) && (freq <= policy->max)) { 858c2ecf20Sopenharmony_ci found = true; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if ((next_larger > freq) && (freq > policy->max)) 908c2ecf20Sopenharmony_ci next_larger = freq; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (!found) { 948c2ecf20Sopenharmony_ci policy->max = next_larger; 958c2ecf20Sopenharmony_ci cpufreq_verify_within_cpu_limits(policy); 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci pr_debug("verification lead to (%u - %u kHz) for cpu %u\n", 998c2ecf20Sopenharmony_ci policy->min, policy->max, policy->cpu); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return 0; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * Generic routine to verify policy & frequency table, requires driver to set 1078c2ecf20Sopenharmony_ci * policy->freq_table prior to it. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ciint cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci if (!policy->freq_table) 1128c2ecf20Sopenharmony_ci return -ENODEV; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return cpufreq_frequency_table_verify(policy, policy->freq_table); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ciint cpufreq_table_index_unsorted(struct cpufreq_policy *policy, 1198c2ecf20Sopenharmony_ci unsigned int target_freq, 1208c2ecf20Sopenharmony_ci unsigned int relation) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct cpufreq_frequency_table optimal = { 1238c2ecf20Sopenharmony_ci .driver_data = ~0, 1248c2ecf20Sopenharmony_ci .frequency = 0, 1258c2ecf20Sopenharmony_ci }; 1268c2ecf20Sopenharmony_ci struct cpufreq_frequency_table suboptimal = { 1278c2ecf20Sopenharmony_ci .driver_data = ~0, 1288c2ecf20Sopenharmony_ci .frequency = 0, 1298c2ecf20Sopenharmony_ci }; 1308c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos; 1318c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *table = policy->freq_table; 1328c2ecf20Sopenharmony_ci unsigned int freq, diff, i = 0; 1338c2ecf20Sopenharmony_ci int index; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", 1368c2ecf20Sopenharmony_ci target_freq, relation, policy->cpu); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci switch (relation) { 1398c2ecf20Sopenharmony_ci case CPUFREQ_RELATION_H: 1408c2ecf20Sopenharmony_ci suboptimal.frequency = ~0; 1418c2ecf20Sopenharmony_ci break; 1428c2ecf20Sopenharmony_ci case CPUFREQ_RELATION_L: 1438c2ecf20Sopenharmony_ci case CPUFREQ_RELATION_C: 1448c2ecf20Sopenharmony_ci optimal.frequency = ~0; 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry_idx(pos, table, i) { 1498c2ecf20Sopenharmony_ci freq = pos->frequency; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if ((freq < policy->min) || (freq > policy->max)) 1528c2ecf20Sopenharmony_ci continue; 1538c2ecf20Sopenharmony_ci if (freq == target_freq) { 1548c2ecf20Sopenharmony_ci optimal.driver_data = i; 1558c2ecf20Sopenharmony_ci break; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci switch (relation) { 1588c2ecf20Sopenharmony_ci case CPUFREQ_RELATION_H: 1598c2ecf20Sopenharmony_ci if (freq < target_freq) { 1608c2ecf20Sopenharmony_ci if (freq >= optimal.frequency) { 1618c2ecf20Sopenharmony_ci optimal.frequency = freq; 1628c2ecf20Sopenharmony_ci optimal.driver_data = i; 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci } else { 1658c2ecf20Sopenharmony_ci if (freq <= suboptimal.frequency) { 1668c2ecf20Sopenharmony_ci suboptimal.frequency = freq; 1678c2ecf20Sopenharmony_ci suboptimal.driver_data = i; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci break; 1718c2ecf20Sopenharmony_ci case CPUFREQ_RELATION_L: 1728c2ecf20Sopenharmony_ci if (freq > target_freq) { 1738c2ecf20Sopenharmony_ci if (freq <= optimal.frequency) { 1748c2ecf20Sopenharmony_ci optimal.frequency = freq; 1758c2ecf20Sopenharmony_ci optimal.driver_data = i; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci } else { 1788c2ecf20Sopenharmony_ci if (freq >= suboptimal.frequency) { 1798c2ecf20Sopenharmony_ci suboptimal.frequency = freq; 1808c2ecf20Sopenharmony_ci suboptimal.driver_data = i; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci break; 1848c2ecf20Sopenharmony_ci case CPUFREQ_RELATION_C: 1858c2ecf20Sopenharmony_ci diff = abs(freq - target_freq); 1868c2ecf20Sopenharmony_ci if (diff < optimal.frequency || 1878c2ecf20Sopenharmony_ci (diff == optimal.frequency && 1888c2ecf20Sopenharmony_ci freq > table[optimal.driver_data].frequency)) { 1898c2ecf20Sopenharmony_ci optimal.frequency = diff; 1908c2ecf20Sopenharmony_ci optimal.driver_data = i; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci break; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci if (optimal.driver_data > i) { 1968c2ecf20Sopenharmony_ci if (suboptimal.driver_data > i) { 1978c2ecf20Sopenharmony_ci WARN(1, "Invalid frequency table: %d\n", policy->cpu); 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci index = suboptimal.driver_data; 2028c2ecf20Sopenharmony_ci } else 2038c2ecf20Sopenharmony_ci index = optimal.driver_data; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci pr_debug("target index is %u, freq is:%u kHz\n", index, 2068c2ecf20Sopenharmony_ci table[index].frequency); 2078c2ecf20Sopenharmony_ci return index; 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_table_index_unsorted); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ciint cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, 2128c2ecf20Sopenharmony_ci unsigned int freq) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos, *table = policy->freq_table; 2158c2ecf20Sopenharmony_ci int idx; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (unlikely(!table)) { 2188c2ecf20Sopenharmony_ci pr_debug("%s: Unable to find frequency table\n", __func__); 2198c2ecf20Sopenharmony_ci return -ENOENT; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry_idx(pos, table, idx) 2238c2ecf20Sopenharmony_ci if (pos->frequency == freq) 2248c2ecf20Sopenharmony_ci return idx; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return -EINVAL; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci/* 2318c2ecf20Sopenharmony_ci * show_available_freqs - show available frequencies for the specified CPU 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_cistatic ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, 2348c2ecf20Sopenharmony_ci bool show_boost) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci ssize_t count = 0; 2378c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos, *table = policy->freq_table; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (!table) 2408c2ecf20Sopenharmony_ci return -ENODEV; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry(pos, table) { 2438c2ecf20Sopenharmony_ci /* 2448c2ecf20Sopenharmony_ci * show_boost = true and driver_data = BOOST freq 2458c2ecf20Sopenharmony_ci * display BOOST freqs 2468c2ecf20Sopenharmony_ci * 2478c2ecf20Sopenharmony_ci * show_boost = false and driver_data = BOOST freq 2488c2ecf20Sopenharmony_ci * show_boost = true and driver_data != BOOST freq 2498c2ecf20Sopenharmony_ci * continue - do not display anything 2508c2ecf20Sopenharmony_ci * 2518c2ecf20Sopenharmony_ci * show_boost = false and driver_data != BOOST freq 2528c2ecf20Sopenharmony_ci * display NON BOOST freqs 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci if (show_boost ^ (pos->flags & CPUFREQ_BOOST_FREQ)) 2558c2ecf20Sopenharmony_ci continue; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci count += sprintf(&buf[count], "%d ", pos->frequency); 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci count += sprintf(&buf[count], "\n"); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci return count; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#define cpufreq_attr_available_freq(_name) \ 2668c2ecf20Sopenharmony_cistruct freq_attr cpufreq_freq_attr_##_name##_freqs = \ 2678c2ecf20Sopenharmony_ci__ATTR_RO(_name##_frequencies) 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/* 2708c2ecf20Sopenharmony_ci * show_scaling_available_frequencies - show available normal frequencies for 2718c2ecf20Sopenharmony_ci * the specified CPU 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_cistatic ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy, 2748c2ecf20Sopenharmony_ci char *buf) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci return show_available_freqs(policy, buf, false); 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_cicpufreq_attr_available_freq(scaling_available); 2798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/* 2828c2ecf20Sopenharmony_ci * show_available_boost_freqs - show available boost frequencies for 2838c2ecf20Sopenharmony_ci * the specified CPU 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_cistatic ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy, 2868c2ecf20Sopenharmony_ci char *buf) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci return show_available_freqs(policy, buf, true); 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_cicpufreq_attr_available_freq(scaling_boost); 2918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistruct freq_attr *cpufreq_generic_attr[] = { 2948c2ecf20Sopenharmony_ci &cpufreq_freq_attr_scaling_available_freqs, 2958c2ecf20Sopenharmony_ci NULL, 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cpufreq_generic_attr); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic int set_freq_table_sorted(struct cpufreq_policy *policy) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *pos, *table = policy->freq_table; 3028c2ecf20Sopenharmony_ci struct cpufreq_frequency_table *prev = NULL; 3038c2ecf20Sopenharmony_ci int ascending = 0; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci policy->freq_table_sorted = CPUFREQ_TABLE_UNSORTED; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci cpufreq_for_each_valid_entry(pos, table) { 3088c2ecf20Sopenharmony_ci if (!prev) { 3098c2ecf20Sopenharmony_ci prev = pos; 3108c2ecf20Sopenharmony_ci continue; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (pos->frequency == prev->frequency) { 3148c2ecf20Sopenharmony_ci pr_warn("Duplicate freq-table entries: %u\n", 3158c2ecf20Sopenharmony_ci pos->frequency); 3168c2ecf20Sopenharmony_ci return -EINVAL; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* Frequency increased from prev to pos */ 3208c2ecf20Sopenharmony_ci if (pos->frequency > prev->frequency) { 3218c2ecf20Sopenharmony_ci /* But frequency was decreasing earlier */ 3228c2ecf20Sopenharmony_ci if (ascending < 0) { 3238c2ecf20Sopenharmony_ci pr_debug("Freq table is unsorted\n"); 3248c2ecf20Sopenharmony_ci return 0; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci ascending++; 3288c2ecf20Sopenharmony_ci } else { 3298c2ecf20Sopenharmony_ci /* Frequency decreased from prev to pos */ 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* But frequency was increasing earlier */ 3328c2ecf20Sopenharmony_ci if (ascending > 0) { 3338c2ecf20Sopenharmony_ci pr_debug("Freq table is unsorted\n"); 3348c2ecf20Sopenharmony_ci return 0; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci ascending--; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci prev = pos; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (ascending > 0) 3448c2ecf20Sopenharmony_ci policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_ASCENDING; 3458c2ecf20Sopenharmony_ci else 3468c2ecf20Sopenharmony_ci policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_DESCENDING; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci pr_debug("Freq table is sorted in %s order\n", 3498c2ecf20Sopenharmony_ci ascending > 0 ? "ascending" : "descending"); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci return 0; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ciint cpufreq_table_validate_and_sort(struct cpufreq_policy *policy) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci int ret; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (!policy->freq_table) 3598c2ecf20Sopenharmony_ci return 0; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); 3628c2ecf20Sopenharmony_ci if (ret) 3638c2ecf20Sopenharmony_ci return ret; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return set_freq_table_sorted(policy); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ciMODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); 3698c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CPUfreq frequency table helpers"); 3708c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 371