7551abd357d1e1591f39421a432a272053298786
[pandora-kernel.git] / drivers / misc / omap_overclocking.c
1 /*
2  * OMAP CPU overclocking hacks
3  *
4  * Licensed under the GPL-2 or later.
5  */
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/proc_fs.h>
9 #include <linux/opp.h>
10 #include <linux/clk.h>
11 #include <linux/uaccess.h>
12
13 #include <plat/omap_device.h>
14
15 #define PROC_DIR        "pandora"
16 #define PROC_CPUMHZ     "pandora/cpu_mhz_max"
17 #define PROC_CPUOPP     "pandora/cpu_opp_max"
18 #define PROC_SYSMHZ     "pandora/sys_mhz_max"
19
20 /* FIXME: could use opp3xxx_data.c, but that's initdata.. */
21 static const unsigned long nominal_freqs_35xx[] = {
22         125000000, 250000000, 500000000, 550000000, 600000000,
23 };
24
25 static const unsigned long nominal_freqs_36xx[] = {
26         300000000, 600000000, 800000000, 1000000000,
27 };
28
29 static const unsigned long *nominal_freqs;
30
31 static int opp_max_avail, opp_max_now, opp_max_ceil;
32
33 static int set_opp_max(int new_opp_max)
34 {
35         struct device *mpu_dev;
36         int i, ret;
37
38         if (new_opp_max == opp_max_now)
39                 return 0;
40
41         mpu_dev = omap_device_get_by_hwmod_name("mpu");
42         if (IS_ERR(mpu_dev)) {
43                 pr_err("%s: mpu device not available (%ld)\n",
44                         __func__, PTR_ERR(mpu_dev));
45                 return -ENODEV;
46         }
47
48         for (i = 1; i < new_opp_max; i++) {
49                 ret = opp_enable_i(mpu_dev, i);
50                 if (ret != 0)
51                         dev_err(mpu_dev, "%s: opp_enable returned %d\n",
52                                 __func__, ret);
53         }
54
55         for (i = new_opp_max; i < opp_max_avail; i++) {
56                 ret = opp_disable_i(mpu_dev, i);
57                 if (ret != 0)
58                         dev_err(mpu_dev, "%s: opp_disable returned %d\n",
59                                 __func__, ret);
60         }
61
62         dev_info(mpu_dev, "max OPP set to %d\n", new_opp_max);
63         opp_max_now = new_opp_max;
64
65         return 0;
66 }
67
68 static int set_opp_max_ceil(int new_opp_max)
69 {
70         opp_max_ceil = new_opp_max;
71         return set_opp_max(new_opp_max);
72 }
73
74 static int set_cpu_mhz_max(unsigned long new_mhz_max)
75 {
76         unsigned long cur_mhz_max = 0;
77         struct device *mpu_dev;
78         int index, ret;
79
80         new_mhz_max *= 1000000;
81
82         if (opp_max_ceil < 1 || opp_max_ceil > opp_max_avail) {
83                 pr_err("%s: corrupt opp_max_ceil: %d\n",
84                         __func__, opp_max_ceil);
85                 return -EINVAL;
86         }
87         index = opp_max_ceil - 1;
88
89         /* find the minimum opp needed for this clock
90          * and make it max allowed for cpufreq */
91         while (index > 0 && new_mhz_max <= nominal_freqs[index - 1])
92                 index--;
93         set_opp_max(index + 1);
94
95         mpu_dev = omap_device_get_by_hwmod_name("mpu");
96         if (IS_ERR(mpu_dev)) {
97                 pr_err("%s: mpu device not available (%ld)\n",
98                         __func__, PTR_ERR(mpu_dev));
99                 return -ENODEV;
100         }
101
102         opp_hack_get_freq(mpu_dev, index, &cur_mhz_max);
103         if (cur_mhz_max == new_mhz_max)
104                 return 0;
105
106         ret = opp_hack_set_freq(mpu_dev, index, new_mhz_max);
107         if (ret != 0) {
108                 dev_err(mpu_dev, "%s: opp_hack_set_freq returned %d\n",
109                         __func__, ret);
110                 return ret;
111         }
112
113         return 0;
114 }
115
116 static int get_cpu_mhz_max(void)
117 {
118         unsigned long cur_mhz_max = 0;
119         struct device *mpu_dev;
120
121         if (opp_max_now < 1 || opp_max_now > opp_max_avail) {
122                 pr_err("%s: corrupt opp_max: %d\n", __func__, opp_max_now);
123                 return -EINVAL;
124         }
125
126         mpu_dev = omap_device_get_by_hwmod_name("mpu");
127         if (IS_ERR(mpu_dev)) {
128                 pr_err("%s: mpu device not available (%ld)\n",
129                         __func__, PTR_ERR(mpu_dev));
130                 return -ENODEV;
131         }
132
133         opp_hack_get_freq(mpu_dev, opp_max_now - 1, &cur_mhz_max);
134
135         return cur_mhz_max / 1000000;
136 }
137
138 static int init_opp_hacks(void)
139 {
140         struct device *mpu_dev;
141
142         mpu_dev = omap_device_get_by_hwmod_name("mpu");
143         if (IS_ERR(mpu_dev)) {
144                 pr_err("%s: mpu device not available (%ld)\n",
145                         __func__, PTR_ERR(mpu_dev));
146                 return -ENODEV;
147         }
148
149         if (cpu_is_omap3630()) {
150                 nominal_freqs = nominal_freqs_36xx;
151                 opp_max_avail = sizeof(nominal_freqs_36xx) / sizeof(nominal_freqs_36xx[0]);
152                 opp_max_ceil = 2;
153         } else if (cpu_is_omap34xx()) {
154                 nominal_freqs = nominal_freqs_35xx;
155                 opp_max_avail = sizeof(nominal_freqs_35xx) / sizeof(nominal_freqs_35xx[0]);
156                 opp_max_ceil = opp_max_avail;
157         } else {
158                 dev_err(mpu_dev, "%s: unsupported CPU\n", __func__);
159                 return -ENODEV;
160         }
161         opp_max_now = opp_max_ceil;
162
163         return 0;
164 }
165
166 static int set_sys_mhz_max(unsigned long rate)
167 {
168         struct clk *dpll3_m2_ck;
169         int ret;
170
171         rate *= 1000000;
172
173         dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
174         if (IS_ERR(dpll3_m2_ck)) {
175                 pr_err("%s: dpll3_m2_clk not available: %ld\n",
176                         __func__, PTR_ERR(dpll3_m2_ck));
177                 return -ENODEV;
178         }
179
180         pr_info("Reprogramming CORE clock to %luHz\n", rate);
181         ret = clk_set_rate(dpll3_m2_ck, rate);
182         if (ret)
183                 pr_err("dpll3_m2_clk rate change failed: %d\n", ret);
184
185         clk_put(dpll3_m2_ck);
186
187         return ret;
188 }
189
190 static int get_sys_mhz_max(void)
191 {
192         struct clk *dpll3_m2_ck;
193         int ret;
194
195         dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
196         if (IS_ERR(dpll3_m2_ck)) {
197                 pr_err("%s: dpll3_m2_clk not available: %ld\n",
198                         __func__, PTR_ERR(dpll3_m2_ck));
199                 return -ENODEV;
200         }
201
202         ret = clk_get_rate(dpll3_m2_ck);
203         clk_put(dpll3_m2_ck);
204
205         return ret / 1000000;
206 }
207
208 static int proc_read_val(char *page, char **start, off_t off, int count,
209                 int *eof, int val)
210 {
211         char *p = page;
212         int len;
213
214         p += sprintf(p, "%d\n", val);
215
216         len = (p - page) - off;
217         if (len < 0)
218                 len = 0;
219
220         *eof = (len <= count) ? 1 : 0;
221         *start = page + off;
222
223         return len;
224 }
225
226 static int proc_write_val(struct file *file, const char __user *buffer,
227                 unsigned long count, unsigned long *val)
228 {
229         char buff[32];
230         int ret;
231
232         count = strncpy_from_user(buff, buffer,
233                         count < sizeof(buff) ? count : sizeof(buff) - 1);
234         buff[count] = 0;
235
236         ret = strict_strtoul(buff, 0, val);
237         if (ret < 0) {
238                 pr_err("error %i parsing %s\n", ret, buff);
239                 return ret;
240         }
241
242         return count;
243 }
244
245 static int cpu_clk_read(char *page, char **start, off_t off, int count,
246                 int *eof, void *data)
247 {
248         return proc_read_val(page, start, off, count, eof, get_cpu_mhz_max());
249 }
250
251 static int cpu_clk_write(struct file *file, const char __user *buffer,
252                 unsigned long count, void *data)
253 {
254         unsigned long val;
255         int ret, retval;
256
257         retval = proc_write_val(file, buffer, count, &val);
258         if (retval < 0)
259                 return retval;
260
261         ret = set_cpu_mhz_max(val);
262         if (ret < 0)
263                 return ret;
264
265         return retval;
266 }
267
268 static int cpu_maxopp_read(char *page, char **start, off_t off, int count,
269                 int *eof, void *data)
270 {
271         return proc_read_val(page, start, off, count, eof, opp_max_ceil);
272 }
273
274 static int cpu_maxopp_write(struct file *file, const char __user *buffer,
275                 unsigned long count, void *data)
276 {
277         unsigned long val;
278         int ret, retval;
279
280         retval = proc_write_val(file, buffer, count, &val);
281         if (retval < 0)
282                 return retval;
283
284         if (val > opp_max_avail)
285                 val = opp_max_avail;
286
287         if (val < 1)
288                 return -EINVAL;
289
290         ret = set_opp_max_ceil(val);
291         if (ret != 0)
292                 return ret;
293
294         return retval;
295 }
296
297 static int sys_clk_read(char *page, char **start, off_t off, int count,
298                 int *eof, void *data)
299 {
300         return proc_read_val(page, start, off, count, eof, get_sys_mhz_max());
301 }
302
303 static int sys_clk_write(struct file *file, const char __user *buffer,
304                 unsigned long count, void *data)
305 {
306         unsigned long val;
307         int ret, retval;
308
309         retval = proc_write_val(file, buffer, count, &val);
310         if (retval < 0)
311                 return retval;
312
313         ret = set_sys_mhz_max(val);
314         if (ret < 0)
315                 return ret;
316
317         return retval;
318 }
319
320 static void proc_create_rw(const char *name, void *pdata,
321                            read_proc_t *read_proc, write_proc_t *write_proc)
322 {
323         struct proc_dir_entry *pret;
324
325         pret = create_proc_entry(name, S_IWUSR | S_IRUGO, NULL);
326         if (pret == NULL) {
327                 proc_mkdir(PROC_DIR, NULL);
328                 pret = create_proc_entry(name, S_IWUSR | S_IRUGO, NULL);
329                 if (pret == NULL) {
330                         pr_err("%s: failed to create proc file %s\n",
331                                 __func__, name);
332                         return;
333                 }
334         }
335
336         pret->data = pdata;
337         pret->read_proc = read_proc;
338         pret->write_proc = write_proc;
339 }
340
341 static int pndctrl_init(void)
342 {
343         int ret;
344
345         ret = init_opp_hacks();
346         if (ret != 0) {
347                 pr_err("init_opp_hacks failed: %d\n", ret);
348                 return -EFAULT;
349         }
350
351         proc_create_rw(PROC_CPUMHZ, NULL, cpu_clk_read, cpu_clk_write);
352         proc_create_rw(PROC_CPUOPP, NULL, cpu_maxopp_read, cpu_maxopp_write);
353         proc_create_rw(PROC_SYSMHZ, NULL, sys_clk_read, sys_clk_write);
354
355         pr_info("OMAP overclocker loaded.\n");
356         return 0;
357 }
358
359
360 static void pndctrl_cleanup(void)
361 {
362         remove_proc_entry(PROC_CPUOPP, NULL);
363         remove_proc_entry(PROC_CPUMHZ, NULL);
364         remove_proc_entry(PROC_SYSMHZ, NULL);
365 }
366
367 module_init(pndctrl_init);
368 module_exit(pndctrl_cleanup);
369
370 MODULE_AUTHOR("GraÅžvydas Ignotas");
371 MODULE_LICENSE("GPL");
372 MODULE_DESCRIPTION("OMAP overclocking support");