|
|
@@ -36,6 +36,12 @@
|
|
|
|
|
|
struct cpufreq_governor;
|
|
|
|
|
|
+enum cpufreq_table_sorting {
|
|
|
+ CPUFREQ_TABLE_UNSORTED,
|
|
|
+ CPUFREQ_TABLE_SORTED_ASCENDING,
|
|
|
+ CPUFREQ_TABLE_SORTED_DESCENDING
|
|
|
+};
|
|
|
+
|
|
|
struct cpufreq_freqs {
|
|
|
unsigned int cpu; /* cpu nr */
|
|
|
unsigned int old;
|
|
|
@@ -87,6 +93,7 @@ struct cpufreq_policy {
|
|
|
|
|
|
struct cpufreq_user_policy user_policy;
|
|
|
struct cpufreq_frequency_table *freq_table;
|
|
|
+ enum cpufreq_table_sorting freq_table_sorted;
|
|
|
|
|
|
struct list_head policy_list;
|
|
|
struct kobject kobj;
|
|
|
@@ -597,9 +604,9 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
|
|
|
struct cpufreq_frequency_table *table);
|
|
|
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
|
|
|
|
|
|
-int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
|
|
- unsigned int target_freq,
|
|
|
- unsigned int relation);
|
|
|
+int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq,
|
|
|
+ unsigned int relation);
|
|
|
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
|
|
|
unsigned int freq);
|
|
|
|
|
|
@@ -610,6 +617,227 @@ int cpufreq_boost_trigger_state(int state);
|
|
|
int cpufreq_boost_enabled(void);
|
|
|
int cpufreq_enable_boost_support(void);
|
|
|
bool policy_has_boost_freq(struct cpufreq_policy *policy);
|
|
|
+
|
|
|
+/* Find lowest freq at or above target in a table in ascending order */
|
|
|
+static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ struct cpufreq_frequency_table *table = policy->freq_table;
|
|
|
+ unsigned int freq;
|
|
|
+ int i, best = -1;
|
|
|
+
|
|
|
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
|
|
+ freq = table[i].frequency;
|
|
|
+
|
|
|
+ if (freq >= target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ best = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ return best;
|
|
|
+}
|
|
|
+
|
|
|
+/* Find lowest freq at or above target in a table in descending order */
|
|
|
+static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ struct cpufreq_frequency_table *table = policy->freq_table;
|
|
|
+ unsigned int freq;
|
|
|
+ int i, best = -1;
|
|
|
+
|
|
|
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
|
|
+ freq = table[i].frequency;
|
|
|
+
|
|
|
+ if (freq == target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ if (freq > target_freq) {
|
|
|
+ best = i;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No freq found above target_freq */
|
|
|
+ if (best == -1)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ return best;
|
|
|
+ }
|
|
|
+
|
|
|
+ return best;
|
|
|
+}
|
|
|
+
|
|
|
+/* Works only on sorted freq-tables */
|
|
|
+static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ target_freq = clamp_val(target_freq, policy->min, policy->max);
|
|
|
+
|
|
|
+ if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
|
|
+ return cpufreq_table_find_index_al(policy, target_freq);
|
|
|
+ else
|
|
|
+ return cpufreq_table_find_index_dl(policy, target_freq);
|
|
|
+}
|
|
|
+
|
|
|
+/* Find highest freq at or below target in a table in ascending order */
|
|
|
+static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ struct cpufreq_frequency_table *table = policy->freq_table;
|
|
|
+ unsigned int freq;
|
|
|
+ int i, best = -1;
|
|
|
+
|
|
|
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
|
|
+ freq = table[i].frequency;
|
|
|
+
|
|
|
+ if (freq == target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ if (freq < target_freq) {
|
|
|
+ best = i;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No freq found below target_freq */
|
|
|
+ if (best == -1)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ return best;
|
|
|
+ }
|
|
|
+
|
|
|
+ return best;
|
|
|
+}
|
|
|
+
|
|
|
+/* Find highest freq at or below target in a table in descending order */
|
|
|
+static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ struct cpufreq_frequency_table *table = policy->freq_table;
|
|
|
+ unsigned int freq;
|
|
|
+ int i, best = -1;
|
|
|
+
|
|
|
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
|
|
+ freq = table[i].frequency;
|
|
|
+
|
|
|
+ if (freq <= target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ best = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ return best;
|
|
|
+}
|
|
|
+
|
|
|
+/* Works only on sorted freq-tables */
|
|
|
+static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ target_freq = clamp_val(target_freq, policy->min, policy->max);
|
|
|
+
|
|
|
+ if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
|
|
+ return cpufreq_table_find_index_ah(policy, target_freq);
|
|
|
+ else
|
|
|
+ return cpufreq_table_find_index_dh(policy, target_freq);
|
|
|
+}
|
|
|
+
|
|
|
+/* Find closest freq to target in a table in ascending order */
|
|
|
+static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ struct cpufreq_frequency_table *table = policy->freq_table;
|
|
|
+ unsigned int freq;
|
|
|
+ int i, best = -1;
|
|
|
+
|
|
|
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
|
|
+ freq = table[i].frequency;
|
|
|
+
|
|
|
+ if (freq == target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ if (freq < target_freq) {
|
|
|
+ best = i;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No freq found below target_freq */
|
|
|
+ if (best == -1)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ /* Choose the closest freq */
|
|
|
+ if (target_freq - table[best].frequency > freq - target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ return best;
|
|
|
+ }
|
|
|
+
|
|
|
+ return best;
|
|
|
+}
|
|
|
+
|
|
|
+/* Find closest freq to target in a table in descending order */
|
|
|
+static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ struct cpufreq_frequency_table *table = policy->freq_table;
|
|
|
+ unsigned int freq;
|
|
|
+ int i, best = -1;
|
|
|
+
|
|
|
+ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
|
|
+ freq = table[i].frequency;
|
|
|
+
|
|
|
+ if (freq == target_freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ if (freq > target_freq) {
|
|
|
+ best = i;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No freq found above target_freq */
|
|
|
+ if (best == -1)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ /* Choose the closest freq */
|
|
|
+ if (table[best].frequency - target_freq > target_freq - freq)
|
|
|
+ return i;
|
|
|
+
|
|
|
+ return best;
|
|
|
+ }
|
|
|
+
|
|
|
+ return best;
|
|
|
+}
|
|
|
+
|
|
|
+/* Works only on sorted freq-tables */
|
|
|
+static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq)
|
|
|
+{
|
|
|
+ target_freq = clamp_val(target_freq, policy->min, policy->max);
|
|
|
+
|
|
|
+ if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
|
|
+ return cpufreq_table_find_index_ac(policy, target_freq);
|
|
|
+ else
|
|
|
+ return cpufreq_table_find_index_dc(policy, target_freq);
|
|
|
+}
|
|
|
+
|
|
|
+static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
|
|
+ unsigned int target_freq,
|
|
|
+ unsigned int relation)
|
|
|
+{
|
|
|
+ if (unlikely(policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED))
|
|
|
+ return cpufreq_table_index_unsorted(policy, target_freq,
|
|
|
+ relation);
|
|
|
+
|
|
|
+ switch (relation) {
|
|
|
+ case CPUFREQ_RELATION_L:
|
|
|
+ return cpufreq_table_find_index_l(policy, target_freq);
|
|
|
+ case CPUFREQ_RELATION_H:
|
|
|
+ return cpufreq_table_find_index_h(policy, target_freq);
|
|
|
+ case CPUFREQ_RELATION_C:
|
|
|
+ return cpufreq_table_find_index_c(policy, target_freq);
|
|
|
+ default:
|
|
|
+ pr_err("%s: Invalid relation: %d\n", __func__, relation);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+}
|
|
|
#else
|
|
|
static inline int cpufreq_boost_trigger_state(int state)
|
|
|
{
|