Merge tag 'lsk-android-14.04' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / rockchip_pm.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/suspend.h>
4 #include <asm/cacheflush.h>
5 #include <asm/tlbflush.h>
6 #include <asm/suspend.h>
7 #include <linux/delay.h>
8 #include <linux/moduleparam.h>
9 #include <linux/rockchip/common.h>
10
11 #include <asm/io.h>
12 #include "pm.h"
13
14 /*************************dump reg********************************************/
15
16 void rkpm_ddr_reg_offset_dump(void __iomem * base_addr,u32 _offset)
17 {
18     rkpm_ddr_printhex(_offset);     
19     rkpm_ddr_printch('-');
20     rkpm_ddr_printhex(readl_relaxed((base_addr + _offset)));  
21 }
22
23 void  rkpm_ddr_regs_dump(void __iomem * base_addr,u32 start_offset,u32 end_offset)
24 {
25         u32 i;
26         u32 line=0;
27
28         rkpm_ddr_printascii("start from:");     
29         rkpm_ddr_printhex((u32)(base_addr +start_offset));       
30         rkpm_ddr_printch('\n');
31         
32         for(i=start_offset;i<=end_offset;)
33         {
34             rkpm_ddr_printhex(reg_readl((base_addr + i)));  
35             line++;
36             if((line%4==0)||i==end_offset)
37                 rkpm_ddr_printch('\n');
38             else              
39                 rkpm_ddr_printch('-');
40             i+=4;
41         } 
42     
43 }
44
45 static struct rkpm_ops pm_ops={NULL};
46
47 static struct rkpm_sram_ops *p_pm_sram_ops=NULL;//pie point for pm_sram_ops
48 static rkpm_sram_suspend_arg_cb p_suspend_pie_cb=NULL;
49
50 // for user setting
51 static u32   rkpm_ctrbits=0;
52 //for judging rkpm_ctrbits valid ,save ifself
53 static u32   rkpm_jdg_ctrbits=0;
54 static u32   rkpm_jdg_sram_ctrbits=0;
55
56 /**************************************ddr callback setting***************************************/
57
58 void rkpm_set_pie_info(struct rkpm_sram_ops *pm_sram_ops,rkpm_sram_suspend_arg_cb pie_cb)
59 {
60
61     p_pm_sram_ops=pm_sram_ops;
62     p_suspend_pie_cb=pie_cb;
63
64
65 }
66
67 void rkpm_set_ops_prepare_finish(rkpm_ops_void_callback prepare,rkpm_ops_void_callback finish)
68 {
69         pm_ops.prepare=prepare; 
70         pm_ops.finish=finish;   
71 }
72
73 void rkpm_set_ops_pwr_dmns(rkpm_ops_void_callback pwr_dmns,rkpm_ops_void_callback re_pwr_dmns)
74 {
75         pm_ops.pwr_dmns=pwr_dmns;       
76         pm_ops.re_pwr_dmns=re_pwr_dmns;
77 }
78
79 void rkpm_set_ops_gtclks(rkpm_ops_void_callback gtclks,rkpm_ops_void_callback re_gtclks)
80 {
81         pm_ops.gtclks=gtclks;   
82         pm_ops.re_gtclks=re_gtclks;
83 }
84
85
86 void rkpm_set_ops_plls(rkpm_ops_void_callback plls,rkpm_ops_void_callback re_plls)
87 {
88         pm_ops.plls=plls;       
89         pm_ops.re_plls=re_plls;
90 }
91
92
93 void rkpm_set_ops_gpios(rkpm_ops_void_callback gpios,rkpm_ops_void_callback re_gpios)
94 {
95         pm_ops.gpios=gpios;     
96         pm_ops.re_gpios=re_gpios;
97 }
98 void rkpm_set_ops_save_setting(rkpm_ops_paramter_u32_cb save_setting,rkpm_ops_void_callback re_save_setting)
99 {
100         pm_ops.save_setting=save_setting;       
101         pm_ops.re_save_setting=re_save_setting;
102 }
103
104
105
106 void rkpm_set_ops_printch(rkpm_ops_printch_callback printch)
107 {
108         pm_ops.printch=printch; 
109 }
110
111 void rkpm_set_ops_regs_pread(rkpm_ops_void_callback regs_pread)
112 {
113         pm_ops.regs_pread=regs_pread;   
114 }
115
116 void rkpm_set_ops_regs_sleep(rkpm_ops_void_callback slp_setting,rkpm_ops_void_callback re_last)
117 {       
118
119         pm_ops.slp_setting=slp_setting;    
120
121         pm_ops.slp_re_first=re_last;    
122 }
123
124
125 /**************************************sram callback setting***************************************/
126 void rkpm_set_sram_ops_volt(rkpm_ops_void_callback volts,rkpm_ops_void_callback re_volts)
127 {
128         if(p_pm_sram_ops)
129         {
130             p_pm_sram_ops->volts=volts; 
131             p_pm_sram_ops->re_volts=re_volts;
132         }
133 }
134
135 void rkpm_set_sram_ops_gtclks(rkpm_ops_void_callback gtclks,rkpm_ops_void_callback re_gtclks)
136 {
137          if(p_pm_sram_ops)
138         {
139                 p_pm_sram_ops->gtclks=gtclks;   
140                 p_pm_sram_ops->re_gtclks=re_gtclks;
141         }
142 }
143
144 void rkpm_set_sram_ops_sysclk(rkpm_ops_paramter_u32_cb sysclk,rkpm_ops_paramter_u32_cb re_sysclk)
145 {
146          if(p_pm_sram_ops)
147         {
148                 p_pm_sram_ops->sysclk=sysclk;   
149                 p_pm_sram_ops->re_sysclk=re_sysclk;
150         }
151 }
152
153 void rkpm_set_sram_ops_pmic(rkpm_ops_void_callback pmic,rkpm_ops_void_callback re_pmic)
154 {
155      if(p_pm_sram_ops)
156     {
157         p_pm_sram_ops->pmic=pmic;       
158         p_pm_sram_ops->re_pmic=re_pmic;
159     }
160 }
161
162 void rkpm_set_sram_ops_ddr(rkpm_ops_void_callback ddr,rkpm_ops_void_callback re_ddr)
163 {
164     if(p_pm_sram_ops)
165     {
166         p_pm_sram_ops->ddr=ddr; 
167         p_pm_sram_ops->re_ddr=re_ddr;
168     }
169 }
170 void rkpm_set_sram_ops_printch(rkpm_ops_printch_callback printch)
171 {  
172     if(p_pm_sram_ops)
173         p_pm_sram_ops->printch=printch; 
174 }
175
176 /******************for user ************************/
177 void inline rkpm_set_ctrbits(u32 bits)
178 {       
179         rkpm_ctrbits = bits;
180         
181 }
182 void inline rkpm_add_ctrbits(u32 bits)
183 {       
184         rkpm_ctrbits |= bits;
185         
186 }
187 u32  inline rkpm_get_ctrbits(void)
188 {       
189         return rkpm_ctrbits;
190 }
191
192 u32 inline  rkpm_chk_ctrbits(u32 bits)
193 {       
194         return (rkpm_ctrbits&bits);
195 }
196
197 //clear
198 void inline rkpm_clr_ctrbits(u32 bits)
199 {
200         rkpm_ctrbits&=~bits;
201 }
202
203 /****************** for pm.c************************/
204
205 static void inline rkpm_set_jdg_ctrbits(u32 bits)
206 {       
207         rkpm_jdg_ctrbits = bits;
208         
209 }
210 static u32  inline rkpm_get_jdg_ctrbits(void)
211 {       
212         return rkpm_jdg_ctrbits;
213 }
214
215 static void inline rkpm_add_jdg_ctrbits(int bit)
216 {       
217         rkpm_jdg_ctrbits|=bit;
218 }
219
220 #if 0
221 static u32 inline rkpm_chk_jdg_ctrbit(int bit)
222 {       
223         return (rkpm_jdg_ctrbits&bit);
224 }
225 #endif
226
227 static u32 inline rkpm_chk_jdg_ctrbits(int bits)
228 {       
229         return (rkpm_jdg_ctrbits&bits);
230 }
231 //clear
232 static void inline rkpm_clr_jdg_ctrbits(int bit)
233 {
234         rkpm_jdg_ctrbits&=~bit;
235 }
236
237
238 #define  RKPM_DDR_FUN(fun) \
239         if(pm_ops.fun)\
240                 (pm_ops.fun)()
241
242 // fun with paramater  param (p1,p2,p3)
243 #define  RKPM_DDR_PFUN(fun,param) \
244         if(pm_ops.fun) \
245             {(pm_ops.fun)param;} while(0)
246
247 #define  RKPM_BITCTR_DDR_FUN(ctr,fun) \
248         if(rkpm_chk_jdg_ctrbits(RKPM_CTR_##ctr)&&pm_ops.fun)\
249                 (pm_ops.fun)()
250
251 #define  RKPM_BITSCTR_DDR_FUN(bits,fun) \
252         if(rkpm_chk_jdg_ctrbits(bits)&&pm_ops.fun)\
253             (pm_ops.fun)()
254
255
256         
257 #define  RKPM_LPMD_BITSCTR_DDR_PFUN(bits,fun,param) \
258                 if(rkpm_chk_jdg_ctrbits(RKPM_CTRBITS_SOC_DLPMD)&&pm_ops.fun)\
259                     (pm_ops.fun)param
260
261 #define  RKPM_LPMD_BITSCTR_DDR_FUN(bits,fun) \
262                 if(rkpm_chk_jdg_ctrbits(RKPM_CTRBITS_SOC_DLPMD)&&pm_ops.fun)\
263                         (pm_ops.fun)()
264
265
266
267 void rkpm_ctrbits_prepare(void)
268 {
269         
270         //rkpm_sram_ctrbits=rkpm_ctrbits;
271         
272         rkpm_jdg_ctrbits=rkpm_ctrbits;
273
274         //if plls is no pd,clk rate is high, volts can not setting low,so we need to judge ctrbits
275         //if(rkpm_chk_jdg_ctrbits(RKPM_CTR_VOLTS))
276         {
277                 //rkpm_clr_jdg_ctrbits(RKPM_CTR_VOLTS);
278         }
279     
280         rkpm_jdg_sram_ctrbits=rkpm_jdg_ctrbits;
281         
282         //clk gating will gate ddr clk in sram
283         if(!rkpm_chk_val_ctrbits(rkpm_jdg_sram_ctrbits,RKPM_CTR_DDR))
284         {
285            // rkpm_clr_val_ctrbit(rkpm_jdg_sram_ctrbits,RKPM_CTR_GTCLKS);
286         }
287     
288 }
289
290 struct rk_soc_pm_info_st {
291     int offset;
292     char *name;
293 };
294
295 #define RK_SOC_PM_HELP_(id,NAME)\
296         {\
297         .offset= RKPM_CTR_##id,\
298         .name= NAME,\
299         }
300     
301 struct rk_soc_pm_info_st rk_soc_pm_helps[]={
302 #if 0
303     RK_SOC_PM_HELP_(NO_PD,"pd is not power dn"),
304     RK_SOC_PM_HELP_(NO_CLK_GATING,"clk is not gating"),
305     RK_SOC_PM_HELP_(NO_PLL,"pll is not power dn"),
306     RK_SOC_PM_HELP_(NO_VOLT,"volt is not set suspend"),
307     RK_SOC_PM_HELP_(NO_GPIO,"gpio is not control "),
308     //RK_SOC_PM_HELP_(NO_SRAM,"not enter sram code"),
309     RK_SOC_PM_HELP_(NO_DDR,"ddr is not reflash"),
310     RK_SOC_PM_HELP_(NO_PMIC,"pmic is not suspend"),
311     RK_SOC_PM_HELP_(RET_DIRT,"sys return from pm_enter directly"),
312     RK_SOC_PM_HELP_(SRAM_NO_WFI,"sys is not runing wfi in sram"),
313     RK_SOC_PM_HELP_(WAKE_UP_KEY,"send a power key to wake up lcd"),
314 #endif
315 };
316     
317 ssize_t rk_soc_pm_helps_sprintf(char *buf)
318 {
319     char *s = buf;
320     int i;
321
322     for(i=0;i<ARRAY_SIZE(rk_soc_pm_helps);i++)
323     {
324         s += sprintf(s, "bit(%d): %s\n", rk_soc_pm_helps[i].offset,rk_soc_pm_helps[i].name);
325     }
326
327     return (s-buf);
328 }   
329     
330 void rk_soc_pm_helps_printk(void)
331 {
332     int i;
333     printk("**************rkpm_ctr_bits bits help***********:\n");
334     for(i=0;i<ARRAY_SIZE(rk_soc_pm_helps);i++)
335     {
336         printk("bit(%d): %s\n", rk_soc_pm_helps[i].offset,rk_soc_pm_helps[i].name);
337     }
338 }   
339
340 #if 0
341 static int __init early_param_rk_soc_pm_ctr(char *str)
342 {
343     get_option(&str, &rkpm_ctrbits);
344     
345     printk("********rkpm_ctr_bits information is following:*********\n");
346     printk("rkpm_ctr_bits=%x\n",rkpm_ctrbits);
347     if(rkpm_ctrbits)
348     {
349         rk_soc_pm_helps_printk();
350     }
351     printk("********rkpm_ctr_bits information end*********\n");
352     return 0;
353 }
354 #endif
355
356 /*******************************************log*********************************************/
357
358
359 bool  pm_log;
360
361 extern void pm_emit_log_char(char c);
362
363 /********************************ddr print**********************************/
364 void rkpm_ddr_printch(char byte)
365 {
366         if(pm_ops.printch)
367             pm_ops.printch(byte);       
368         //if (byte == '\n')
369                 //rkpm_ddr_printch('\r');
370 }
371 void rkpm_ddr_printascii(const char *s)
372 {
373         while (*s) {
374                 rkpm_ddr_printch(*s);
375                 s++;
376         }
377 }
378
379 void  rkpm_ddr_printhex(unsigned int hex)
380 {
381         int i = 8;
382         rkpm_ddr_printch('0');
383         rkpm_ddr_printch('x');
384         while (i--) {
385                 unsigned char c = (hex & 0xF0000000) >> 28;
386                 rkpm_ddr_printch(c < 0xa ? c + '0' : c - 0xa + 'a');
387                 hex <<= 4;
388         }
389 }
390 static int rk_lpmode_enter(unsigned long arg)
391 {
392
393         //RKPM_DDR_PFUN(slp_setting(rkpm_jdg_sram_ctrbits),slp_setting); 
394     
395         RKPM_DDR_FUN(slp_setting); 
396                 
397         local_flush_tlb_all();
398         flush_cache_all();
399         outer_flush_all();
400         outer_disable();
401         cpu_proc_fin();
402         //outer_inv_all();// ???
403         //  l2x0_inv_all_pm(); //rk319x is not need
404         flush_cache_all();
405         
406         rkpm_ddr_printch('d');
407
408         //rkpm_udelay(3*10);
409
410         dsb();
411         wfi();  
412         
413         rkpm_ddr_printch('D');
414         return 0;
415 }
416
417
418 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long));
419
420 static int rkpm_enter(suspend_state_t state)
421 {
422  
423         printk("%s\n",__FUNCTION__);
424
425         
426         RKPM_DDR_FUN(prepare);   
427         
428         printk(KERN_DEBUG "pm: ");
429
430         rkpm_ctrbits_prepare();
431          
432       //  if(rkpm_chk_jdg_ctrbits(RKPM_CTR_RET_DIRT))
433       //  return 0;
434       
435         rkpm_ddr_printch('0');
436
437         RKPM_BITCTR_DDR_FUN(PWR_DMNS,pwr_dmns);
438
439         rkpm_ddr_printch('1');
440
441         local_fiq_disable();
442     
443         RKPM_DDR_PFUN(save_setting,(rkpm_jdg_sram_ctrbits)); 
444         
445         rkpm_ddr_printch('2');
446         
447         RKPM_BITCTR_DDR_FUN(GTCLKS,gtclks);
448
449         rkpm_ddr_printch('3');
450
451         RKPM_BITCTR_DDR_FUN(PLLS,plls);
452
453         rkpm_ddr_printch('4');
454
455         RKPM_BITCTR_DDR_FUN(GPIOS,gpios);
456
457         RKPM_DDR_FUN(regs_pread);
458
459         rkpm_ddr_printch('5');
460
461         pm_log = false;
462
463         if(rkpm_chk_jdg_ctrbits(RKPM_CTRBITS_SOC_DLPMD))
464         {   
465             if(cpu_suspend(0,rk_lpmode_enter)==0)
466             {
467                 RKPM_DDR_FUN(slp_re_first);
468                 rkpm_ddr_printch('D');
469                 //rk_soc_pm_ctr_bits_prepare();
470             }                         
471             rkpm_ddr_printch('d');          
472         }
473         else if(rkpm_chk_jdg_ctrbits(RKPM_CTR_IDLESRAM_MD)&&p_suspend_pie_cb)
474         {
475             call_with_stack(p_suspend_pie_cb,&rkpm_jdg_sram_ctrbits, rockchip_sram_stack);
476         }
477         else
478         {
479             dsb();
480             wfi();
481         }
482
483         pm_log = true;
484
485         rkpm_ddr_printch('5');
486
487         RKPM_BITCTR_DDR_FUN(GPIOS,re_gpios);
488
489         rkpm_ddr_printch('4');
490
491         RKPM_BITCTR_DDR_FUN(PLLS,re_plls);
492
493         rkpm_ddr_printch('3');
494
495         RKPM_BITCTR_DDR_FUN(GTCLKS,re_gtclks);
496         
497         rkpm_ddr_printch('2');
498         
499         RKPM_DDR_FUN(re_save_setting); 
500
501         local_fiq_enable();
502         rkpm_ddr_printch('1');
503         
504
505
506         RKPM_BITCTR_DDR_FUN(PWR_DMNS,re_pwr_dmns);
507
508         rkpm_ddr_printch('0');
509
510
511         pm_log = false;
512
513         printk(KERN_CONT "\n");
514
515         rkpm_ddr_printch('\n');
516
517         RKPM_DDR_FUN(finish);
518         
519         return 0;
520 }
521
522 static int rkpm_enter_tst(void)
523 {
524
525        return rkpm_enter(0);
526
527 }
528
529 static int rkpm_suspend_prepare(void)
530 {
531         /* disable entering idle by disable_hlt() */
532         //disable_hlt();
533         return 0;
534 }
535
536 static void rkpm_suspend_finish(void)
537 {
538         //enable_hlt();
539         
540         #if 0 //def CONFIG_KEYS_RK29
541         if(rkpm_check_ctrbits(1<<RKPM_CTR_WAKE_UP_KEY))
542         {
543                 rk28_send_wakeup_key();
544                 printk("rk30_pm_finish rk28_send_wakeup_key\n");
545         }
546         #endif
547 }
548
549
550 static struct platform_suspend_ops rockchip_suspend_ops = {
551         .enter          = rkpm_enter,
552         .valid          = suspend_valid_only_mem,
553         .prepare        = rkpm_suspend_prepare,
554         .finish         = rkpm_suspend_finish,
555 };
556 void __init rockchip_suspend_init(void)
557 {
558     //printk("%s\n",__FUNCTION__);
559     suspend_set_ops(&rockchip_suspend_ops);
560     return;
561 }
562
563 static enum rockchip_pm_policy pm_policy;
564 static BLOCKING_NOTIFIER_HEAD(policy_notifier_list);
565
566 int rockchip_pm_policy_register_notifier(struct notifier_block *nb)
567 {
568         return blocking_notifier_chain_register(&policy_notifier_list, nb);
569 }
570
571 int rockchip_pm_policy_unregister_notifier(struct notifier_block *nb)
572 {
573         return blocking_notifier_chain_unregister(&policy_notifier_list, nb);
574 }
575
576 static int rockchip_pm_policy_notify(void)
577 {
578         return blocking_notifier_call_chain(&policy_notifier_list,
579                         pm_policy, NULL);
580 }
581
582 enum rockchip_pm_policy rockchip_pm_get_policy(void)
583 {
584         return pm_policy;
585 }
586
587 int rockchip_pm_set_policy(enum rockchip_pm_policy policy)
588 {
589         if (policy < ROCKCHIP_PM_NR_POLICYS && policy != pm_policy) {
590                 printk(KERN_INFO "pm policy %d -> %d\n", pm_policy, policy);
591                 pm_policy = policy;
592                 rockchip_pm_policy_notify();
593         }
594
595         return 0;
596 }
597
598 static unsigned int policy;
599
600 static int set_policy(const char *val, const struct kernel_param *kp)
601 {
602         int ret;
603
604         ret = param_set_uint(val, kp);
605         if (ret < 0)
606                 return ret;
607
608         rockchip_pm_set_policy(policy);
609         policy = rockchip_pm_get_policy();
610
611         return 0;
612 }
613
614 static struct kernel_param_ops policy_param_ops = {
615         .set = set_policy,
616         .get = param_get_uint,
617 };
618
619 module_param_cb(policy, &policy_param_ops, &policy, 0600);