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