Merge remote-tracking branch 'spi/topic/cleanup' into spi-sh-msiof
[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                 if (freq == target_freq) {
141                         optimal.driver_data = i;
142                         break;
143                 }
144                 switch (relation) {
145                 case CPUFREQ_RELATION_H:
146                         if (freq < target_freq) {
147                                 if (freq >= optimal.frequency) {
148                                         optimal.frequency = freq;
149                                         optimal.driver_data = i;
150                                 }
151                         } else {
152                                 if (freq <= suboptimal.frequency) {
153                                         suboptimal.frequency = freq;
154                                         suboptimal.driver_data = i;
155                                 }
156                         }
157                         break;
158                 case CPUFREQ_RELATION_L:
159                         if (freq > target_freq) {
160                                 if (freq <= optimal.frequency) {
161                                         optimal.frequency = freq;
162                                         optimal.driver_data = i;
163                                 }
164                         } else {
165                                 if (freq >= suboptimal.frequency) {
166                                         suboptimal.frequency = freq;
167                                         suboptimal.driver_data = i;
168                                 }
169                         }
170                         break;
171                 }
172         }
173         if (optimal.driver_data > i) {
174                 if (suboptimal.driver_data > i)
175                         return -EINVAL;
176                 *index = suboptimal.driver_data;
177         } else
178                 *index = optimal.driver_data;
179
180         pr_debug("target index is %u, freq is:%u kHz\n", *index,
181                  table[*index].frequency);
182
183         return 0;
184 }
185 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
186
187 int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
188                 unsigned int freq)
189 {
190         struct cpufreq_frequency_table *pos, *table;
191
192         table = cpufreq_frequency_get_table(policy->cpu);
193         if (unlikely(!table)) {
194                 pr_debug("%s: Unable to find frequency table\n", __func__);
195                 return -ENOENT;
196         }
197
198         cpufreq_for_each_valid_entry(pos, table)
199                 if (pos->frequency == freq)
200                         return pos - table;
201
202         return -EINVAL;
203 }
204 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
205
206 /**
207  * show_available_freqs - show available frequencies for the specified CPU
208  */
209 static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
210                                     bool show_boost)
211 {
212         ssize_t count = 0;
213         struct cpufreq_frequency_table *pos, *table = policy->freq_table;
214
215         if (!table)
216                 return -ENODEV;
217
218         cpufreq_for_each_valid_entry(pos, table) {
219                 /*
220                  * show_boost = true and driver_data = BOOST freq
221                  * display BOOST freqs
222                  *
223                  * show_boost = false and driver_data = BOOST freq
224                  * show_boost = true and driver_data != BOOST freq
225                  * continue - do not display anything
226                  *
227                  * show_boost = false and driver_data != BOOST freq
228                  * display NON BOOST freqs
229                  */
230                 if (show_boost ^ (pos->flags & CPUFREQ_BOOST_FREQ))
231                         continue;
232
233                 count += sprintf(&buf[count], "%d ", pos->frequency);
234         }
235         count += sprintf(&buf[count], "\n");
236
237         return count;
238
239 }
240
241 #define cpufreq_attr_available_freq(_name)        \
242 struct freq_attr cpufreq_freq_attr_##_name##_freqs =     \
243 __ATTR_RO(_name##_frequencies)
244
245 /**
246  * show_scaling_available_frequencies - show available normal frequencies for
247  * the specified CPU
248  */
249 static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy,
250                                                   char *buf)
251 {
252         return show_available_freqs(policy, buf, false);
253 }
254 cpufreq_attr_available_freq(scaling_available);
255 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
256
257 /**
258  * show_available_boost_freqs - show available boost frequencies for
259  * the specified CPU
260  */
261 static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy,
262                                               char *buf)
263 {
264         return show_available_freqs(policy, buf, true);
265 }
266 cpufreq_attr_available_freq(scaling_boost);
267 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs);
268
269 struct freq_attr *cpufreq_generic_attr[] = {
270         &cpufreq_freq_attr_scaling_available_freqs,
271 #ifdef CONFIG_CPU_FREQ_BOOST_SW
272         &cpufreq_freq_attr_scaling_boost_freqs,
273 #endif
274         NULL,
275 };
276 EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
277
278 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
279                                       struct cpufreq_frequency_table *table)
280 {
281         int ret = cpufreq_frequency_table_cpuinfo(policy, table);
282
283         if (!ret)
284                 policy->freq_table = table;
285
286         return ret;
287 }
288 EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
289
290 struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
291
292 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
293 {
294         struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
295         return policy ? policy->freq_table : NULL;
296 }
297 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
298
299 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
300 MODULE_DESCRIPTION("CPUfreq frequency table helpers");
301 MODULE_LICENSE("GPL");