Merge tag 'v3.10.55' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mtk_eemcs_helper.c
1 #include <linux/module.h>
2 #include <linux/device.h>
3 #include <linux/fs.h>
4 #include <linux/cdev.h>
5 #include <linux/interrupt.h>
6 #include <linux/spinlock.h>
7 #include <linux/uaccess.h>
8 #include <linux/mm.h>
9 #include <linux/kfifo.h>
10 #include <linux/firmware.h>
11 #include <linux/syscalls.h>
12 #include <linux/uaccess.h>
13 #include <linux/platform_device.h>
14 #include <linux/proc_fs.h>
15 #include <asm/setup.h>
16
17 #include <mach/mtk_eemcs_helper.h>
18 #include <mach/mt_boot.h>
19 #include <mach/dfo_boot.h>
20 #include <asm/memblock.h>
21 #include <mach/battery_common.h>
22
23 #define SHOW_WARNING_NUM (5)
24
25 #define DFO_FEATURE_EN
26 #define MD5_MEM_SIZE (16*1024*1024)
27
28 //-------------feature enable/disable configure (oringinal from mtk_ccci_helper.c)----------------//
29 #define FEATURE_GET_MD_BAT_VOL //disable for bring up
30 //-------------grobal variable define----------------//
31
32 unsigned int ext_md_support[MAX_EXT_MD_NUM];
33 unsigned int ext_md_usage_case = 0;
34 unsigned int ext_md_size_list[MAX_EXT_MD_NUM] = {0};
35 phys_addr_t ext_md_mem_addr[MAX_EXT_MD_NUM] = {0};
36
37 eemcs_kern_func_info eemcs_func_table[MAX_EXT_MD_NUM][MAX_KERN_API];
38 static unsigned char eemcs_kern_func_err_num[MAX_EXT_MD_NUM][MAX_KERN_API];
39 eemcs_sys_cb_func_info_t eemcs_sys_cb_table_1000[MAX_EXT_MD_NUM][MAX_KERN_API];
40 eemcs_sys_cb_func_info_t eemcs_sys_cb_table_100[MAX_EXT_MD_NUM][MAX_KERN_API];
41 int (*eemcs_sys_msg_notify_func[MAX_EXT_MD_NUM])(int, unsigned int, unsigned int);
42
43 typedef struct _dfo_item
44 {
45 char name[32];
46 int value;
47 }dfo_item_t;
48
49 static dfo_item_t eemcs_dfo_setting[] =
50 {
51 {"MTK_MD5_SUPPORT", modem_lwg},
52 {"MTK_ENABLE_MD5", 1},
53 {"MD5_SIZE", MD5_MEM_SIZE},
54 };
55
56
57 /*------------------------external function API------------------------*/
58 extern unsigned long *get_ext_modem_start_addr_list(void);
59 /*---------------------------------------------------------------------*/
60
61
62 static int get_eemcs_dfo_setting(char item[], unsigned int *val)
63 {
64 char *eemcs_name;
65 int eemcs_value;
66 int i;
67
68 for (i=0; i<(sizeof(eemcs_dfo_setting)/sizeof(dfo_item_t)); i++) {
69 eemcs_name = eemcs_dfo_setting[i].name;
70 eemcs_value = eemcs_dfo_setting[i].value;
71 if(!strcmp(eemcs_name, item)) {
72 printk("[EEMCS/PLAT] Get DFO:%s:0x%08X\n", eemcs_name, eemcs_value);
73 *val = (unsigned int)eemcs_value;
74 return 0;
75 }
76 }
77 //printk("[EEMCS/PLAT] DFO:%s not found\n", i+1, item);
78 printk("[EEMCS/PLAT] DFO:%s not found\n", item);
79 return -1;
80 }
81
82 void update_ext_md_support(void)
83 {
84 int val;
85 ext_md_usage_case = 0;
86
87 if(get_eemcs_dfo_setting("MTK_MD5_SUPPORT", &val) == 0) {
88 ext_md_support[MD_SYS5-MD_EXT1] = val;
89 }
90
91 if(get_eemcs_dfo_setting("MTK_ENABLE_MD5", &val) == 0) {
92 if(val > 0) {
93 ext_md_usage_case |= MD5_EN;
94 }
95 }
96
97 if(get_eemcs_dfo_setting("MD5_SIZE", &val) == 0) {
98 val = round_up(val, 0x200000);
99 ext_md_size_list[MD_SYS5-MD_EXT1] = val;
100 }
101
102 }
103
104 /*API for kernal memory setting*/
105 /*get the info about how many modem is running currently*/
106 unsigned int get_nr_ext_modem(void)
107 {
108 return MAX_EXT_MD_NUM;
109 }
110 EXPORT_SYMBOL(get_nr_ext_modem);
111
112
113 unsigned int *get_ext_modem_size_list(void)
114 {
115 return ext_md_size_list;
116 }
117 EXPORT_SYMBOL(get_ext_modem_size_list);
118
119 #ifdef DFO_FEATURE_EN // pase DFO ATAG info
120 int parse_eemcs_dfo_setting(void *dfo_tbl, int num)
121 {
122 char *eemcs_name;
123 int *eemcs_value;
124 char *tag_name;
125 int tag_value;
126 int i, j;
127
128 tag_dfo_boot *dfo_data;
129
130 if(dfo_tbl == NULL)
131 return -1;
132
133 dfo_data = (tag_dfo_boot *)dfo_tbl;
134 for (i=0; i<(sizeof(eemcs_dfo_setting)/sizeof(dfo_item_t)); i++) {
135 eemcs_name = eemcs_dfo_setting[i].name;
136 eemcs_value = &(eemcs_dfo_setting[i].value);
137 for (j=0; j<num; j++) {
138 tag_name = dfo_data->name[j];
139 tag_value = dfo_data->value[j];
140 if(!strcmp(eemcs_name, tag_name)) {
141 *eemcs_value = tag_value;
142 }
143 }
144 printk("[EEMCS/PLAT] DFO:%s:0x%08X\n", eemcs_name, *eemcs_value);
145 }
146
147 update_ext_md_support();
148 return 0;
149 }
150 #else // load default seeting
151 int parse_eemcs_dfo_setting(void *dfo_data, int num)
152 {
153 char *eemcs_name;
154 int eemcs_value;
155 int i;
156
157 for (i=0; i<(sizeof(eemcs_dfo_setting)/sizeof(dfo_item_t)); i++) {
158 eemcs_name = eemcs_dfo_setting[i].name;
159 eemcs_value = eemcs_dfo_setting[i].value;
160 printk("[EEMCS/PLAT] DFO:%s:0x%08X\n", eemcs_name, eemcs_value);
161 }
162
163 update_ext_md_support();
164 return 0;
165 }
166 #endif
167
168
169 void eemcs_memory_reserve(void){
170 unsigned int md5_en;
171
172 if( (ext_md_usage_case&MD5_EN)== MD5_EN) { //Only MD1 enabled
173 md5_en = 1;
174 ext_md_mem_addr[MD_SYS5-MD_EXT1] =
175 (unsigned int)arm_memblock_steal(ext_md_size_list[MD_SYS5-MD_EXT1], SZ_32M);
176 } else { // No MD is enabled
177 md5_en = 0;
178 ext_md_mem_addr[MD_SYS5-MD_EXT1] = 0;
179 }
180
181 if ( (ext_md_mem_addr[MD_SYS5-MD_EXT1]&(32*1024*1024 - 1)) != 0 )
182 printk("[EEMCS/PLAT] md5 memory addr is not 32M align!!!\n");
183
184 printk("[EEMCS/PLAT] EN(%d):MemBase(0x%08X)\n", md5_en, (unsigned int)ext_md_mem_addr);
185
186 printk("[EEMCS/PLAT] (0)MemStart(0x%08X):MemSize(0x%08X)\n", \
187 ext_md_mem_addr[MD_SYS5-MD_EXT1], ext_md_size_list[MD_SYS5-MD_EXT1]);
188
189 }
190
191 int parse_ext_meta_md_setting(unsigned char args[])
192 {
193 unsigned char md_active_setting = args[1];
194 unsigned char md_setting_flag = args[0];
195 int active_id = -1;
196 int active_index = -1;
197
198 if(!(md_active_setting & MD5_SETTING_ACTIVE)) {
199 printk("[EEMCS/PLAT] META EXT MD setting not found [%d][%d]\n", args[0], args[1]);
200 } else {
201 active_id = MD_SYS5;
202 active_index = MD_SYS5 - MD_EXT1;
203 }
204
205 switch(active_id) {
206 case MD_SYS5:
207 if(md_setting_flag == MD_LWG_FLAG){
208 ext_md_support[active_index] = modem_lwg;
209 } else if(md_setting_flag == MD_LTG_FLAG){
210 ext_md_support[active_index] = modem_ltg;
211 }
212 printk("[EEMCS/PLAT] META EXT MD type:%d\n", ext_md_support[active_index]);
213 break;
214 }
215 return 0;
216 }
217
218 void get_ext_md_post_fix(int md_id, char buf[], char buf_ex[])
219 {
220 // name format: modem_X_YYY_Z_Ex.img
221 int X, Ex;
222 char YYY[8];
223 #if defined(DFO_FEATURE_EN)
224 unsigned int feature_val = 0;
225 #endif
226
227 if (md_id < MD_SYS5) {
228 printk("[EEMCS/PLAT] [Error]get_ext_md_post_fix: invalid md_id=%d\n", md_id);
229 return;
230 }
231
232 // X
233 X = md_id + 1;
234
235 #if defined(DFO_FEATURE_EN)
236 // DFO start -------------------
237 // YYY
238 YYY[0] = '\0';
239 switch(md_id) {
240 case MD_SYS5:
241 feature_val = ext_md_support[MD_SYS5-MD_EXT1];
242 break;
243 default:
244 printk("[EEMCS/PLAT] [Error]get_ext_md_post_fix: invalid md_id=%d\n", md_id);
245 break;
246 }
247 switch(feature_val) {
248 case modem_lwg:
249 snprintf(YYY, 8, "_lwg_n");
250 break;
251 case modem_ltg:
252 snprintf(YYY, 8, "_ltg_n");
253 break;
254 default:
255 printk("[EEMCS/PLAT] [Error]get_ext_md_post_fix: invalid feature=%d\n", feature_val);
256 break;
257 }
258 // DFO end ---------------------
259 #else
260 // Static start -------------------
261 // YYY
262 snprintf(YYY, 8, "_lwg_n");
263 // Static end ---------------------
264 #endif
265
266 // [_Ex] Get chip version
267 #if 0
268 if(get_chip_version() == CHIP_SW_VER_01)
269 Ex = 1;
270 else if(get_chip_version() == CHIP_SW_VER_02)
271 Ex = 2;
272 #else
273 Ex = 1;
274 #endif
275
276 // Gen post fix
277 if(buf) {
278 snprintf(buf, 12, "%d%s", X, YYY);
279 printk("[EEMCS/PLAT] MD%d image postfix=%s\n", md_id, buf);
280 }
281
282 if(buf_ex) {
283 snprintf(buf_ex, 12, "%d%s_E%d", X, YYY, Ex);
284 printk("[EEMCS/PLAT] MD%d image postfix=%s\n", md_id, buf_ex);
285 }
286 }
287 EXPORT_SYMBOL(get_ext_md_post_fix);
288
289 unsigned int get_ext_modem_is_enabled(int md_id)
290 {
291 switch(md_id)
292 {
293 case MD_SYS5:
294 return !!(ext_md_usage_case & MD5_EN);
295
296 default:
297 return 0;
298 }
299 }
300 EXPORT_SYMBOL(get_ext_modem_is_enabled);
301
302
303 unsigned int get_ext_modem_support(int md_id){
304 #if defined(DFO_FEATURE_EN)
305 unsigned int feature_val = 0;
306
307 switch(md_id) {
308 case MD_SYS5:
309 feature_val = ext_md_support[MD_SYS5-MD_EXT1];
310 break;
311 default:
312 printk("[EEMCS/PLAT] [Error]get_ext_modem_support: invalid md_id=%d\n", md_id);
313 break;
314 }
315
316 return feature_val;
317
318 #else
319
320 return modem_lwg;
321
322 #endif
323
324
325 }
326
327 EXPORT_SYMBOL(get_ext_modem_support);
328
329 unsigned int set_ext_modem_support(int md_id, int md_type){
330 #if defined(DFO_FEATURE_EN)
331 printk("[EEMCS/PLAT] set_ext_modem_support MD %d Type %d", md_id, md_type);
332 switch(md_id) {
333 case MD_SYS5:
334 if (md_type >= modem_lwg && md_type <= modem_ltg){
335 ext_md_support[MD_SYS5-MD_EXT1] = md_type;
336 }
337 else{
338 printk("[EEMCS/PLAT] [Error]set_modem_support fail(md:%d, md_type:%d)\n", md_id, md_type);
339 return -1;
340 }
341 break;
342 default:
343 printk("[EEMCS/PLAT] [Error]set_modem_support: invalid md_id=%d\n", md_id);
344 return -1;
345 break;
346 }
347
348 return 0;
349
350 #else
351
352 printk("[EEMCS/PLAT] set_ext_modem_support: DFO not support");
353 return -1;
354
355 #endif
356
357
358 }
359
360 EXPORT_SYMBOL(set_ext_modem_support);
361
362 void get_ap_platform_ver(char * ver)
363 {
364 sprintf(ver, "MT%04x_S%02x", get_chip_code(), (get_chip_sw_ver_code()&0xFF));
365 }
366
367 EXPORT_SYMBOL(get_ap_platform_ver);
368
369
370 unsigned int get_ext_md_mem_start_addr(int md_id){
371 unsigned int feature_val = 0;
372
373 switch(md_id) {
374 case MD_SYS5:
375 feature_val = ext_md_mem_addr[MD_SYS5-MD_EXT1];
376 break;
377 default:
378 printk("[EEMCS/PLAT] [Error]get_ext_md_mem_start_addr: invalid md_id=%d\n", md_id);
379 break;
380 }
381
382 return feature_val;
383 }
384 EXPORT_SYMBOL(get_ext_md_mem_start_addr);
385
386 unsigned int get_ext_md_mem_size(int md_id){
387 unsigned int feature_val = 0;
388
389 switch(md_id) {
390 case MD_SYS5:
391 feature_val = ext_md_size_list[MD_SYS5-MD_EXT1];
392 break;
393 default:
394 printk("[EEMCS/PLAT] [Error]get_ext_md_mem_size: invalid md_id=%d\n", md_id);
395 break;
396 }
397
398 return feature_val;
399
400 }
401 EXPORT_SYMBOL(get_ext_md_mem_size);
402
403
404 int eemcs_get_bat_info(unsigned int para)
405 {
406 int val = 0;
407 #if defined (FEATURE_GET_MD_BAT_VOL)
408 val = (int)BAT_Get_Battery_Voltage(0);
409 printk("[EEMCS/PLAT] get_bat_info : %d \n", val);
410 return val;
411 #endif
412
413 }
414 EXPORT_SYMBOL(eemcs_get_bat_info);
415
416
417 /*********************************************************************************/
418 /* API about Security cipher MD image */
419 /* */
420 /*********************************************************************************/
421 #ifdef ENABLE_SECURITY_FEATURE
422 #include <mach/mt_sec_export.h>
423 #include <mach/emi_mpu.h>
424 EXPORT_SYMBOL(masp_boot_init);
425 EXPORT_SYMBOL(masp_ccci_version_info);
426 EXPORT_SYMBOL(masp_ccci_is_cipherfmt);
427 EXPORT_SYMBOL(masp_ccci_signfmt_verify_file);
428 EXPORT_SYMBOL(masp_ccci_decrypt_cipherfmt);
429 EXPORT_SYMBOL(masp_secro_md_get_data);
430 EXPORT_SYMBOL(masp_secro_en);
431 EXPORT_SYMBOL(masp_secro_md_len);
432 EXPORT_SYMBOL(masp_secro_blk_sz);
433 EXPORT_SYMBOL(masp_secure_algo_init);
434 EXPORT_SYMBOL(masp_secure_algo_deinit);
435 EXPORT_SYMBOL(masp_secure_algo);
436 /*********************************************************************************/
437 /* API about md ROM/RW/Share memory MPU protection */
438 /* */
439 /*********************************************************************************/
440 int clear_md_region_protection(int md_id)
441 {
442 unsigned int rom_mem_mpu_id, rw_mem_mpu_id;
443
444 printk("[EEMCS/PLAT] Clear MD%d region protect...\n", md_id+1);
445 switch(md_id)
446 {
447 case MD_SYS5:
448 rom_mem_mpu_id = 1; //0;
449 rw_mem_mpu_id = 2; //1;
450 break;
451
452 default:
453 printk("[EEMCS/PLAT] [Error]clear_md_region_protection: invalid md_id=%d\n", md_id+1);
454 return -1;
455 }
456
457 printk("[EEMCS/PLAT] Clear MPU protect MD%d ROM region<%d>\n", md_id+1, rom_mem_mpu_id);
458 emi_mpu_set_region_protection(0, /*START_ADDR*/
459 0, /*END_ADDR*/
460 rom_mem_mpu_id, /*region*/
461 SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION));
462
463 printk("[EEMCS/PLAT] Clear MPU protect MD%d R/W region<%d>\n", md_id+1, rw_mem_mpu_id);
464 emi_mpu_set_region_protection(0, /*START_ADDR*/
465 0, /*END_ADDR*/
466 rw_mem_mpu_id, /*region*/
467 SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION));
468
469 return 0;
470 }
471 EXPORT_SYMBOL(clear_md_region_protection);
472 #endif
473
474 /***************************************************************************/
475 /* Register ccci call back function when AP receive system channel message */
476 /* */
477 /***************************************************************************/
478 int eemcs_register_sys_msg_notify_func(int md_id, int (*func)(int, unsigned int, unsigned int))
479 {
480 int ret = 0;
481 int ex_md_id = md_id - MD_EXT1;
482
483 if( ex_md_id >= MAX_EXT_MD_NUM ) {
484 printk("[EEMCS/PLAT] [Error]register_sys_msg_notify_func: invalid md id(%d)\n", md_id+1);
485 return E_PARAM;
486 }
487
488 if(eemcs_sys_msg_notify_func[ex_md_id] == NULL) {
489 eemcs_sys_msg_notify_func[ex_md_id] = func;
490 } else {
491 printk("[EEMCS/PLAT] [Error]eemcs_sys_msg_notify_func: func registered!(%d)\n", md_id+1);
492 }
493
494 return ret;
495 }
496 EXPORT_SYMBOL(eemcs_register_sys_msg_notify_func);
497
498
499 int eemcs_notify_md_by_sys_msg(int md_id, unsigned int msg, unsigned int data)
500 {
501 int (*func)(int, unsigned int, unsigned int);
502 int ret = 0;
503 int ext_md_id = md_id - MD_EXT1;
504
505 if(ext_md_id >= MAX_EXT_MD_NUM) {
506 printk("[EEMCS/PLAT] [Error]notify_md_by_sys_msg: invalid md id(%d)\n", md_id+1);
507 return E_PARAM;
508 }
509
510 func = eemcs_sys_msg_notify_func[ext_md_id];
511 if(func != NULL) {
512 ret = func(md_id, msg, data);
513 } else {
514 ret = E_NO_EXIST;
515 printk("[EEMCS/PLAT] [Error]notify_md_by_sys_msg: func not register!(%d)\n", md_id+1);
516 }
517
518 return ret;
519 }
520 EXPORT_SYMBOL(eemcs_notify_md_by_sys_msg);
521
522
523 int eemcs_register_ccci_sys_call_back(int md_id, unsigned int id, eemcs_sys_cb_func_t func)
524 {
525 int ret = 0;
526 eemcs_sys_cb_func_info_t *info_ptr;
527 int ext_md_id = md_id - MD_EXT1;
528
529 if( ext_md_id >= MAX_EXT_MD_NUM ) {
530 printk("[EEMCS/PLAT] [Error]register_sys_call_back: invalid md id(%d)\n", md_id+1);
531 return E_PARAM;
532 }
533
534 if((id >= 0x100)&&((id-0x100) < MAX_KERN_API)) {
535 info_ptr = &(eemcs_sys_cb_table_100[ext_md_id][id-0x100]);
536 } else if((id >= 0x1000)&&((id-0x1000) < MAX_KERN_API)) {
537 info_ptr = &(eemcs_sys_cb_table_1000[ext_md_id][id-0x1000]);
538 } else {
539 printk("[EEMCS/PLAT] [Error]register_sys_call_back: invalid func id(0x%x)\n", id);
540 return E_PARAM;
541 }
542
543 if(info_ptr->func == NULL) {
544 info_ptr->id = id;
545 info_ptr->func = func;
546 }
547 else
548 printk("[EEMCS/PLAT] [Error]register_sys_call_back: func(0x%x) registered!\n", id);
549
550 return ret;
551 }
552 EXPORT_SYMBOL(eemcs_register_ccci_sys_call_back);
553
554
555 void eemcs_exec_ccci_sys_call_back(int md_id, int cb_id, int data)
556 {
557 eemcs_sys_cb_func_t func;
558 int id;
559 eemcs_sys_cb_func_info_t *curr_table;
560 int ext_md_id = md_id - MD_EXT1;
561
562 if(ext_md_id >= MAX_EXT_MD_NUM) {
563 printk("[EEMCS/PLAT] [Error]exec_sys_cb: invalid md id(%d) \n", md_id+1);
564 return;
565 }
566
567 id = cb_id & 0xFF;
568 if(id >= MAX_KERN_API) {
569 printk("[EEMCS/PLAT] [Error]exec_sys_cb: invalid func id(0x%x)\n", cb_id);
570 return;
571 }
572
573 if ((cb_id & (0x1000|0x100))==0x1000) {
574 curr_table = eemcs_sys_cb_table_1000[ext_md_id];
575 } else if ((cb_id & (0x1000|0x100))==0x100) {
576 curr_table = eemcs_sys_cb_table_100[ext_md_id];
577 } else {
578 printk("[EEMCS/PLAT] [Error]exec_sys_cb: invalid func id(0x%x)\n", cb_id);
579 return;
580 }
581
582 func = curr_table[id].func;
583 if(func != NULL) {
584 func(md_id, data);
585 } else {
586 printk("[EEMCS/PLAT] [Error]exec_sys_cb: func id(0x%x) not register!\n", cb_id);
587 }
588 }
589 EXPORT_SYMBOL(eemcs_exec_ccci_sys_call_back);
590
591
592 /////////////////////////////////////////////////////////////////////////////////////////////
593
594 /***************************************************************************/
595 /* Register kernel API for ccci driver invoking */
596 /* */
597 /***************************************************************************/
598 int eemcs_register_ccci_kern_func_by_md_id(int md_id, unsigned int id, eemcs_kern_cb_func_t func)
599 {
600 int ret = 0;
601 eemcs_kern_func_info *info_ptr;
602
603 if((id >= MAX_KERN_API) || (func == NULL) || (md_id >= MAX_EXT_MD_NUM)) {
604 printk("[EEMCS/PLAT] [Error]register_kern_func: md_id:%d, func_id:%d!\n", md_id+1, id);
605 return E_PARAM;
606 }
607
608 info_ptr = &(eemcs_func_table[md_id][id]);
609 if(info_ptr->func == NULL) {
610 info_ptr->id = id;
611 info_ptr->func = func;
612 }
613 else
614 printk("[EEMCS/PLAT] [Error]register_kern_func: func(%d) registered!(%d)\n", md_id+1, id);
615
616 return ret;
617 }
618 EXPORT_SYMBOL(eemcs_register_ccci_kern_func_by_md_id);
619
620
621 int eemcs_register_ccci_kern_func(unsigned int id, eemcs_kern_cb_func_t func)
622 {
623 return eemcs_register_ccci_kern_func_by_md_id(CURR_EXT_MD_ID, id, func);
624 }
625 EXPORT_SYMBOL(eemcs_register_ccci_kern_func);
626
627
628 int eemcs_exec_ccci_kern_func_by_md_id(int md_id, unsigned int id, char *buf, unsigned int len)
629 {
630 eemcs_kern_cb_func_t func;
631 int ret = 0;
632
633 if(md_id >= MAX_EXT_MD_NUM) {
634 printk("[EEMCS/PLAT] [Error]exec kern func: invalid md id(%d)\n", md_id+1);
635 return E_PARAM;
636 }
637
638 if(id >= MAX_KERN_API) {
639 printk("[EEMCS/PLAT] [Error]exec kern func: invalid func(%d) id(%d)\n", md_id, id);
640 return E_PARAM;
641 }
642
643 func = eemcs_func_table[md_id][id].func;
644 if(func != NULL) {
645 ret = func(md_id, buf, len);
646 }
647 else {
648 ret = E_NO_EXIST;
649 if(eemcs_kern_func_err_num[md_id][id] < SHOW_WARNING_NUM) {
650 eemcs_kern_func_err_num[md_id][id]++;
651 printk("[EEMCS/PLAT] [Error]exec kern func: func%d not register(%d)\n", md_id+1, id);
652 }
653 }
654
655 return ret;
656 }
657 EXPORT_SYMBOL(eemcs_exec_ccci_kern_func_by_md_id);
658
659
660 int eemcs_exec_ccci_kern_func(unsigned int id, char *buf, unsigned int len)
661 {
662 return eemcs_exec_ccci_kern_func_by_md_id(CURR_EXT_MD_ID, id, buf, len);
663 }
664 EXPORT_SYMBOL(eemcs_exec_ccci_kern_func);
665
666
667 /***************************************************************************/
668 /* Register ccci suspend & resume function */
669 /* */
670 /***************************************************************************/
671 typedef struct eemcs_pm_cb_item
672 {
673 void (*cb_func)(int);
674 int md_id;
675 }eemcs_pm_cb_item_t;
676
677
678 static eemcs_pm_cb_item_t eemcs_suspend_cb_table[MAX_EXT_MD_NUM][MAX_SLEEP_API];
679 static eemcs_pm_cb_item_t eemcs_resume_cb_table[MAX_EXT_MD_NUM][MAX_SLEEP_API];
680
681
682 void eemcs_register_suspend_notify(int md_id, unsigned int id, void (*func)(int))
683 {
684 if((id >= MAX_SLEEP_API) || (func == NULL) || (md_id >= MAX_EXT_MD_NUM)) {
685 printk("[EEMCS/PLAT] [Error]register_suspend_notify: invalid para(md:%d, cmd:%d)\n", md_id, id);
686 }
687
688 if (eemcs_suspend_cb_table[md_id][id].cb_func == NULL){
689 eemcs_suspend_cb_table[md_id][id].cb_func = func;
690 eemcs_suspend_cb_table[md_id][id].md_id = md_id;
691 }
692 }
693 EXPORT_SYMBOL(eemcs_register_suspend_notify);
694
695
696 void eemcs_register_resume_notify(int md_id, unsigned int id, void (*func)(int))
697 {
698 if((id >= MAX_SLEEP_API) || (func == NULL) || (md_id >= MAX_EXT_MD_NUM)) {
699 printk("[EEMCS/PLAT] [Error]register_resume_notify: invalid para(md:%d, cmd:%d)\n", md_id, id);
700 }
701
702 if (eemcs_resume_cb_table[md_id][id].cb_func == NULL){
703 eemcs_resume_cb_table[md_id][id].cb_func = func;
704 eemcs_resume_cb_table[md_id][id].md_id = md_id;
705 }
706 }
707 EXPORT_SYMBOL(eemcs_register_resume_notify);
708
709
710 static int eemcs_helper_probe(struct platform_device *dev)
711 {
712
713 //printk( "\neemcs_helper_probe\n" );
714 return 0;
715 }
716
717 static int eemcs_helper_remove(struct platform_device *dev)
718 {
719 //printk( "\neemcs_helper_remove\n" );
720 return 0;
721 }
722
723 static void eemcs_helper_shutdown(struct platform_device *dev)
724 {
725 //printk( "\neemcs_helper_shutdown\n" );
726 }
727
728 static int eemcs_helper_suspend(struct platform_device *dev, pm_message_t state)
729 {
730 int i, j;
731 void (*func)(int);
732 int md_id;
733
734 printk( "\neemcs_helper_suspend\n" );
735
736 for (i = 0; i < MAX_EXT_MD_NUM; i++) {
737 for (j = 0; j < EEMCS_SLP_ID_MAX; j++) {
738 func = eemcs_suspend_cb_table[i][j].cb_func;
739 md_id = eemcs_suspend_cb_table[i][j].md_id;
740 if(func != NULL)
741 func(md_id);
742 }
743 }
744
745 return 0;
746 }
747
748 static int eemcs_helper_resume(struct platform_device *dev)
749 {
750 int i,j;
751 void (*func)(int);
752 int md_id;
753
754 printk( "\neemcs_helper_resume\n" );
755
756 for (i = 0; i < MAX_EXT_MD_NUM; i++) {
757 for (j = 0; j < EEMCS_RSM_ID_MAX; j++) {
758 func = eemcs_resume_cb_table[i][j].cb_func;
759 md_id = eemcs_resume_cb_table[i][j].md_id;
760 if(func != NULL)
761 func(md_id);
762 }
763 }
764
765 return 0;
766 }
767
768 //*-------------------------------------------------------------*//
769 #if defined (CONFIG_PM) && defined (FEATURE_PM_IPO_H)
770 int eemcs_helper_pm_suspend(struct device *device)
771 {
772 //pr_debug("calling %s()\n", __func__);
773
774 struct platform_device *pdev = to_platform_device(device);
775 BUG_ON(pdev == NULL);
776
777 return eemcs_helper_suspend(pdev, PMSG_SUSPEND);
778 }
779
780 int eemcs_helper_pm_resume(struct device *device)
781 {
782 //pr_debug("calling %s()\n", __func__);
783
784 struct platform_device *pdev = to_platform_device(device);
785 BUG_ON(pdev == NULL);
786
787 return eemcs_helper_resume(pdev);
788 }
789
790 extern void mt_irq_set_sens(unsigned int irq, unsigned int sens);
791 extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity);
792 int eemcs_helper_pm_restore_noirq(struct device *device)
793 {
794 pr_debug("calling %s()\n", __func__);
795 /*Not ready, need to check more details*/
796 #if 0
797 // CCIF AP0
798 mt_irq_set_sens(CCIF0_AP_IRQ_ID, MT_LEVEL_SENSITIVE);
799 mt_irq_set_polarity(CCIF0_AP_IRQ_ID, MT_POLARITY_LOW);
800
801 // MD1 WDT
802 mt_irq_set_sens(MD_WDT_IRQ_ID, MT_EDGE_SENSITIVE);
803 mt_irq_set_polarity(MD_WDT_IRQ_ID, MT_POLARITY_LOW);
804
805 // MD1
806 exec_ccci_kern_func_by_md_id(0, ID_IPO_H_RESTORE_CB, NULL, 0);
807 #endif
808 return 0;
809
810 }
811
812 #else /*CONFIG_PM*/
813
814 #define eemcs_helper_pm_suspend NULL
815 #define eemcs_helper_pm_resume NULL
816 #define eemcs_helper_pm_restore_noirq NULL
817
818 #endif /*CONFIG_PM*/
819 //*-------------------------------------------------------------*//
820
821 struct dev_pm_ops eemcs_helper_pm_ops = {
822 .suspend = eemcs_helper_pm_suspend,
823 .resume = eemcs_helper_pm_resume,
824 .freeze = eemcs_helper_pm_suspend,
825 .thaw = eemcs_helper_pm_resume,
826 .poweroff = eemcs_helper_pm_suspend,
827 .restore = eemcs_helper_pm_resume,
828 .restore_noirq = eemcs_helper_pm_restore_noirq,
829 };
830
831 static struct platform_driver eemcs_helper_driver =
832 {
833 .driver = {
834 .name = "eemcs-helper",
835 #ifdef CONFIG_PM
836 .pm = &eemcs_helper_pm_ops,
837 #endif
838 },
839 .probe = eemcs_helper_probe,
840 .remove = eemcs_helper_remove,
841 .shutdown = eemcs_helper_shutdown,
842 .suspend = eemcs_helper_suspend,
843 .resume = eemcs_helper_resume,
844 };
845
846 struct platform_device eemcs_helper_device = {
847 .name = "eemcs-helper",
848 .id = 0,
849 .dev = {}
850 };
851
852 static int __init eemcs_helper_init(void)
853 {
854 int ret;
855
856
857 /* Not ready, need check*/
858 #if 0
859 // Init ccci helper sys fs
860 memset( (void*)cmd_map_table, 0, sizeof(cmd_map_table) );
861 mtk_ccci_sysfs();
862 #endif
863 // init ccci kernel API register table
864 memset((void*)eemcs_func_table, 0, sizeof(eemcs_func_table));
865 memset((void*)eemcs_kern_func_err_num, 0, sizeof(eemcs_kern_func_err_num));
866
867 // init ccci system channel call back function register table
868 memset((void*)eemcs_sys_cb_table_100, 0, sizeof(eemcs_sys_cb_table_100));
869 memset((void*)eemcs_sys_cb_table_1000, 0, sizeof(eemcs_sys_cb_table_1000));
870
871 ret = platform_device_register(&eemcs_helper_device);
872 if (ret) {
873 printk("[EEMCS/PLAT] [Error]eemcs_helper_device register fail: %d\n", ret);
874 return ret;
875 }
876
877 ret = platform_driver_register(&eemcs_helper_driver);
878 if (ret) {
879 printk("[EEMCS/PLAT] [Error]eemcs_helper_driver register fail: %d\n", ret);
880 return ret;
881 }
882
883 return 0;
884 }
885
886 module_init(eemcs_helper_init);
887
888 MODULE_LICENSE("GPL");
889 MODULE_AUTHOR("MTK");
890 MODULE_DESCRIPTION("The eemcs helper function");
891 /////////////////////////////////////////////////////////////////////////////////////////////
892
893