#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"
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};
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)
}
/******************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;
}
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();
//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);
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');
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');
dsb();
wfi();
}
-
- pm_log = true;
+#else
+ flush_cache_all();
+ cpu_suspend(1);
+#endif
rkpm_ddr_printch('5');
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)
{
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);