import PULS_20180308
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / freqhopping / mt_freqhopping_drv.c
1 /*
2 * Copyright (C) 2011 MediaTek, Inc.
3 *
4 * Author: Holmes Chiou <holmes.chiou@mediatek.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/sched.h>
19 #include <linux/kthread.h>
20 #include <linux/delay.h>
21 #include <linux/uaccess.h>
22 #include <linux/io.h>
23 #include <linux/platform_device.h>
24 #include <linux/miscdevice.h>
25 //#include <asm/sched_clock.h>
26 #include <linux/vmalloc.h>
27 #include <linux/dma-mapping.h>
28 #include <board-custom.h>
29 #include <linux/seq_file.h>
30
31 #include "mach/mt_fhreg.h"
32
33 #include <linux/xlog.h> //ccyeh: for 6572
34
35 #if 0 //ccyeh: we don't need these header files here.
36 #include "mach/mt_clkmgr.h"
37 #include "mach/mt_typedefs.h"
38 #include "mach/mt_gpio.h"
39 #include "mach/mt_gpufreq.h"
40 #include "mach/mt_cpufreq.h"
41 #include "mach/emi_bwl.h"
42 #include "mach/sync_write.h"
43 #include "mach/mt_sleep.h"
44 #endif
45
46 #include <mach/mt_freqhopping_drv.h>
47
48
49 #define FREQ_HOPPING_DEVICE "mt-freqhopping"
50
51 #define FH_PLL_COUNT (g_p_fh_hal_drv->pll_cnt)
52
53 //static unsigned int g_resume_mempll_ssc=false;
54 static struct mt_fh_hal_driver *g_p_fh_hal_drv;
55
56 static fh_pll_t *g_fh_drv_pll;
57 static struct freqhopping_ssc *g_fh_drv_usr_def;
58 static unsigned int g_drv_pll_count;
59
60 static struct miscdevice mt_fh_device = {
61 .minor = MISC_DYNAMIC_MINOR,
62 .name = "mtfreqhopping",
63 //.fops = &mt_fh_fops, //TODO: Interface for UI maybe in the future...
64 };
65
66
67 static int mt_freqhopping_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
68
69 static int mt_fh_drv_probe(struct platform_device *dev)
70 {
71 int err = 0;
72
73 FH_MSG("EN: mt_fh_probe()");
74
75 if ((err = misc_register(&mt_fh_device)))
76 FH_MSG("register fh driver error!");
77
78 return err;
79 }
80
81 static int mt_fh_drv_remove(struct platform_device *dev)
82 {
83 int err = 0;
84
85 if ((err = misc_deregister(&mt_fh_device)))
86 FH_MSG("deregister fh driver error!");
87
88 return err;
89 }
90
91 static void mt_fh_drv_shutdown(struct platform_device *dev)
92 {
93 FH_MSG("mt_fh_shutdown");
94 }
95
96 static int mt_fh_drv_suspend(struct platform_device *dev, pm_message_t state)
97 {
98 // struct freqhopping_ioctl fh_ctl;
99
100 FH_MSG("-supd-");
101
102 return 0;
103 }
104
105 static int mt_fh_drv_resume(struct platform_device *dev)
106 {
107 // struct freqhopping_ioctl fh_ctl;
108
109 FH_MSG("+resm+");
110
111 return 0;
112 }
113
114 static struct platform_driver freqhopping_driver = {
115 .probe = mt_fh_drv_probe,
116 .remove = mt_fh_drv_remove,
117 .shutdown = mt_fh_drv_shutdown,
118 .suspend = mt_fh_drv_suspend,
119 .resume = mt_fh_drv_resume,
120 .driver = {
121 .name = FREQ_HOPPING_DEVICE,
122 .owner = THIS_MODULE,
123 },
124 };
125
126 static int mt_fh_enable_usrdef(struct freqhopping_ioctl* fh_ctl)
127 {
128 unsigned long flags = 0;
129 const unsigned int pll_id = fh_ctl->pll_id;
130
131 FH_MSG("EN: %s",__func__);
132 FH_MSG("pll_id: %d",fh_ctl->pll_id);
133
134 if (fh_ctl->pll_id < FH_PLL_COUNT){
135 //we don't care the PLL status , we just change the flag & update the table
136 //the setting will be applied during the following FH enable
137
138 g_p_fh_hal_drv->mt_fh_lock(&flags);
139 memcpy(&g_fh_drv_usr_def[pll_id],&(fh_ctl->ssc_setting),sizeof(g_fh_drv_usr_def[pll_id]));
140 g_fh_drv_pll[pll_id].user_defined = true;
141 g_p_fh_hal_drv->mt_fh_unlock(&flags);
142 }
143
144 //FH_MSG("Exit");
145
146 return 0;
147
148 }
149
150 static int mt_fh_disable_usrdef(struct freqhopping_ioctl* fh_ctl)
151 {
152 unsigned long flags = 0;
153 const unsigned int pll_id = fh_ctl->pll_id;
154
155 FH_MSG("EN: %s",__func__);
156 FH_MSG("id: %d",fh_ctl->pll_id);
157
158 if (fh_ctl->pll_id < FH_PLL_COUNT){
159 g_p_fh_hal_drv->mt_fh_lock(&flags);
160 memset(&g_fh_drv_usr_def[pll_id], 0,sizeof(g_fh_drv_usr_def[pll_id]));
161 g_fh_drv_pll[pll_id].user_defined = false;
162 g_p_fh_hal_drv->mt_fh_unlock(&flags);
163 }
164
165 //FH_MSG("Exit");
166
167 return 0;
168 }
169
170 static int mt_fh_hal_ctrl_lock(struct freqhopping_ioctl* fh_ctl,bool enable)
171 {
172 int retVal=1;
173 unsigned long flags = 0;
174
175 FH_MSG("EN: _fctr_lck %d:%d",fh_ctl->pll_id,enable);
176
177 g_p_fh_hal_drv->mt_fh_lock(&flags);
178 retVal = g_p_fh_hal_drv->mt_fh_hal_ctrl(fh_ctl, enable);
179 g_p_fh_hal_drv->mt_fh_unlock(&flags);
180
181 return retVal;
182 }
183
184
185 static int mt_freqhopping_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
186 {
187 //Get the structure of ioctl
188 int ret = 0;
189
190 struct freqhopping_ioctl *freqhopping_ctl = (struct freqhopping_ioctl *)arg;
191
192 FH_MSG("EN:CMD:%d pll id:%d",cmd,freqhopping_ctl->pll_id);
193
194 if(FH_CMD_ENABLE == cmd) {
195 ret = mt_fh_hal_ctrl_lock(freqhopping_ctl,true);
196 }else if(FH_CMD_DISABLE == cmd) {
197 ret = mt_fh_hal_ctrl_lock(freqhopping_ctl,false);
198 }
199 else if(FH_CMD_ENABLE_USR_DEFINED == cmd) {
200 ret = mt_fh_enable_usrdef(freqhopping_ctl);
201 }
202 else if(FH_CMD_DISABLE_USR_DEFINED == cmd) {
203 ret = mt_fh_disable_usrdef(freqhopping_ctl);
204 }else {
205 //Invalid command is not acceptable!!
206 WARN_ON(1);
207 }
208
209 //FH_MSG("Exit");
210
211 return ret;
212 }
213
214 //static int freqhopping_userdefine_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
215 static int freqhopping_userdefine_proc_read(struct seq_file* m, void* v)
216 {
217 int i=0;
218
219 FH_MSG("EN: %s",__func__);
220
221 seq_printf(m, "user defined settings:\n");
222
223 seq_printf(m, "===============================================\r\n" );
224 seq_printf(m, " freq == delta t == delta f == up bond == low bond == dds ==\r\n" );
225
226 for(i = 0;i < g_drv_pll_count ; ++i) {
227 seq_printf(m, "%10d 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\r\n"
228 ,g_fh_drv_usr_def[i].freq
229 ,g_fh_drv_usr_def[i].dt
230 ,g_fh_drv_usr_def[i].df
231 ,g_fh_drv_usr_def[i].upbnd
232 ,g_fh_drv_usr_def[i].lowbnd
233 ,g_fh_drv_usr_def[i].dds);
234 }
235
236 return 0;
237
238 #if 0
239 char *p = page;
240 int len = 0;
241 int i=0;
242
243 FH_MSG("EN: %s",__func__);
244
245 p += sprintf(p, "user defined settings:\n");
246
247 p += sprintf(p, "===============================================\r\n" );
248 p += sprintf(p, " freq == delta t == delta f == up bond == low bond == dds ==\r\n" );
249
250 for(i=0;i<g_drv_pll_count ;i++) {
251 p += sprintf(p, "%10d 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\r\n"
252 ,g_fh_drv_usr_def[i].freq
253 ,g_fh_drv_usr_def[i].dt
254 ,g_fh_drv_usr_def[i].df
255 ,g_fh_drv_usr_def[i].upbnd
256 ,g_fh_drv_usr_def[i].lowbnd
257 ,g_fh_drv_usr_def[i].dds);
258 }
259
260 *start = page + off;
261
262 len = p - page;
263
264 if (len > off)
265 len -= off;
266 else
267 len = 0;
268
269 return len < count ? len : count;
270 #endif
271 }
272
273 static ssize_t freqhopping_userdefine_proc_write(struct file *file, const char *buffer, size_t count, loff_t *data)
274 {
275 int ret;
276 char kbuf[256];
277 size_t len = 0;
278 unsigned int p1,p2,p3,p4,p5,p6,p7;
279 struct freqhopping_ioctl fh_ctl;
280
281 p1 = p2 = p3 = p4 = p5 = p6 = p7 = 0;
282
283 FH_MSG("EN: %s",__func__);
284
285 len = min(count, (sizeof(kbuf)-1));
286
287 if (count == 0)return -1;
288 if(count > 255)count = 255;
289
290 ret = copy_from_user(kbuf, buffer, count);
291 if (ret < 0)return -1;
292
293 kbuf[count] = '\0';
294
295 sscanf(kbuf, "%x %x %x %x %x %x %x", &p1, &p2, &p3, &p4, &p5, &p6, &p7);
296
297 fh_ctl.pll_id = p2;
298 fh_ctl.ssc_setting.df = p3;
299 fh_ctl.ssc_setting.dt = p4;
300 fh_ctl.ssc_setting.upbnd = p5;
301 fh_ctl.ssc_setting.lowbnd = p6;
302 fh_ctl.ssc_setting.dds = p7;
303 fh_ctl.ssc_setting.freq = 0;
304
305 /* Check validity of PLL ID */
306 if (fh_ctl.pll_id >= FH_PLL_COUNT)
307 return -1;
308
309
310 if( p1 == FH_CMD_ENABLE){
311 ret = mt_fh_enable_usrdef(&fh_ctl);
312 if(ret){
313 FH_MSG("__EnableUsrSetting() fail!");
314 }
315 }
316 else{
317 ret = mt_fh_disable_usrdef(&fh_ctl);
318 if(ret){
319 FH_MSG("__DisableUsrSetting() fail!");
320 }
321 }
322
323 FH_MSG("Exit: %s",__func__);
324 return count;
325 }
326
327 //static int freqhopping_status_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
328 static int freqhopping_status_proc_read(struct seq_file* m, void* v)
329 {
330 int i=0;
331
332 FH_MSG("EN: %s",__func__);
333
334 seq_printf(m, "FH status:\r\n");
335
336 seq_printf(m, "===============================================\r\n" );
337 seq_printf(m, "id == fh_status == pll_status == setting_id == curr_freq == user_defined ==\r\n" );
338
339
340 for(i = 0;i < g_drv_pll_count ; ++i) {
341 seq_printf(m, "%2d %8d %8d",
342 i,
343 g_fh_drv_pll[i].fh_status,
344 g_fh_drv_pll[i].pll_status);
345 seq_printf(m, " %8d %8d ",
346 g_fh_drv_pll[i].setting_id,
347 g_fh_drv_pll[i].curr_freq);
348
349 seq_printf(m, " %d\r\n",
350 g_fh_drv_pll[i].user_defined);
351 }
352 seq_printf(m, "\r\n");
353
354 return 0;
355
356 #if 0
357 char *p = page;
358 int len = 0;
359 int i=0;
360
361 FH_MSG("EN: %s",__func__);
362
363 p += sprintf(p, "FH status:\r\n");
364
365 p += sprintf(p, "===============================================\r\n" );
366 p += sprintf(p, "id == fh_status == pll_status == setting_id == curr_freq == user_defined ==\r\n" );
367
368
369 for(i=0;i<g_drv_pll_count ;i++) {
370 p += sprintf(p, "%2d %8d %8d",
371 i,
372 g_fh_drv_pll[i].fh_status,
373 g_fh_drv_pll[i].pll_status);
374 p += sprintf(p, " %8d %8d ",
375 g_fh_drv_pll[i].setting_id,
376 g_fh_drv_pll[i].curr_freq);
377
378 p += sprintf(p, " %d\r\n",
379 g_fh_drv_pll[i].user_defined);
380 }
381 #if 0
382 p += sprintf(p, "\r\nPLL status:\r\n");
383 for(i=0;i<g_drv_pll_count ;i++) {
384 p += sprintf(p, "%d ",pll_is_on(i));
385 }
386 #endif
387 p += sprintf(p, "\r\n");
388
389 //TODO: unsigned int mt_get_cpu_freq(void)
390
391
392 *start = page + off;
393
394 len = p - page;
395
396 if (len > off)
397 len -= off;
398 else
399 len = 0;
400
401 return len < count ? len : count;
402 #endif
403 }
404
405 static ssize_t freqhopping_status_proc_write(struct file *file, const char *buffer, size_t count, loff_t *data)
406 {
407 int ret;
408 char kbuf[256];
409 size_t len = 0;
410 unsigned int p1,p2,p3,p4,p5,p6;
411 struct freqhopping_ioctl fh_ctl;
412
413 p1 = p2 = p3 = p4 = p5 = p6 = 0;
414
415 FH_MSG("EN: %s",__func__);
416
417 len = min(count, (sizeof(kbuf)-1));
418
419 if (count == 0)return -1;
420 if(count > 255)count = 255;
421
422 ret = copy_from_user(kbuf, buffer, count);
423 if (ret < 0)return -1;
424
425 kbuf[count] = '\0';
426
427 sscanf(kbuf, "%x %x", &p1, &p2);
428
429 fh_ctl.pll_id = p2;
430 fh_ctl.ssc_setting.df= 0;
431 fh_ctl.ssc_setting.dt= 0;
432 fh_ctl.ssc_setting.upbnd= 0;
433 fh_ctl.ssc_setting.lowbnd= 0;
434
435 /* Check validity of PLL ID */
436 if (fh_ctl.pll_id >= FH_PLL_COUNT)
437 return -1;
438
439 if( p1 == 0){
440 mt_freqhopping_ioctl(NULL,FH_CMD_DISABLE,(unsigned long)(&fh_ctl));
441 }
442 else{
443 mt_freqhopping_ioctl(NULL,FH_CMD_ENABLE,(unsigned long)(&fh_ctl));
444 }
445
446 return count;
447 }
448
449 //static int freqhopping_debug_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
450 static int freqhopping_debug_proc_read(struct seq_file* m, void* v)
451 {
452 #if defined(PLATFORM_DEP_DEBUG_PROC_READ)
453 FH_IO_PROC_READ_T arg;
454 arg.m = m;
455 arg.v = v;
456 arg.pll = g_fh_drv_pll;
457 //g_p_fh_hal_drv->ioctl(FH_IO_PROC_READ, &arg);
458 return 0;
459 #else
460 FH_MSG("EN: %s",__func__);
461
462 seq_printf(m, "\r\n[freqhopping debug flag]\r\n");
463 seq_printf(m, "===============================================\r\n" );
464 seq_printf(m, "id==ARMPLL==MAINPLL==MEMPLL==MSDCPLL==MMPLL==VENCPLL\r\n" );
465 seq_printf(m, " == %04d====%04d====%04d====%04d====%04d====%04d=\r\n" ,
466 g_fh_drv_pll[MT658X_FH_ARM_PLL].fh_status, g_fh_drv_pll[MT658X_FH_MAIN_PLL].fh_status,
467 g_fh_drv_pll[MT658X_FH_MEM_PLL].fh_status, g_fh_drv_pll[MT658X_FH_MSDC_PLL].fh_status,
468 g_fh_drv_pll[MT658X_FH_MM_PLL].fh_status, g_fh_drv_pll[MT658X_FH_VENC_PLL].fh_status);
469 seq_printf(m, " == %04d====%04d====%04d====%04d====%04d====%04d=\r\n" ,
470 g_fh_drv_pll[MT658X_FH_ARM_PLL].setting_id, g_fh_drv_pll[MT658X_FH_MAIN_PLL].setting_id,
471 g_fh_drv_pll[MT658X_FH_MEM_PLL].setting_id, g_fh_drv_pll[MT658X_FH_MSDC_PLL].setting_id,
472 g_fh_drv_pll[MT658X_FH_MM_PLL].setting_id, g_fh_drv_pll[MT658X_FH_VENC_PLL].setting_id);
473 return 0;
474 #if 0
475 char *p = page;
476 int len = 0;
477
478 FH_MSG("EN: %s",__func__);
479
480 p += sprintf(p, "\r\n[freqhopping debug flag]\r\n");
481 p += sprintf(p, "===============================================\r\n" );
482 p += sprintf(p, "id==ARMPLL==MAINPLL==MEMPLL==MSDCPLL==MMPLL==VENCPLL\r\n" );
483 p += sprintf(p, " == %04d====%04d====%04d====%04d====%04d====%04d=\r\n" ,
484 g_fh_drv_pll[MT658X_FH_ARM_PLL].fh_status, g_fh_drv_pll[MT658X_FH_MAIN_PLL].fh_status,
485 g_fh_drv_pll[MT658X_FH_MEM_PLL].fh_status, g_fh_drv_pll[MT658X_FH_MSDC_PLL].fh_status,
486 g_fh_drv_pll[MT658X_FH_MM_PLL].fh_status, g_fh_drv_pll[MT658X_FH_VENC_PLL].fh_status);
487 p += sprintf(p, " == %04d====%04d====%04d====%04d====%04d====%04d=\r\n" ,
488 g_fh_drv_pll[MT658X_FH_ARM_PLL].setting_id, g_fh_drv_pll[MT658X_FH_MAIN_PLL].setting_id,
489 g_fh_drv_pll[MT658X_FH_MEM_PLL].setting_id, g_fh_drv_pll[MT658X_FH_MSDC_PLL].setting_id,
490 g_fh_drv_pll[MT658X_FH_MM_PLL].setting_id, g_fh_drv_pll[MT658X_FH_VENC_PLL].setting_id);
491
492 *start = page + off;
493
494 len = p - page;
495
496 if (len > off)
497 len -= off;
498 else
499 len = 0;
500
501 return len < count ? len : count;
502 #endif
503 #endif
504 }
505
506 static ssize_t freqhopping_debug_proc_write(struct file *file, const char *buffer, size_t count, loff_t *data)
507 {
508 int ret;
509 char kbuf[256];
510 size_t len = 0;
511 unsigned int cmd,p1,p2,p3,p4,p5,p6,p7;
512 struct freqhopping_ioctl fh_ctl;
513
514 p1 = p2 = p3 = p4 = p5 = p6 = p7 = 0;
515
516 FH_MSG("EN: %s",__func__);
517
518 len = min(count, (sizeof(kbuf)-1));
519
520 if (count == 0)return -1;
521 if(count > 255)count = 255;
522
523 ret = copy_from_user(kbuf, buffer, count);
524 if (ret < 0)return -1;
525
526 kbuf[count] = '\0';
527
528 sscanf(kbuf, "%x %x %x %x %x %x %x %x", &cmd, &p1, &p2, &p3, &p4, &p5, &p6, &p7);
529
530 //ccyeh fh_ctl.opcode = p1;
531 fh_ctl.pll_id = p2;
532 //ccyeh removed fh_ctl.ssc_setting_id = p3;
533 fh_ctl.ssc_setting.dds = p3;
534 fh_ctl.ssc_setting.df = p4;
535 fh_ctl.ssc_setting.dt = p5;
536 fh_ctl.ssc_setting.upbnd = p6;
537 fh_ctl.ssc_setting.lowbnd = p7;
538 fh_ctl.ssc_setting.freq = 0;
539
540 /* Check validity of PLL ID */
541 if (fh_ctl.pll_id >= FH_PLL_COUNT)
542 return -1;
543
544
545 if (cmd < FH_CMD_INTERNAL_MAX_CMD) {
546 mt_freqhopping_ioctl(NULL,cmd,(unsigned long)(&fh_ctl));
547 }
548 else if((cmd > FH_DCTL_CMD_ID) && (cmd < FH_DCTL_CMD_MAX))
549 {
550 mt_freqhopping_devctl(cmd, &fh_ctl);
551 }
552 else {
553 FH_MSG("CMD error!");
554 }
555
556 return count;
557 }
558
559 static int freqhopping_debug_proc_open(struct inode *inode, struct file *file)
560 {
561 return single_open(file, freqhopping_debug_proc_read, NULL);
562 }
563
564 static int freqhopping_dramc_proc_open(struct inode *inode, struct file *file)
565 {
566 return single_open(file, g_p_fh_hal_drv->proc.dramc_read, NULL);
567 }
568 static ssize_t freqhopping_dramc_proc_write(struct file *file, const char *buffer, size_t count, loff_t *data)
569 {
570 return (ssize_t)(g_p_fh_hal_drv->proc.dramc_write(file, buffer, count, data));
571 }
572
573 static int freqhopping_dvfs_proc_open(struct inode *inode, struct file *file)
574 {
575 return single_open(file, g_p_fh_hal_drv->proc.dvfs_read, NULL);
576 }
577 static ssize_t freqhopping_dvfs_proc_write(struct file *file, const char *buffer, size_t count, loff_t *data)
578 {
579 return (ssize_t)(g_p_fh_hal_drv->proc.dvfs_write(file, buffer, count, data));
580 }
581
582 static int freqhopping_dumpregs_proc_open(struct inode *inode, struct file *file)
583 {
584 return single_open(file, g_p_fh_hal_drv->proc.dumpregs_read, NULL);
585 }
586
587 static int freqhopping_status_proc_open(struct inode *inode, struct file *file)
588 {
589 return single_open(file, freqhopping_status_proc_read, NULL);
590 }
591 static int freqhopping_userdefine_proc_open(struct inode *inode, struct file *file)
592 {
593 return single_open(file, freqhopping_userdefine_proc_read, NULL);
594 }
595
596 static const struct file_operations freqhopping_debug_fops = {
597 .owner = THIS_MODULE,
598 .open = freqhopping_debug_proc_open,
599 .read = seq_read,
600 .write = freqhopping_debug_proc_write,
601 };
602 static const struct file_operations dramc_fops = {
603 .owner = THIS_MODULE,
604 .open = freqhopping_dramc_proc_open,
605 .read = seq_read,
606 .write = freqhopping_dramc_proc_write,
607 };
608 static const struct file_operations dvfs_fops = {
609 .owner = THIS_MODULE,
610 .open = freqhopping_dvfs_proc_open,
611 .read = seq_read,
612 .write = freqhopping_dvfs_proc_write,
613 };
614 static const struct file_operations dumpregs_fops = {
615 .owner = THIS_MODULE,
616 .open = freqhopping_dumpregs_proc_open,
617 .read = seq_read,
618 };
619 static const struct file_operations status_fops = {
620 .owner = THIS_MODULE,
621 .open = freqhopping_status_proc_open,
622 .read = seq_read,
623 .write = freqhopping_status_proc_write,
624 };
625 static const struct file_operations userdef_fops = {
626 .owner = THIS_MODULE,
627 .open = freqhopping_userdefine_proc_open,
628 .read = seq_read,
629 .write = freqhopping_userdefine_proc_write,
630 };
631
632 static int freqhopping_debug_proc_init(void)
633 {
634 struct proc_dir_entry *prDebugEntry;
635 struct proc_dir_entry *prDramcEntry;
636 struct proc_dir_entry *prDumpregEntry;
637 struct proc_dir_entry *prStatusEntry;
638 struct proc_dir_entry *prUserdefEntry;
639 struct proc_dir_entry *fh_proc_dir = NULL;
640
641 //TODO: check the permission!!
642
643 FH_MSG("EN: %s",__func__);
644
645 fh_proc_dir = proc_mkdir("freqhopping", NULL);
646 if (!fh_proc_dir){
647 FH_MSG("proc_mkdir fail!");
648 return 1;
649 }
650 else{
651
652
653 /* /proc/freqhopping/freqhopping_debug */
654 //prDebugEntry = create_proc_entry("freqhopping_debug", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
655 prDebugEntry = proc_create("freqhopping_debug", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir, &freqhopping_debug_fops);
656 if(prDebugEntry)
657 {
658 //prDebugEntry->read_proc = freqhopping_debug_proc_read;
659 //prDebugEntry->write_proc = freqhopping_debug_proc_write;
660 FH_MSG("[%s]: successfully create /proc/freqhopping_debug", __func__);
661 }else{
662 FH_MSG("[%s]: failed to create /proc/freqhopping/freqhopping_debug", __func__);
663 return 1;
664 }
665
666
667 /* /proc/freqhopping/dramc */
668 //prDramcEntry = create_proc_entry("dramc", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
669 prDramcEntry = proc_create("dramc", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir, &dramc_fops);
670 if(prDramcEntry)
671 {
672 //prDramcEntry->read_proc = g_p_fh_hal_drv->proc.dramc_read;
673 //prDramcEntry->write_proc = g_p_fh_hal_drv->proc.dramc_write;
674 FH_MSG("[%s]: successfully create /proc/freqhopping/prDramcEntry", __func__);
675 }else{
676 FH_MSG("[%s]: failed to create /proc/freqhopping/prDramcEntry", __func__);
677 return 1;
678 }
679 /* /proc/freqhopping/dvfs */
680 //prDramcEntry = create_proc_entry("dvfs", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
681 prDramcEntry = proc_create("dvfs", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir, &dvfs_fops);
682 if(prDramcEntry)
683 {
684 //prDramcEntry->read_proc = g_p_fh_hal_drv->proc.dvfs_read;
685 //prDramcEntry->write_proc = g_p_fh_hal_drv->proc.dvfs_write;
686 FH_MSG("[%s]: successfully create /proc/freqhopping/dvfs", __func__);
687 }else{
688 FH_MSG("[%s]: failed to create /proc/freqhopping/dvfs", __func__);
689 return 1;
690 }
691
692
693 /* /proc/freqhopping/dumpregs */
694 //prDumpregEntry = create_proc_entry("dumpregs", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
695 prDumpregEntry = proc_create("dumpregs", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir, &dumpregs_fops);
696 if(prDumpregEntry)
697 {
698 //prDumpregEntry->read_proc = g_p_fh_hal_drv->proc.dumpregs_read;
699 //prDumpregEntry->write_proc = NULL;
700 FH_MSG("[%s]: successfully create /proc/freqhopping/dumpregs", __func__);
701 }else{
702 FH_MSG("[%s]: failed to create /proc/freqhopping/dumpregs", __func__);
703 return 1;
704 }
705
706
707 /* /proc/freqhopping/status */
708 //prStatusEntry = create_proc_entry("status", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
709 prStatusEntry = proc_create("status", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir, &status_fops);
710 if(prStatusEntry)
711 {
712 //prStatusEntry->read_proc = freqhopping_status_proc_read;
713 //prStatusEntry->write_proc = freqhopping_status_proc_write;
714 FH_MSG("[%s]: successfully create /proc/freqhopping/status", __func__);
715 }else{
716 FH_MSG("[%s]: failed to create /proc/freqhopping/status", __func__);
717 return 1;
718 }
719
720
721 /* /proc/freqhopping/userdefine */
722 //prUserdefEntry = create_proc_entry("userdef", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
723 prUserdefEntry = proc_create("userdef", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir, &userdef_fops);
724 if(prUserdefEntry)
725 {
726 //prUserdefEntry->read_proc = freqhopping_userdefine_proc_read;
727 //prUserdefEntry->write_proc = freqhopping_userdefine_proc_write;
728 FH_MSG("[%s]: successfully create /proc/freqhopping/userdef", __func__);
729 }else{
730 FH_MSG("[%s]: failed to create /proc/freqhopping/userdef", __func__);
731 return 1;
732 }
733
734 #if 0// MT_FH_CLK_GEN
735 /* /proc/freqhopping/clkgen */
736 prUserdefEntry = create_proc_entry("clkgen", S_IRUGO | S_IWUSR | S_IWGRP, fh_proc_dir);
737 if(prUserdefEntry)
738 {
739 prUserdefEntry->read_proc = g_p_fh_hal_drv->proc.clk_gen_read;
740 prUserdefEntry->write_proc = g_p_fh_hal_drv->proc.clk_gen_write;
741 FH_MSG("[%s]: successfully create /proc/freqhopping/clkgen", __func__);
742 }else{
743 FH_MSG("[%s]: failed to create /proc/freqhopping/clkgen", __func__);
744 return 1;
745 }
746 #endif //MT_FH_CLK_GEN
747 }
748
749 return 0 ;
750 }
751
752 #if defined(DISABLE_FREQ_HOPPING)
753 void mt_fh_popod_save(void){}
754 EXPORT_SYMBOL(mt_fh_popod_save);
755
756 void mt_fh_popod_restore(void){}
757 EXPORT_SYMBOL(mt_fh_popod_restore);
758
759 int freqhopping_config(unsigned int pll_id, unsigned long vco_freq, unsigned int enable){return 0;}
760 EXPORT_SYMBOL(freqhopping_config);
761
762 int mt_l2h_mempll(void){return 0;}
763 EXPORT_SYMBOL(mt_l2h_mempll);
764
765 int mt_h2l_mempll(void){return 0;}
766 EXPORT_SYMBOL(mt_h2l_mempll);
767
768 int mt_dfs_armpll(unsigned int current_freq, unsigned int target_dds){return 0;}
769 EXPORT_SYMBOL(mt_dfs_armpll);
770
771 int mt_dfs_mmpll(unsigned int target_dds){ return 0;}
772 EXPORT_SYMBOL(mt_dfs_mmpll);
773
774 int mt_dfs_vencpll(unsigned int target_dds){return 0;}
775 EXPORT_SYMBOL(mt_dfs_vencpll);
776
777 int mt_dfs_mpll(unsigned int target_dds){return 0;}
778 EXPORT_SYMBOL(mt_dfs_mpll);
779
780 int mt_is_support_DFS_mode(void){return 0;}
781 EXPORT_SYMBOL(mt_is_support_DFS_mode);
782
783 int mt_l2h_dvfs_mempll(void){return 0;}
784 EXPORT_SYMBOL(mt_l2h_dvfs_mempll);
785
786 int mt_h2l_dvfs_mempll(void){return 0;}
787 EXPORT_SYMBOL(mt_h2l_dvfs_mempll);
788
789 int mt_fh_dram_overclock(int clk){return 0;}
790 EXPORT_SYMBOL(mt_fh_dram_overclock);
791
792 int mt_fh_get_dramc(void){return 0;}
793 EXPORT_SYMBOL(mt_fh_get_dramc);
794
795 void mt_freqhopping_init(void){}
796 EXPORT_SYMBOL(mt_freqhopping_init);
797
798 void mt_freqhopping_pll_init(void){}
799 EXPORT_SYMBOL(mt_freqhopping_pll_init);
800
801 int mt_freqhopping_devctl(unsigned int cmd, void* args){return 0;}
802 EXPORT_SYMBOL(mt_freqhopping_devctl);
803
804 #else
805 void mt_fh_popod_save(void)
806 {
807 if(!g_p_fh_hal_drv)
808 {
809 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
810 return;
811 }
812 FH_MSG("EN: %s",__func__);
813
814 g_p_fh_hal_drv->mt_fh_popod_save();
815 }
816 EXPORT_SYMBOL(mt_fh_popod_save);
817
818 void mt_fh_popod_restore(void)
819 {
820 if(!g_p_fh_hal_drv)
821 {
822 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
823 return;
824 }
825
826 FH_MSG("EN: %s",__func__);
827
828 g_p_fh_hal_drv->mt_fh_popod_restore();
829 }
830 EXPORT_SYMBOL(mt_fh_popod_restore);
831
832 int freqhopping_config(unsigned int pll_id, unsigned long vco_freq, unsigned int enable)
833 {
834 struct freqhopping_ioctl fh_ctl;
835 unsigned int fh_status;
836 unsigned long flags=0;
837 unsigned int skip_flag=0;
838
839 FH_MSG("conf() id: %d f: %d, e: %d",(int)pll_id, (int)vco_freq, (int)enable);
840
841 if( (g_p_fh_hal_drv->mt_fh_get_init()) == 0){
842 FH_MSG("Not init yet, init first.");
843 return 1;
844 }
845
846 g_p_fh_hal_drv->mt_fh_lock(&flags);
847
848 //backup
849 fh_status = g_fh_drv_pll[pll_id].fh_status;
850
851 g_fh_drv_pll[pll_id].curr_freq = vco_freq;
852 g_fh_drv_pll[pll_id].pll_status = (enable > 0) ? FH_PLL_ENABLE:FH_PLL_DISABLE;
853
854
855 //prepare freqhopping_ioctl
856 fh_ctl.pll_id = pll_id;
857
858 if(g_fh_drv_pll[pll_id].fh_status != FH_FH_DISABLE){
859 //FH_MSG("+fh");
860 g_p_fh_hal_drv->mt_fh_hal_ctrl(&fh_ctl,enable);
861
862 }
863 else{
864 skip_flag = 1;
865 //FH_MSG("-fh,skip");
866 }
867
868 //restore
869 g_fh_drv_pll[pll_id].fh_status = fh_status;
870
871 g_p_fh_hal_drv->mt_fh_unlock(&flags);
872
873 if(skip_flag)
874 FH_MSG("-fh,skip");
875
876 return 0;
877 }
878 EXPORT_SYMBOL(freqhopping_config);
879
880
881 int mt_l2h_mempll(void)
882 {
883 return(g_p_fh_hal_drv->mt_l2h_mempll());
884 }
885 EXPORT_SYMBOL(mt_l2h_mempll);
886
887 int mt_h2l_mempll(void)
888 {
889 return(g_p_fh_hal_drv->mt_h2l_mempll());
890 }
891 EXPORT_SYMBOL(mt_h2l_mempll);
892
893 int mt_dfs_armpll(unsigned int current_freq, unsigned int target_dds)
894 {
895 if(!g_p_fh_hal_drv)
896 {
897 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
898 return 1;
899 }
900
901 return(g_p_fh_hal_drv->mt_dfs_armpll(current_freq, target_dds));
902 }
903 EXPORT_SYMBOL(mt_dfs_armpll);
904 int mt_dfs_mmpll(unsigned int target_dds)
905 {
906 if(!g_p_fh_hal_drv)
907 {
908 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
909 return 1;
910 }
911 return(g_p_fh_hal_drv->mt_dfs_mmpll(target_dds));
912 }
913 EXPORT_SYMBOL(mt_dfs_mmpll);
914 int mt_dfs_vencpll(unsigned int target_dds)
915 {
916 if(!g_p_fh_hal_drv)
917 {
918 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
919 return 1;
920 }
921
922 return(g_p_fh_hal_drv->mt_dfs_vencpll(target_dds));
923 }
924 EXPORT_SYMBOL(mt_dfs_vencpll);
925
926 int mt_dfs_mpll(unsigned int target_dds)
927 {
928 if((!g_p_fh_hal_drv) || (!g_p_fh_hal_drv->mt_dfs_mpll))
929 {
930 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
931 return 1;
932 }
933
934 return(g_p_fh_hal_drv->mt_dfs_mpll(target_dds));
935
936 }
937 EXPORT_SYMBOL(mt_dfs_mpll);
938
939
940 int mt_is_support_DFS_mode(void)
941 {
942 return(g_p_fh_hal_drv->mt_is_support_DFS_mode());
943 }
944 EXPORT_SYMBOL(mt_is_support_DFS_mode);
945 int mt_l2h_dvfs_mempll(void)
946 {
947 if(!g_p_fh_hal_drv)
948 {
949 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
950 return 1;
951 }
952 return(g_p_fh_hal_drv->mt_l2h_dvfs_mempll());
953 }
954 EXPORT_SYMBOL(mt_l2h_dvfs_mempll);
955
956 int mt_h2l_dvfs_mempll(void)
957 {
958 if(!g_p_fh_hal_drv)
959 {
960 FH_MSG("[%s]: g_p_fh_hal_drv is uninitialized.", __func__);
961 return 1;
962 }
963
964 return(g_p_fh_hal_drv->mt_h2l_dvfs_mempll());
965 }
966 EXPORT_SYMBOL(mt_h2l_dvfs_mempll);
967 int mt_fh_dram_overclock(int clk)
968 {
969 return (g_p_fh_hal_drv->mt_dram_overclock(clk));
970 }
971 EXPORT_SYMBOL(mt_fh_dram_overclock);
972
973 int mt_fh_get_dramc(void)
974 {
975 return (g_p_fh_hal_drv->mt_get_dramc());
976 }
977 EXPORT_SYMBOL(mt_fh_get_dramc);
978
979 void mt_freqhopping_init(void)
980 {
981 g_p_fh_hal_drv = mt_get_fh_hal_drv();
982
983 g_p_fh_hal_drv->mt_fh_hal_init();
984
985 g_fh_drv_pll = g_p_fh_hal_drv->fh_pll;
986 g_fh_drv_usr_def = g_p_fh_hal_drv->fh_usrdef;
987 g_drv_pll_count = g_p_fh_hal_drv->pll_cnt;
988
989 freqhopping_debug_proc_init();
990 platform_driver_register(&freqhopping_driver);
991
992 mt_freqhopping_pll_init(); //TODO_HAL: wait for clkmgr to invoke this function
993 }
994 EXPORT_SYMBOL(mt_freqhopping_init);
995
996 void mt_freqhopping_pll_init(void)
997 {
998 g_p_fh_hal_drv->mt_fh_default_conf();
999 }
1000 EXPORT_SYMBOL(mt_freqhopping_pll_init);
1001
1002 int mt_freqhopping_devctl(unsigned int cmd, void* args)
1003 {
1004 if(!g_p_fh_hal_drv)
1005 {
1006 return 1;
1007 }
1008
1009 //g_p_fh_hal_drv->ioctl(cmd, args);
1010 return 0;
1011
1012 }
1013 EXPORT_SYMBOL(mt_freqhopping_devctl);
1014
1015
1016 #endif