Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[sfrench/cifs-2.6.git] / drivers / cpufreq / s3c2416-cpufreq.c
1 /*
2  * S3C2416/2450 CPUfreq Support
3  *
4  * Copyright 2011 Heiko Stuebner <heiko@sntech.de>
5  *
6  * based on s3c64xx_cpufreq.c
7  *
8  * Copyright 2009 Wolfson Microelectronics plc
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/init.h>
18 #include <linux/cpufreq.h>
19 #include <linux/clk.h>
20 #include <linux/err.h>
21 #include <linux/regulator/consumer.h>
22 #include <linux/reboot.h>
23 #include <linux/module.h>
24
25 static DEFINE_MUTEX(cpufreq_lock);
26
27 struct s3c2416_data {
28         struct clk *armdiv;
29         struct clk *armclk;
30         struct clk *hclk;
31
32         unsigned long regulator_latency;
33 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
34         struct regulator *vddarm;
35 #endif
36
37         struct cpufreq_frequency_table *freq_table;
38
39         bool is_dvs;
40         bool disable_dvs;
41 };
42
43 static struct s3c2416_data s3c2416_cpufreq;
44
45 struct s3c2416_dvfs {
46         unsigned int vddarm_min;
47         unsigned int vddarm_max;
48 };
49
50 /* pseudo-frequency for dvs mode */
51 #define FREQ_DVS        132333
52
53 /* frequency to sleep and reboot in
54  * it's essential to leave dvs, as some boards do not reconfigure the
55  * regulator on reboot
56  */
57 #define FREQ_SLEEP      133333
58
59 /* Sources for the ARMCLK */
60 #define SOURCE_HCLK     0
61 #define SOURCE_ARMDIV   1
62
63 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
64 /* S3C2416 only supports changing the voltage in the dvs-mode.
65  * Voltages down to 1.0V seem to work, so we take what the regulator
66  * can get us.
67  */
68 static struct s3c2416_dvfs s3c2416_dvfs_table[] = {
69         [SOURCE_HCLK] = {  950000, 1250000 },
70         [SOURCE_ARMDIV] = { 1250000, 1350000 },
71 };
72 #endif
73
74 static struct cpufreq_frequency_table s3c2416_freq_table[] = {
75         { SOURCE_HCLK, FREQ_DVS },
76         { SOURCE_ARMDIV, 133333 },
77         { SOURCE_ARMDIV, 266666 },
78         { SOURCE_ARMDIV, 400000 },
79         { 0, CPUFREQ_TABLE_END },
80 };
81
82 static struct cpufreq_frequency_table s3c2450_freq_table[] = {
83         { SOURCE_HCLK, FREQ_DVS },
84         { SOURCE_ARMDIV, 133500 },
85         { SOURCE_ARMDIV, 267000 },
86         { SOURCE_ARMDIV, 534000 },
87         { 0, CPUFREQ_TABLE_END },
88 };
89
90 static int s3c2416_cpufreq_verify_speed(struct cpufreq_policy *policy)
91 {
92         struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
93
94         if (policy->cpu != 0)
95                 return -EINVAL;
96
97         return cpufreq_frequency_table_verify(policy, s3c_freq->freq_table);
98 }
99
100 static unsigned int s3c2416_cpufreq_get_speed(unsigned int cpu)
101 {
102         struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
103
104         if (cpu != 0)
105                 return 0;
106
107         /* return our pseudo-frequency when in dvs mode */
108         if (s3c_freq->is_dvs)
109                 return FREQ_DVS;
110
111         return clk_get_rate(s3c_freq->armclk) / 1000;
112 }
113
114 static int s3c2416_cpufreq_set_armdiv(struct s3c2416_data *s3c_freq,
115                                       unsigned int freq)
116 {
117         int ret;
118
119         if (clk_get_rate(s3c_freq->armdiv) / 1000 != freq) {
120                 ret = clk_set_rate(s3c_freq->armdiv, freq * 1000);
121                 if (ret < 0) {
122                         pr_err("cpufreq: Failed to set armdiv rate %dkHz: %d\n",
123                                freq, ret);
124                         return ret;
125                 }
126         }
127
128         return 0;
129 }
130
131 static int s3c2416_cpufreq_enter_dvs(struct s3c2416_data *s3c_freq, int idx)
132 {
133 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
134         struct s3c2416_dvfs *dvfs;
135 #endif
136         int ret;
137
138         if (s3c_freq->is_dvs) {
139                 pr_debug("cpufreq: already in dvs mode, nothing to do\n");
140                 return 0;
141         }
142
143         pr_debug("cpufreq: switching armclk to hclk (%lukHz)\n",
144                  clk_get_rate(s3c_freq->hclk) / 1000);
145         ret = clk_set_parent(s3c_freq->armclk, s3c_freq->hclk);
146         if (ret < 0) {
147                 pr_err("cpufreq: Failed to switch armclk to hclk: %d\n", ret);
148                 return ret;
149         }
150
151 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
152         /* changing the core voltage is only allowed when in dvs mode */
153         if (s3c_freq->vddarm) {
154                 dvfs = &s3c2416_dvfs_table[idx];
155
156                 pr_debug("cpufreq: setting regulator to %d-%d\n",
157                          dvfs->vddarm_min, dvfs->vddarm_max);
158                 ret = regulator_set_voltage(s3c_freq->vddarm,
159                                             dvfs->vddarm_min,
160                                             dvfs->vddarm_max);
161
162                 /* when lowering the voltage failed, there is nothing to do */
163                 if (ret != 0)
164                         pr_err("cpufreq: Failed to set VDDARM: %d\n", ret);
165         }
166 #endif
167
168         s3c_freq->is_dvs = 1;
169
170         return 0;
171 }
172
173 static int s3c2416_cpufreq_leave_dvs(struct s3c2416_data *s3c_freq, int idx)
174 {
175 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
176         struct s3c2416_dvfs *dvfs;
177 #endif
178         int ret;
179
180         if (!s3c_freq->is_dvs) {
181                 pr_debug("cpufreq: not in dvs mode, so can't leave\n");
182                 return 0;
183         }
184
185 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
186         if (s3c_freq->vddarm) {
187                 dvfs = &s3c2416_dvfs_table[idx];
188
189                 pr_debug("cpufreq: setting regulator to %d-%d\n",
190                          dvfs->vddarm_min, dvfs->vddarm_max);
191                 ret = regulator_set_voltage(s3c_freq->vddarm,
192                                             dvfs->vddarm_min,
193                                             dvfs->vddarm_max);
194                 if (ret != 0) {
195                         pr_err("cpufreq: Failed to set VDDARM: %d\n", ret);
196                         return ret;
197                 }
198         }
199 #endif
200
201         /* force armdiv to hclk frequency for transition from dvs*/
202         if (clk_get_rate(s3c_freq->armdiv) > clk_get_rate(s3c_freq->hclk)) {
203                 pr_debug("cpufreq: force armdiv to hclk frequency (%lukHz)\n",
204                          clk_get_rate(s3c_freq->hclk) / 1000);
205                 ret = s3c2416_cpufreq_set_armdiv(s3c_freq,
206                                         clk_get_rate(s3c_freq->hclk) / 1000);
207                 if (ret < 0) {
208                         pr_err("cpufreq: Failed to set the armdiv to %lukHz: %d\n",
209                                clk_get_rate(s3c_freq->hclk) / 1000, ret);
210                         return ret;
211                 }
212         }
213
214         pr_debug("cpufreq: switching armclk parent to armdiv (%lukHz)\n",
215                         clk_get_rate(s3c_freq->armdiv) / 1000);
216
217         ret = clk_set_parent(s3c_freq->armclk, s3c_freq->armdiv);
218         if (ret < 0) {
219                 pr_err("cpufreq: Failed to switch armclk clock parent to armdiv: %d\n",
220                        ret);
221                 return ret;
222         }
223
224         s3c_freq->is_dvs = 0;
225
226         return 0;
227 }
228
229 static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
230                                       unsigned int target_freq,
231                                       unsigned int relation)
232 {
233         struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
234         struct cpufreq_freqs freqs;
235         int idx, ret, to_dvs = 0;
236         unsigned int i;
237
238         mutex_lock(&cpufreq_lock);
239
240         pr_debug("cpufreq: to %dKHz, relation %d\n", target_freq, relation);
241
242         ret = cpufreq_frequency_table_target(policy, s3c_freq->freq_table,
243                                              target_freq, relation, &i);
244         if (ret != 0)
245                 goto out;
246
247         idx = s3c_freq->freq_table[i].driver_data;
248
249         if (idx == SOURCE_HCLK)
250                 to_dvs = 1;
251
252         /* switching to dvs when it's not allowed */
253         if (to_dvs && s3c_freq->disable_dvs) {
254                 pr_debug("cpufreq: entering dvs mode not allowed\n");
255                 ret = -EINVAL;
256                 goto out;
257         }
258
259         freqs.flags = 0;
260         freqs.old = s3c_freq->is_dvs ? FREQ_DVS
261                                      : clk_get_rate(s3c_freq->armclk) / 1000;
262
263         /* When leavin dvs mode, always switch the armdiv to the hclk rate
264          * The S3C2416 has stability issues when switching directly to
265          * higher frequencies.
266          */
267         freqs.new = (s3c_freq->is_dvs && !to_dvs)
268                                 ? clk_get_rate(s3c_freq->hclk) / 1000
269                                 : s3c_freq->freq_table[i].frequency;
270
271         pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
272
273         if (!to_dvs && freqs.old == freqs.new)
274                 goto out;
275
276         cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
277
278         if (to_dvs) {
279                 pr_debug("cpufreq: enter dvs\n");
280                 ret = s3c2416_cpufreq_enter_dvs(s3c_freq, idx);
281         } else if (s3c_freq->is_dvs) {
282                 pr_debug("cpufreq: leave dvs\n");
283                 ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx);
284         } else {
285                 pr_debug("cpufreq: change armdiv to %dkHz\n", freqs.new);
286                 ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new);
287         }
288
289         cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
290
291 out:
292         mutex_unlock(&cpufreq_lock);
293
294         return ret;
295 }
296
297 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
298 static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq)
299 {
300         int count, v, i, found;
301         struct cpufreq_frequency_table *freq;
302         struct s3c2416_dvfs *dvfs;
303
304         count = regulator_count_voltages(s3c_freq->vddarm);
305         if (count < 0) {
306                 pr_err("cpufreq: Unable to check supported voltages\n");
307                 return;
308         }
309
310         freq = s3c_freq->freq_table;
311         while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) {
312                 if (freq->frequency == CPUFREQ_ENTRY_INVALID)
313                         continue;
314
315                 dvfs = &s3c2416_dvfs_table[freq->driver_data];
316                 found = 0;
317
318                 /* Check only the min-voltage, more is always ok on S3C2416 */
319                 for (i = 0; i < count; i++) {
320                         v = regulator_list_voltage(s3c_freq->vddarm, i);
321                         if (v >= dvfs->vddarm_min)
322                                 found = 1;
323                 }
324
325                 if (!found) {
326                         pr_debug("cpufreq: %dkHz unsupported by regulator\n",
327                                  freq->frequency);
328                         freq->frequency = CPUFREQ_ENTRY_INVALID;
329                 }
330
331                 freq++;
332         }
333
334         /* Guessed */
335         s3c_freq->regulator_latency = 1 * 1000 * 1000;
336 }
337 #endif
338
339 static int s3c2416_cpufreq_reboot_notifier_evt(struct notifier_block *this,
340                                                unsigned long event, void *ptr)
341 {
342         struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
343         int ret;
344
345         mutex_lock(&cpufreq_lock);
346
347         /* disable further changes */
348         s3c_freq->disable_dvs = 1;
349
350         mutex_unlock(&cpufreq_lock);
351
352         /* some boards don't reconfigure the regulator on reboot, which
353          * could lead to undervolting the cpu when the clock is reset.
354          * Therefore we always leave the DVS mode on reboot.
355          */
356         if (s3c_freq->is_dvs) {
357                 pr_debug("cpufreq: leave dvs on reboot\n");
358                 ret = cpufreq_driver_target(cpufreq_cpu_get(0), FREQ_SLEEP, 0);
359                 if (ret < 0)
360                         return NOTIFY_BAD;
361         }
362
363         return NOTIFY_DONE;
364 }
365
366 static struct notifier_block s3c2416_cpufreq_reboot_notifier = {
367         .notifier_call = s3c2416_cpufreq_reboot_notifier_evt,
368 };
369
370 static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
371 {
372         struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
373         struct cpufreq_frequency_table *freq;
374         struct clk *msysclk;
375         unsigned long rate;
376         int ret;
377
378         if (policy->cpu != 0)
379                 return -EINVAL;
380
381         msysclk = clk_get(NULL, "msysclk");
382         if (IS_ERR(msysclk)) {
383                 ret = PTR_ERR(msysclk);
384                 pr_err("cpufreq: Unable to obtain msysclk: %d\n", ret);
385                 return ret;
386         }
387
388         /*
389          * S3C2416 and S3C2450 share the same processor-ID and also provide no
390          * other means to distinguish them other than through the rate of
391          * msysclk. On S3C2416 msysclk runs at 800MHz and on S3C2450 at 533MHz.
392          */
393         rate = clk_get_rate(msysclk);
394         if (rate == 800 * 1000 * 1000) {
395                 pr_info("cpufreq: msysclk running at %lukHz, using S3C2416 frequency table\n",
396                         rate / 1000);
397                 s3c_freq->freq_table = s3c2416_freq_table;
398                 policy->cpuinfo.max_freq = 400000;
399         } else if (rate / 1000 == 534000) {
400                 pr_info("cpufreq: msysclk running at %lukHz, using S3C2450 frequency table\n",
401                         rate / 1000);
402                 s3c_freq->freq_table = s3c2450_freq_table;
403                 policy->cpuinfo.max_freq = 534000;
404         }
405
406         /* not needed anymore */
407         clk_put(msysclk);
408
409         if (s3c_freq->freq_table == NULL) {
410                 pr_err("cpufreq: No frequency information for this CPU, msysclk at %lukHz\n",
411                        rate / 1000);
412                 return -ENODEV;
413         }
414
415         s3c_freq->is_dvs = 0;
416
417         s3c_freq->armdiv = clk_get(NULL, "armdiv");
418         if (IS_ERR(s3c_freq->armdiv)) {
419                 ret = PTR_ERR(s3c_freq->armdiv);
420                 pr_err("cpufreq: Unable to obtain ARMDIV: %d\n", ret);
421                 return ret;
422         }
423
424         s3c_freq->hclk = clk_get(NULL, "hclk");
425         if (IS_ERR(s3c_freq->hclk)) {
426                 ret = PTR_ERR(s3c_freq->hclk);
427                 pr_err("cpufreq: Unable to obtain HCLK: %d\n", ret);
428                 goto err_hclk;
429         }
430
431         /* chech hclk rate, we only support the common 133MHz for now
432          * hclk could also run at 66MHz, but this not often used
433          */
434         rate = clk_get_rate(s3c_freq->hclk);
435         if (rate < 133 * 1000 * 1000) {
436                 pr_err("cpufreq: HCLK not at 133MHz\n");
437                 clk_put(s3c_freq->hclk);
438                 ret = -EINVAL;
439                 goto err_armclk;
440         }
441
442         s3c_freq->armclk = clk_get(NULL, "armclk");
443         if (IS_ERR(s3c_freq->armclk)) {
444                 ret = PTR_ERR(s3c_freq->armclk);
445                 pr_err("cpufreq: Unable to obtain ARMCLK: %d\n", ret);
446                 goto err_armclk;
447         }
448
449 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
450         s3c_freq->vddarm = regulator_get(NULL, "vddarm");
451         if (IS_ERR(s3c_freq->vddarm)) {
452                 ret = PTR_ERR(s3c_freq->vddarm);
453                 pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
454                 goto err_vddarm;
455         }
456
457         s3c2416_cpufreq_cfg_regulator(s3c_freq);
458 #else
459         s3c_freq->regulator_latency = 0;
460 #endif
461
462         freq = s3c_freq->freq_table;
463         while (freq->frequency != CPUFREQ_TABLE_END) {
464                 /* special handling for dvs mode */
465                 if (freq->driver_data == 0) {
466                         if (!s3c_freq->hclk) {
467                                 pr_debug("cpufreq: %dkHz unsupported as it would need unavailable dvs mode\n",
468                                          freq->frequency);
469                                 freq->frequency = CPUFREQ_ENTRY_INVALID;
470                         } else {
471                                 freq++;
472                                 continue;
473                         }
474                 }
475
476                 /* Check for frequencies we can generate */
477                 rate = clk_round_rate(s3c_freq->armdiv,
478                                       freq->frequency * 1000);
479                 rate /= 1000;
480                 if (rate != freq->frequency) {
481                         pr_debug("cpufreq: %dkHz unsupported by clock (clk_round_rate return %lu)\n",
482                                  freq->frequency, rate);
483                         freq->frequency = CPUFREQ_ENTRY_INVALID;
484                 }
485
486                 freq++;
487         }
488
489         policy->cur = clk_get_rate(s3c_freq->armclk) / 1000;
490
491         /* Datasheet says PLL stabalisation time must be at least 300us,
492          * so but add some fudge. (reference in LOCKCON0 register description)
493          */
494         policy->cpuinfo.transition_latency = (500 * 1000) +
495                                              s3c_freq->regulator_latency;
496
497         ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table);
498         if (ret)
499                 goto err_freq_table;
500
501         cpufreq_frequency_table_get_attr(s3c_freq->freq_table, 0);
502
503         register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier);
504
505         return 0;
506
507 err_freq_table:
508 #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
509         regulator_put(s3c_freq->vddarm);
510 err_vddarm:
511 #endif
512         clk_put(s3c_freq->armclk);
513 err_armclk:
514         clk_put(s3c_freq->hclk);
515 err_hclk:
516         clk_put(s3c_freq->armdiv);
517
518         return ret;
519 }
520
521 static struct freq_attr *s3c2416_cpufreq_attr[] = {
522         &cpufreq_freq_attr_scaling_available_freqs,
523         NULL,
524 };
525
526 static struct cpufreq_driver s3c2416_cpufreq_driver = {
527         .owner          = THIS_MODULE,
528         .flags          = 0,
529         .verify         = s3c2416_cpufreq_verify_speed,
530         .target         = s3c2416_cpufreq_set_target,
531         .get            = s3c2416_cpufreq_get_speed,
532         .init           = s3c2416_cpufreq_driver_init,
533         .name           = "s3c2416",
534         .attr           = s3c2416_cpufreq_attr,
535 };
536
537 static int __init s3c2416_cpufreq_init(void)
538 {
539         return cpufreq_register_driver(&s3c2416_cpufreq_driver);
540 }
541 module_init(s3c2416_cpufreq_init);