f789128ba6ec2b6faaf7d396790ddc9fa35d7c82
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk29 / cpufreq.c
1 /* arch/arm/mach-rk2818/cpufreq.c
2  *
3  * Copyright (C) 2010 ROCKCHIP, Inc.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #ifdef CONFIG_CPU_FREQ_DEBUG
17 #define DEBUG
18 #endif
19 #define pr_fmt(fmt) "%s: " fmt, __func__
20
21 #include <linux/clk.h>
22 #include <linux/cpufreq.h>
23 #include <linux/err.h>
24 #include <linux/init.h>
25 #include <linux/regulator/consumer.h>
26 #include <linux/suspend.h>
27 #include <mach/cpufreq.h>
28
29 #define dprintk(fmt, ...) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
30
31 #define SLEEP_FREQ      (800 * 1000) /* Use 800MHz when entering sleep */
32
33 static int no_cpufreq_access;
34
35 static struct cpufreq_frequency_table default_freq_table[] = {
36 //      { .index = 1100000, .frequency =   24000 },
37 //      { .index = 1200000, .frequency =  204000 },
38 //      { .index = 1200000, .frequency =  300000 },
39         { .index = 1200000, .frequency =  408000 },
40 //      { .index = 1200000, .frequency =  600000 },
41         { .index = 1200000, .frequency =  816000 }, /* must enable, see SLEEP_FREQ above */
42 //      { .index = 1250000, .frequency = 1008000 },
43 //      { .index = 1300000, .frequency = 1104000 },
44 //      { .index = 1400000, .frequency = 1176000 },
45 //      { .index = 1400000, .frequency = 1200000 },
46         { .frequency = CPUFREQ_TABLE_END },
47 };
48 static struct cpufreq_frequency_table *freq_table = default_freq_table;
49 static struct clk *arm_clk;
50 static struct regulator *vcore;
51 static int vcore_uV;
52
53 int board_update_cpufreq_table(struct cpufreq_frequency_table *table)
54 {
55         freq_table = table;
56         return 0;
57 }
58
59 static int rk29_cpufreq_verify(struct cpufreq_policy *policy)
60 {
61         return cpufreq_frequency_table_verify(policy, freq_table);
62 }
63
64 static int rk29_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)
65 {
66         int index;
67         struct cpufreq_freqs freqs;
68         const struct cpufreq_frequency_table *freq;
69         int err = 0;
70
71         if (policy->cpu != 0)
72                 return -EINVAL;
73
74         if ((relation & ENABLE_FURTHER_CPUFREQ) &&
75             (relation & DISABLE_FURTHER_CPUFREQ)) {
76                 /* Invalidate both if both marked */
77                 relation &= ~ENABLE_FURTHER_CPUFREQ;
78                 relation &= ~DISABLE_FURTHER_CPUFREQ;
79                 pr_err("denied marking FURTHER_CPUFREQ as both marked.\n");
80         }
81         if (relation & ENABLE_FURTHER_CPUFREQ)
82                 no_cpufreq_access--;
83         if (no_cpufreq_access) {
84 #ifdef CONFIG_PM_VERBOSE
85                 pr_err("denied access to %s as it is disabled temporarily\n", __func__);
86 #endif
87                 return -EINVAL;
88         }
89         if (relation & DISABLE_FURTHER_CPUFREQ)
90                 no_cpufreq_access++;
91         relation &= ~MASK_FURTHER_CPUFREQ;
92
93         if (cpufreq_frequency_table_target(policy, freq_table, target_freq, relation, &index)) {
94                 pr_err("invalid target_freq: %d\n", target_freq);
95                 return -EINVAL;
96         }
97         freq = &freq_table[index];
98
99         if (policy->cur == freq->frequency)
100                 return 0;
101
102         freqs.old = policy->cur;
103         freqs.new = freq->frequency;
104         freqs.cpu = 0;
105         dprintk("%dHz r %d(%c) selected %dHz (%duV)\n",
106                 target_freq, relation, relation == CPUFREQ_RELATION_L ? 'L' : 'H',
107                 freq->frequency, freq->index);
108
109 #ifdef CONFIG_REGULATOR
110         if (vcore && freqs.new > freqs.old && vcore_uV != freq->index) {
111                 err = regulator_set_voltage(vcore, freq->index, freq->index);
112                 if (err) {
113                         pr_err("fail to set vcore (%duV) for %dkHz: %d\n",
114                                 freq->index, freqs.new, err);
115                         goto err_vol;
116                 }
117                 vcore_uV = freq->index;
118         }
119 #endif
120
121         cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
122         dprintk("pre change\n");
123         clk_set_rate(arm_clk, freqs.new * 1000);
124         dprintk("post change\n");
125         freqs.new = clk_get_rate(arm_clk) / 1000;
126         cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
127
128 #ifdef CONFIG_REGULATOR
129         if (vcore && freqs.new < freqs.old && vcore_uV != freq->index) {
130                 err = regulator_set_voltage(vcore, freq->index, freq->index);
131                 if (err) {
132                         pr_err("fail to set vcore (%duV) for %dkHz: %d\n",
133                                 freq->index, freqs.new, err);
134                 }
135                 vcore_uV = freq->index;
136         }
137 #endif
138         dprintk("ok, got %dkHz\n", freqs.new);
139
140 err_vol:
141         return err;
142 }
143
144 static int __init rk29_cpufreq_init(struct cpufreq_policy *policy)
145 {
146         arm_clk = clk_get(NULL, "arm_pll");
147         if (IS_ERR(arm_clk))
148                 return PTR_ERR(arm_clk);
149
150         if (policy->cpu != 0)
151                 return -EINVAL;
152
153 #ifdef CONFIG_REGULATOR
154         vcore = regulator_get(NULL, "vcore");
155         if (IS_ERR(vcore)) {
156                 pr_err("fail to get regulator vcore: %ld\n", PTR_ERR(vcore));
157                 vcore = NULL;
158         }
159 #endif
160
161         BUG_ON(cpufreq_frequency_table_cpuinfo(policy, freq_table));
162         cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
163         policy->cur = clk_get_rate(arm_clk) / 1000;
164
165         policy->cpuinfo.transition_latency = 400 * NSEC_PER_USEC; // make default sampling_rate to 40000
166
167         return 0;
168 }
169
170 static int rk29_cpufreq_exit(struct cpufreq_policy *policy)
171 {
172         if (vcore)
173                 regulator_put(vcore);
174         clk_put(arm_clk);
175         return 0;
176 }
177
178 static struct freq_attr *rk29_cpufreq_attr[] = {
179         &cpufreq_freq_attr_scaling_available_freqs,
180         NULL,
181 };
182
183 static struct cpufreq_driver rk29_cpufreq_driver = {
184         .flags          = CPUFREQ_STICKY,
185         .init           = rk29_cpufreq_init,
186         .exit           = rk29_cpufreq_exit,
187         .verify         = rk29_cpufreq_verify,
188         .target         = rk29_cpufreq_target,
189         .name           = "rk29",
190         .attr           = rk29_cpufreq_attr,
191 };
192
193 static int rk29_cpufreq_pm_notifier_event(struct notifier_block *this,
194                 unsigned long event, void *ptr)
195 {
196         int ret;
197
198         switch (event) {
199         case PM_SUSPEND_PREPARE:
200                 ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
201                                 DISABLE_FURTHER_CPUFREQ);
202                 if (ret < 0)
203                         return NOTIFY_BAD;
204                 return NOTIFY_OK;
205         case PM_POST_RESTORE:
206         case PM_POST_SUSPEND:
207                 cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
208                                 ENABLE_FURTHER_CPUFREQ);
209                 return NOTIFY_OK;
210         }
211         return NOTIFY_DONE;
212 }
213
214 static struct notifier_block rk29_cpufreq_pm_notifier = {
215         .notifier_call = rk29_cpufreq_pm_notifier_event,
216 };
217
218 static int __init rk29_cpufreq_register(void)
219 {
220         register_pm_notifier(&rk29_cpufreq_pm_notifier);
221
222         return cpufreq_register_driver(&rk29_cpufreq_driver);
223 }
224
225 device_initcall(rk29_cpufreq_register);
226