obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o ddr.o sram.o
+obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_RK29_VPU) += vpu.o vpu_mem.o
obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o
#include <mach/pmu.h>
-/* CRU PLL CON */
-#define PLL_HIGH_BAND (0x01 << 16)
-#define PLL_LOW_BAND (0x00 << 16)
-#define PLL_PD (0x01 << 15)
-
-#define PLL_CLKR(i) ((((i) - 1) & 0x1f) << 10)
-#define PLL_NR(v) ((((v) >> 10) & 0x1f) + 1)
-
-#define PLL_CLKF(i) ((((i) - 1) & 0x7f) << 3)
-#define PLL_NF(v) ((((v) >> 3) & 0x7f) + 1)
-#define PLL_NF2(v) (((((v) >> 3) & 0x7f) + 1) << 1)
-
-#define PLL_CLKOD(i) (((i) & 0x03) << 1)
-#define PLL_NO_1 PLL_CLKOD(0)
-#define PLL_NO_2 PLL_CLKOD(1)
-#define PLL_NO_4 PLL_CLKOD(2)
-#define PLL_NO_8 PLL_CLKOD(3)
-#define PLL_NO_SHIFT(v) (((v) >> 1) & 0x03)
-
-#define PLL_BYPASS (0x01)
-
-/* CRU MODE CON */
-#define CRU_CPU_MODE_MASK (0x03u << 0)
-#define CRU_CPU_MODE_SLOW (0x00u << 0)
-#define CRU_CPU_MODE_NORMAL (0x01u << 0)
-#define CRU_CPU_MODE_SLOW27 (0x02u << 0)
-
-#define CRU_GENERAL_MODE_MASK (0x03u << 2)
-#define CRU_GENERAL_MODE_SLOW (0x00u << 2)
-#define CRU_GENERAL_MODE_NORMAL (0x01u << 2)
-#define CRU_GENERAL_MODE_SLOW27 (0x02u << 2)
-
-#define CRU_CODEC_MODE_MASK (0x03u << 4)
-#define CRU_CODEC_MODE_SLOW (0x00u << 4)
-#define CRU_CODEC_MODE_NORMAL (0x01u << 4)
-#define CRU_CODEC_MODE_SLOW27 (0x02u << 4)
-
-#define CRU_DDR_MODE_MASK (0x03u << 6)
-#define CRU_DDR_MODE_SLOW (0x00u << 6)
-#define CRU_DDR_MODE_NORMAL (0x01u << 6)
-#define CRU_DDR_MODE_SLOW27 (0x02u << 6)
-
/* Clock flags */
/* bit 0 is free */
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
static int codec_pll_clk_mode(struct clk *clk, int on)
{
+ u32 cpll = cru_readl(CRU_CPLL_CON);
if (on) {
- cru_writel(cru_readl(CRU_CPLL_CON) & ~PLL_PD, CRU_CPLL_CON);
+ cru_writel(cpll & ~(PLL_PD | PLL_BYPASS), CRU_CPLL_CON);
delay_300us();
pll_wait_lock(CODEC_PLL_IDX);
cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_NORMAL, CRU_MODE_CON);
} else {
cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_SLOW, CRU_MODE_CON);
- cru_writel(cru_readl(CRU_CPLL_CON) | PLL_PD, CRU_CPLL_CON);
+ cru_writel(cpll | PLL_BYPASS, CRU_CPLL_CON);
+ cru_writel(cpll | PLL_PD | PLL_BYPASS, CRU_CPLL_CON);
delay_500ns();
}
return 0;
/* codec pll */
clk_set_rate_nolock(&codec_pll_clk, 552 * MHZ);
clk_set_parent_nolock(&clk_gpu, &codec_pll_clk);
- clk_set_parent_nolock(&clk_mac_ref_div, &codec_pll_clk);
/* arm pll */
clk_set_rate_nolock(&arm_pll_clk, armclk);
+ clk_set_parent_nolock(&clk_mac_ref_div, &arm_pll_clk);
}
static void __init clk_enable_init_clocks(void)
*
*/
+#ifdef CONFIG_CPU_FREQ_DEBUG
+#define DEBUG
+#endif
+#define pr_fmt(fmt) "cpufreq: %s: " fmt, __func__
+
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+
+#define SLEEP_FREQ (800 * 1000) /* Use 800MHz when entering sleep */
+
+/* additional symantics for "relation" in cpufreq with pm */
+#define DISABLE_FURTHER_CPUFREQ 0x10
+#define ENABLE_FURTHER_CPUFREQ 0x20
+#define MASK_FURTHER_CPUFREQ 0x30
+/* With 0x00(NOCHANGE), it depends on the previous "further" status */
+static int no_cpufreq_access;
static struct cpufreq_frequency_table freq_table[] = {
// { .index = 950000, .frequency = 204000 },
if (policy->cpu != 0)
return -EINVAL;
+
+ if ((relation & ENABLE_FURTHER_CPUFREQ) &&
+ (relation & DISABLE_FURTHER_CPUFREQ)) {
+ /* Invalidate both if both marked */
+ relation &= ~ENABLE_FURTHER_CPUFREQ;
+ relation &= ~DISABLE_FURTHER_CPUFREQ;
+ pr_err("denied marking FURTHER_CPUFREQ as both marked.\n");
+ }
+ if (relation & ENABLE_FURTHER_CPUFREQ)
+ no_cpufreq_access--;
+ if (no_cpufreq_access) {
+#ifdef CONFIG_PM_VERBOSE
+ pr_err("denied access to %s as it is disabled temporarily\n", __func__);
+#endif
+ return -EINVAL;
+ }
+ if (relation & DISABLE_FURTHER_CPUFREQ)
+ no_cpufreq_access++;
+ relation &= ~MASK_FURTHER_CPUFREQ;
+
if (cpufreq_frequency_table_target(policy, freq_table, target_freq, relation, &index)) {
- pr_err("cpufreq: invalid target_freq: %d\n", target_freq);
+ pr_err("invalid target_freq: %d\n", target_freq);
return -EINVAL;
}
freq = &freq_table[index];
freqs.old = policy->cur;
freqs.new = freq->frequency;
freqs.cpu = 0;
-#ifdef CONFIG_CPU_FREQ_DEBUG
- printk(KERN_DEBUG "%s %d r %d (%d-%d) selected %d (%duV)\n", __func__, target_freq, relation, policy->min, policy->max, freq->frequency, freq->index);
-#endif
+ pr_debug("%d r %d (%d-%d) selected %d (%duV)\n", target_freq, relation, policy->min, policy->max, freq->frequency, freq->index);
#ifdef CONFIG_REGULATOR
if (vcore && freqs.new > freqs.old) {
err = regulator_set_voltage(vcore, freq->index, freq->index);
if (err) {
- pr_err("cpufreq: fail to set vcore (%duV) for %dkHz: %d\n",
+ pr_err("fail to set vcore (%duV) for %dkHz: %d\n",
freq->index, freqs.new, err);
goto err_vol;
}
if (vcore && freqs.new < freqs.old) {
err = regulator_set_voltage(vcore, freq->index, freq->index);
if (err) {
- pr_err("cpufreq: fail to set vcore (%duV) for %dkHz: %d\n",
+ pr_err("fail to set vcore (%duV) for %dkHz: %d\n",
freq->index, freqs.new, err);
}
}
#ifdef CONFIG_REGULATOR
vcore = regulator_get(NULL, "vcore");
if (IS_ERR(vcore)) {
- pr_err("cpufreq: fail to get regulator vcore: %ld\n", PTR_ERR(vcore));
+ pr_err("fail to get regulator vcore: %ld\n", PTR_ERR(vcore));
vcore = NULL;
}
#endif
.attr = rk29_cpufreq_attr,
};
+static int rk29_cpufreq_pm_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int ret;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ DISABLE_FURTHER_CPUFREQ);
+ if (ret < 0)
+ return NOTIFY_BAD;
+ return NOTIFY_OK;
+ case PM_POST_RESTORE:
+ case PM_POST_SUSPEND:
+ cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ ENABLE_FURTHER_CPUFREQ);
+ return NOTIFY_OK;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rk29_cpufreq_pm_notifier = {
+ .notifier_call = rk29_cpufreq_pm_notifier_event,
+};
+
static int __init rk29_cpufreq_register(void)
{
+ register_pm_notifier(&rk29_cpufreq_pm_notifier);
+
return cpufreq_register_driver(&rk29_cpufreq_driver);
}
CLK_GATE_MAX,
};
+enum cru_soft_reset {
+ SOFT_RST_ARM_CORE = 0,
+ SOFT_RST_CPU_SYSTEM_INTERCONNECT_1_AXI,
+ SOFT_RST_CPU_SYSTEM_INTERCONNECT_1_AHB,
+ SOFT_RST_CPU_SYSTEM_INTERCONNECT_1_APB,
+ SOFT_RST_CPU_SYSTEM_INTERCONNECT_1_ATB,
+ SOFT_RST_CPU_SYSTEM_INTERCONNECT_2,
+ SOFT_RST_DMA0 = 7,
+ SOFT_RST_GIC,
+ SOFT_RST_INTERNAL_MEMORY,
+ SOFT_RST_TZPC = 11,
+ SOFT_RST_ROM,
+ SOFT_RST_I2S0,
+ SOFT_RST_I2S1,
+ SOFT_RST_SPDIF,
+ SOFT_RST_UART0,
+ SOFT_RST_RTC,
+ SOFT_RST_DDR_PHY,
+ SOFT_RST_DDR_DLL_BYTE0,
+ SOFT_RST_DDR_DLL_BYTE1,
+ SOFT_RST_DDR_DLL_BYTE2,
+ SOFT_RST_DDR_DLL_BYTE3,
+ SOFT_RST_DDR_DLL_CMD,
+ SOFT_RST_DDR_CONTROLLER,
+ SOFT_RST_ARM_CORE_DEBUG,
+ SOFT_RST_DAP_DBG,
+ SOFT_RST_CPU_VODEC_A2A_AHB,
+ SOFT_RST_CPU_DISPLAY_A2A_AHB,
+ SOFT_RST_DAP_SYS,
+
+ SOFT_RST_PERI_SYSTEM_INTERCONNECT_1_AXI = 32,
+ SOFT_RST_PERI_SYSTEM_INTERCONNECT_1_AHB,
+ SOFT_RST_PERI_SYSTEM_INTERCONNECT_1_APB,
+ SOFT_RST_PERIPH_EMEM = 32 + 4,
+ SOFT_RST_PERIPH_USB,
+ SOFT_RST_DMA1,
+ SOFT_RST_MAC,
+ SOFT_RST_HIF,
+ SOFT_RST_NANDC,
+ SOFT_RST_SMC,
+ SOFT_RST_HSADC,
+ SOFT_RST_SDMMC,
+ SOFT_RST_SDIO,
+ SOFT_RST_EMMC,
+ SOFT_RST_USB_OTG_2_0_AHB_BUS,
+ SOFT_RST_USB_OTG_2_0_PHY,
+ SOFT_RST_USB_OTG_2_0_CONTROLLER,
+ SOFT_RST_USB_HOST_2_0_AHB_BUS,
+ SOFT_RST_USB_HOST_2_0_PHY,
+ SOFT_RST_USB_HOST_2_0_CONTROLLER,
+ SOFT_RST_UHOST,
+ SOFT_RST_VIP,
+ SOFT_RST_VIP_MATRIX_AHB,
+ SOFT_RST_SPI0,
+ SOFT_RST_SPI1,
+ SOFT_RST_SARADC,
+ SOFT_RST_UART1,
+ SOFT_RST_UART2,
+ SOFT_RST_UART3,
+ SOFT_RST_PWM,
+
+ SOFT_RST_DISPLAY_INTERCONNECTOR_AXI = 64,
+ SOFT_RST_DISPLAY_INTERCONNECTOR_AHB,
+ SOFT_RST_LCDC,
+ SOFT_RST_IPP,
+ SOFT_RST_EBC,
+ SOFT_RST_GPU = 64 + 7,
+ SOFT_RST_DDR_REG_PORT,
+ SOFT_RST_DDR_CPU_PORT,
+ SOFT_RST_PERIPH_USED_CPU_AXI,
+ SOFT_RST_DDR_PERIPH_PORT,
+ SOFT_RST_DDR_LCDC_PORT,
+ SOFT_RST_DDR_VCODEC_PORT = 64 + 15,
+ SOFT_RST_DDR_GPU_PORT,
+ SOFT_RST_PID_FILTER_AHB,
+ SOFT_RST_VCODEC_AXI_BUS,
+ SOFT_RST_VCODEC_AHB_BUS,
+ SOFT_RST_TIMER0,
+ SOFT_RST_TIMER1,
+ SOFT_RST_TIMER2,
+ SOFT_RST_TIMER3,
+
+ SOFT_RST_MAX,
+};
+
+/* CRU MODE CON */
+#define CRU_CPU_MODE_MASK (0x03u << 0)
+#define CRU_CPU_MODE_SLOW (0x00u << 0)
+#define CRU_CPU_MODE_NORMAL (0x01u << 0)
+#define CRU_CPU_MODE_SLOW27 (0x02u << 0)
+
+#define CRU_GENERAL_MODE_MASK (0x03u << 2)
+#define CRU_GENERAL_MODE_SLOW (0x00u << 2)
+#define CRU_GENERAL_MODE_NORMAL (0x01u << 2)
+#define CRU_GENERAL_MODE_SLOW27 (0x02u << 2)
+
+#define CRU_CODEC_MODE_MASK (0x03u << 4)
+#define CRU_CODEC_MODE_SLOW (0x00u << 4)
+#define CRU_CODEC_MODE_NORMAL (0x01u << 4)
+#define CRU_CODEC_MODE_SLOW27 (0x02u << 4)
+
+#define CRU_DDR_MODE_MASK (0x03u << 6)
+#define CRU_DDR_MODE_SLOW (0x00u << 6)
+#define CRU_DDR_MODE_NORMAL (0x01u << 6)
+#define CRU_DDR_MODE_SLOW27 (0x02u << 6)
+
+/* CRU PLL CON */
+#define PLL_HIGH_BAND (0x01 << 16)
+#define PLL_LOW_BAND (0x00 << 16)
+#define PLL_PD (0x01 << 15)
+
+#define PLL_CLKR(i) ((((i) - 1) & 0x1f) << 10)
+#define PLL_NR(v) ((((v) >> 10) & 0x1f) + 1)
+
+#define PLL_CLKF(i) ((((i) - 1) & 0x7f) << 3)
+#define PLL_NF(v) ((((v) >> 3) & 0x7f) + 1)
+#define PLL_NF2(v) (((((v) >> 3) & 0x7f) + 1) << 1)
+
+#define PLL_CLKOD(i) (((i) & 0x03) << 1)
+#define PLL_NO_1 PLL_CLKOD(0)
+#define PLL_NO_2 PLL_CLKOD(1)
+#define PLL_NO_4 PLL_CLKOD(2)
+#define PLL_NO_8 PLL_CLKOD(3)
+#define PLL_NO_SHIFT(v) (((v) >> 1) & 0x03)
+
+#define PLL_BYPASS (0x01)
+
/* Register definitions */
#define CRU_APLL_CON 0x00
#define CRU_DPLL_CON 0x04
#define CRU_SOFTRST1_CON 0x70
#define CRU_SOFTRST2_CON 0x74
+static inline void cru_set_soft_reset(enum cru_soft_reset idx, bool on)
+{
+ unsigned long flags;
+ u32 addr = RK29_CRU_BASE + CRU_SOFTRST0_CON + ((idx >> 5) << 2);
+ u32 mask = 1 << (idx & 31);
+ u32 v;
+
+ if (idx >= SOFT_RST_MAX)
+ return;
+
+ local_irq_save(flags);
+ v = readl(addr);
+ if (on)
+ v |= mask;
+ else
+ v &= ~mask;
+ writel(v, addr);
+ local_irq_restore(flags);
+}
+
#endif
--- /dev/null
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/regulator/consumer.h>
+#include <linux/io.h>
+#include <linux/wakelock.h>
+
+#include <mach/rk29_iomap.h>
+#include <mach/cru.h>
+#include <mach/pmu.h>
+#include <mach/board.h>
+#include <mach/system.h>
+#include <mach/sram.h>
+
+#define cru_readl(offset) readl(RK29_CRU_BASE + offset)
+#define cru_writel(v, offset) do { writel(v, RK29_CRU_BASE + offset); readl(RK29_CRU_BASE + offset); } while (0)
+#define pmu_readl(offset) readl(RK29_PMU_BASE + offset)
+#define pmu_writel(v, offset) do { writel(v, RK29_PMU_BASE + offset); readl(RK29_PMU_BASE + offset); } while (0)
+static unsigned long save_sp;
+
+static inline void delay_500ns(void)
+{
+ int delay = 12;
+ while (delay--)
+ barrier();
+}
+
+static inline void delay_300us(void)
+{
+ int i;
+ for (i = 0; i < 600; i++)
+ delay_500ns();
+}
+
+static u32 apll;
+static u32 lpj;
+static struct regulator *vcore;
+static int vcore_uV;
+
+extern void ddr_suspend(void);
+extern void ddr_resume(void);
+
+static void __sramfunc rk29_pm_enter_ddr(void)
+{
+ u32 clksel0, dpll, mode;
+
+ asm("dsb");
+ ddr_suspend();
+
+ /* suspend ddr pll */
+ mode = cru_readl(CRU_MODE_CON);
+ dpll = cru_readl(CRU_DPLL_CON);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_DDR_MODE_MASK) | CRU_DDR_MODE_SLOW, CRU_MODE_CON);
+ cru_writel(dpll | PLL_BYPASS, CRU_DPLL_CON);
+ cru_writel(dpll | PLL_PD | PLL_BYPASS, CRU_DPLL_CON);
+ delay_500ns();
+
+ /* set arm clk 24MHz/32 = 750KHz */
+ clksel0 = cru_readl(CRU_CLKSEL0_CON);
+ cru_writel(clksel0 | 0x1F, CRU_CLKSEL0_CON);
+
+ asm("wfi");
+
+ /* resume arm clk */
+ cru_writel(clksel0, CRU_CLKSEL0_CON);
+
+ /* resume ddr pll */
+ cru_writel(dpll, CRU_DPLL_CON);
+ delay_300us();
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_DDR_MODE_MASK) | (mode & CRU_DDR_MODE_MASK), CRU_MODE_CON);
+
+ ddr_resume();
+}
+
+static int rk29_pm_enter(suspend_state_t state)
+{
+ u32 cpll, gpll, mode;
+
+ mode = cru_readl(CRU_MODE_CON);
+
+ /* suspend codec pll */
+ cpll = cru_readl(CRU_CPLL_CON);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_SLOW, CRU_MODE_CON);
+ cru_writel(cpll | PLL_BYPASS, CRU_CPLL_CON);
+ cru_writel(cpll | PLL_PD | PLL_BYPASS, CRU_CPLL_CON);
+ delay_500ns();
+
+ /* suspend general pll */
+ gpll = cru_readl(CRU_GPLL_CON);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | CRU_GENERAL_MODE_SLOW, CRU_MODE_CON);
+ cru_writel(gpll | PLL_BYPASS, CRU_GPLL_CON);
+ cru_writel(gpll | PLL_PD | PLL_BYPASS, CRU_GPLL_CON);
+ delay_500ns();
+
+ DDR_SAVE_SP(save_sp);
+ rk29_pm_enter_ddr();
+ DDR_RESTORE_SP(save_sp);
+
+ /* resume general pll */
+ cru_writel(gpll, CRU_GPLL_CON);
+ delay_300us();
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | (mode & CRU_GENERAL_MODE_MASK), CRU_MODE_CON);
+
+ /* resume codec pll */
+ cru_writel(cpll, CRU_CPLL_CON);
+ delay_300us();
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | (mode & CRU_CODEC_MODE_MASK), CRU_MODE_CON);
+
+ return 0;
+}
+
+static int rk29_pm_prepare(void)
+{
+ printk("+%s\n", __func__);
+ disable_hlt(); // disable entering rk29_idle() by disable_hlt()
+
+ /* suspend arm pll */
+ apll = cru_readl(CRU_APLL_CON);
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON);
+ cru_writel(apll | PLL_BYPASS, CRU_APLL_CON);
+ cru_writel(apll | PLL_PD | PLL_BYPASS, CRU_APLL_CON);
+ delay_500ns();
+ lpj = loops_per_jiffy;
+ loops_per_jiffy = 120000; // make udelay/mdelay correct
+
+ if (vcore) {
+ vcore_uV = regulator_get_voltage(vcore);
+ regulator_set_voltage(vcore, 1000000, 1000000);
+ }
+ printk("-%s\n", __func__);
+ return 0;
+}
+
+static void rk29_pm_finish(void)
+{
+ printk("+%s\n", __func__);
+ if (vcore) {
+ regulator_set_voltage(vcore, vcore_uV, vcore_uV);
+ }
+
+ /* resume arm pll */
+ loops_per_jiffy = lpj;
+ cru_writel(apll, CRU_APLL_CON);
+ delay_300us();
+ cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_NORMAL, CRU_MODE_CON);
+
+ enable_hlt();
+ printk("-%s\n", __func__);
+}
+
+static struct platform_suspend_ops rk29_pm_ops = {
+ .enter = rk29_pm_enter,
+ .valid = suspend_valid_only_mem,
+ .prepare = rk29_pm_prepare,
+ .finish = rk29_pm_finish,
+};
+
+static void rk29_idle(void)
+{
+ if (!need_resched()) {
+ int allow_sleep = 1;
+#ifdef CONFIG_HAS_WAKELOCK
+ allow_sleep = !has_wake_lock(WAKE_LOCK_IDLE);
+#endif
+ if (allow_sleep) {
+ u32 mode_con = cru_readl(CRU_MODE_CON);
+ cru_writel((mode_con & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON);
+ arch_idle();
+ cru_writel((mode_con & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_NORMAL, CRU_MODE_CON);
+ } else {
+ arch_idle();
+ }
+ }
+ local_irq_enable();
+}
+
+static int __init rk29_pm_init(void)
+{
+ vcore = regulator_get(NULL, "vcore");
+ if (IS_ERR(vcore)) {
+ pr_err("pm: fail to get regulator vcore: %ld\n", PTR_ERR(vcore));
+ vcore = NULL;
+ }
+
+ suspend_set_ops(&rk29_pm_ops);
+
+ /* set idle function */
+ pm_idle = rk29_idle;
+
+ return 0;
+}
+__initcall(rk29_pm_init);