ARM: rockchip: support arch32 psci suspend
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / rockchip_pm.c
old mode 100644 (file)
new mode 100755 (executable)
index 0ae52e6..2ac0c61
@@ -5,7 +5,9 @@
 #include <asm/tlbflush.h>
 #include <asm/suspend.h>
 #include <linux/delay.h>
-
+#include <linux/moduleparam.h>
+#include <linux/rockchip/common.h>
+#include <asm/psci.h>
 #include <asm/io.h>
 #include "pm.h"
 
@@ -21,23 +23,32 @@ void rkpm_ddr_reg_offset_dump(void __iomem * base_addr,u32 _offset)
 void  rkpm_ddr_regs_dump(void __iomem * base_addr,u32 start_offset,u32 end_offset)
 {
        u32 i;
-        u32 line=0;
+        //u32 line=0;
 
         rkpm_ddr_printascii("start from:");     
-        rkpm_ddr_printhex((u32)(base_addr +start_offset));       
+       rkpm_ddr_printhex((unsigned long)base_addr + start_offset);
         rkpm_ddr_printch('\n');
+                   
         
        for(i=start_offset;i<=end_offset;)
        {
+         
             rkpm_ddr_printhex(reg_readl((base_addr + i)));  
-            line++;
-            if((line%4==0)||i==end_offset)
+            if(i%16==12) 
+            {   
                 rkpm_ddr_printch('\n');
-            else              
-                rkpm_ddr_printch('-');
-            i+=4;
+            }
+            else
+            {
+                    if(i!=end_offset)
+                    rkpm_ddr_printch('-');
+                    else                        
+                    rkpm_ddr_printch('\n');
+            }
+            i=i+4;
        } 
     
+    
 }
 
 static struct rkpm_ops pm_ops={NULL};
@@ -165,6 +176,12 @@ void rkpm_set_sram_ops_ddr(rkpm_ops_void_callback ddr,rkpm_ops_void_callback re_
         p_pm_sram_ops->re_ddr=re_ddr;
     }
 }
+
+void rkpm_set_sram_ops_bus(rkpm_ops_void_callback bus_idle_request)
+{
+       if (p_pm_sram_ops)
+               p_pm_sram_ops->bus_idle_request = bus_idle_request;
+}
 void rkpm_set_sram_ops_printch(rkpm_ops_printch_callback printch)
 {  
     if(p_pm_sram_ops)
@@ -172,28 +189,28 @@ void rkpm_set_sram_ops_printch(rkpm_ops_printch_callback printch)
 }
 
 /******************for user ************************/
-void inline rkpm_set_ctrbits(u32 bits)
+void rkpm_set_ctrbits(u32 bits)
 {      
        rkpm_ctrbits = bits;
        
 }
-void inline rkpm_add_ctrbits(u32 bits)
+void rkpm_add_ctrbits(u32 bits)
 {      
        rkpm_ctrbits |= bits;
        
 }
-u32  inline rkpm_get_ctrbits(void)
+u32 rkpm_get_ctrbits(void)
 {      
        return rkpm_ctrbits;
 }
 
-u32 inline  rkpm_chk_ctrbits(u32 bits)
+u32 rkpm_chk_ctrbits(u32 bits)
 {      
        return (rkpm_ctrbits&bits);
 }
 
 //clear
-void inline rkpm_clr_ctrbits(u32 bits)
+void rkpm_clr_ctrbits(u32 bits)
 {
        rkpm_ctrbits&=~bits;
 }
@@ -385,13 +402,42 @@ void  rkpm_ddr_printhex(unsigned int hex)
                hex <<= 4;
        }
 }
+
+#ifdef CONFIG_ARM_PSCI
+static bool psci_suspend_available(void)
+{
+       return (psci_ops.cpu_suspend != NULL);
+}
+#else
+static inline bool psci_suspend_available(void)
+{
+       return false;
+}
+#endif
+
+#ifdef CONFIG_ARM
+void rk_sram_suspend(void)
+{
+       RKPM_DDR_FUN(regs_pread);
+       rkpm_ddr_printascii("sram");
+       call_with_stack(p_suspend_pie_cb
+               , &rkpm_jdg_sram_ctrbits, rockchip_sram_stack);
+}
+
 static int rk_lpmode_enter(unsigned long arg)
 {
+#ifdef CONFIG_ARM_PSCI
+       const struct psci_power_state ps = {
+               .type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
+       };
 
+       if (psci_suspend_available())
+               return psci_ops.cpu_suspend(ps, virt_to_phys(cpu_resume));
+#endif
         //RKPM_DDR_PFUN(slp_setting(rkpm_jdg_sram_ctrbits),slp_setting); 
     
         RKPM_DDR_FUN(slp_setting); 
-                
+
         local_flush_tlb_all();
         flush_cache_all();
         outer_flush_all();
@@ -400,8 +446,8 @@ static int rk_lpmode_enter(unsigned long arg)
         //outer_inv_all();// ???
         //  l2x0_inv_all_pm(); //rk319x is not need
         flush_cache_all();
-        
-        rkpm_ddr_printch('d');
+
+        rkpm_ddr_printch('d');
 
         //rkpm_udelay(3*10);
 
@@ -412,23 +458,28 @@ static int rk_lpmode_enter(unsigned long arg)
        return 0;
 }
 
