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