-
 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long));
+#endif /* CONFIG_ARM */
 
 static int rkpm_enter(suspend_state_t state)
 {
-        printk("%s\n",__FUNCTION__);
-
-        
+       //static u32 test_count=0;
+        // printk(KERN_DEBUG"pm: ");
+        printk("%s:\n",__FUNCTION__);
+        //printk("pm test times=%d\n",++test_count);
+
+#ifdef CONFIG_ARM_PSCI
+       if (psci_suspend_available()) {
+               cpu_suspend(0, rk_lpmode_enter);
+               return 0;
+       }
+#endif
         RKPM_DDR_FUN(prepare);   
         
-        printk(KERN_DEBUG "pm: ");
-
         rkpm_ctrbits_prepare();
          
-      //  if(rkpm_chk_jdg_ctrbits(RKPM_CTR_RET_DIRT))
-      //  return 0;
+        //  if(rkpm_chk_jdg_ctrbits(RKPM_CTR_RET_DIRT))
+        //  return 0;
       
         rkpm_ddr_printch('0');
 
@@ -456,14 +507,13 @@ static int rkpm_enter(suspend_state_t state)
 
         rkpm_ddr_printch('5');
 
-        pm_log = false;
-
+#ifdef CONFIG_ARM
         if(rkpm_chk_jdg_ctrbits(RKPM_CTRBITS_SOC_DLPMD))
         {   
             if(cpu_suspend(0,rk_lpmode_enter)==0)
             {
                 RKPM_DDR_FUN(slp_re_first);
-                rkpm_ddr_printch('D');
+               rkpm_ddr_printch('K');
                 //rk_soc_pm_ctr_bits_prepare();
             }                        
             rkpm_ddr_printch('d');          
@@ -477,8 +527,10 @@ static int rkpm_enter(suspend_state_t state)
             dsb();
             wfi();
         }
-
-        pm_log = true;
+#else
+       flush_cache_all();
+       cpu_suspend(1);
+#endif
 
         rkpm_ddr_printch('5');
 
@@ -499,30 +551,23 @@ static int rkpm_enter(suspend_state_t state)
         local_fiq_enable();
         rkpm_ddr_printch('1');
         
-
-
         RKPM_BITCTR_DDR_FUN(PWR_DMNS,re_pwr_dmns);
 
         rkpm_ddr_printch('0');
-
-
-        pm_log = false;
-
-        printk(KERN_CONT "\n");
-
         rkpm_ddr_printch('\n');
-
-        RKPM_DDR_FUN(finish);
         
+        RKPM_DDR_FUN(finish);           
         return 0;
 }
 
+#if 0
 static int rkpm_enter_tst(void)
 {
 
        return rkpm_enter(0);
 
 }
+#endif
 
 static int rkpm_suspend_prepare(void)
 {
@@ -558,4 +603,69 @@ void __init rockchip_suspend_init(void)
     return;
 }
 
+#ifndef CONFIG_ARM
+static int __init rockchip_init_suspend(void)
+{
+       suspend_set_ops(&rockchip_suspend_ops);
+       return 0;
+}
+late_initcall_sync(rockchip_init_suspend);
+#endif /* CONFIG_ARM */
+
+static enum rockchip_pm_policy pm_policy;
+static BLOCKING_NOTIFIER_HEAD(policy_notifier_list);
+
+int rockchip_pm_policy_register_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&policy_notifier_list, nb);
+}
+
+int rockchip_pm_policy_unregister_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&policy_notifier_list, nb);
+}
+
+static int rockchip_pm_policy_notify(void)
+{
+       return blocking_notifier_call_chain(&policy_notifier_list,
+                       pm_policy, NULL);
+}
+
+enum rockchip_pm_policy rockchip_pm_get_policy(void)
+{
+       return pm_policy;
+}
+
+int rockchip_pm_set_policy(enum rockchip_pm_policy policy)
+{
+       if (policy < ROCKCHIP_PM_NR_POLICYS && policy != pm_policy) {
+               printk(KERN_INFO "pm policy %d -> %d\n", pm_policy, policy);
+               pm_policy = policy;
+               rockchip_pm_policy_notify();
+       }
+
+       return 0;
+}
+
+static unsigned int policy;
+
+static int set_policy(const char *val, const struct kernel_param *kp)
+{
+       int ret;
+
+       ret = param_set_uint(val, kp);
+       if (ret < 0)
+               return ret;
+
+       rockchip_pm_set_policy(policy);
+       policy = rockchip_pm_get_policy();
+
+       return 0;
+}
+
+static struct kernel_param_ops policy_param_ops = {
+       .set = set_policy,
+       .get = param_get_uint,
+};
 
+module_param_cb(policy, &policy_param_ops, &policy, 0600);