464667b9e5879cbf241e88625b7f049ea33535de
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk30 / pm.c
1 #include <linux/clk.h>
2 #include <linux/delay.h>
3 #include <linux/err.h>
4 #include <linux/kernel.h>
5 #include <linux/init.h>
6 #include <linux/pm.h>
7 #include <linux/suspend.h>
8 #include <linux/random.h>
9 #include <linux/crc32.h>
10 #include <linux/io.h>
11 #include <linux/wakelock.h>
12 #include <asm/cacheflush.h>
13 #include <asm/tlbflush.h>
14 #include <asm/hardware/cache-l2x0.h>
15 #include <asm/hardware/gic.h>
16
17 #include <mach/pmu.h>
18 #include <mach/board.h>
19 #include <mach/system.h>
20 #include <mach/sram.h>
21 #include <mach/gpio.h>
22 #include <mach/iomux.h>
23 #include <mach/cru.h>
24 #include <mach/ddr.h>
25
26 #define cru_readl(offset)       readl_relaxed(RK30_CRU_BASE + offset)
27 #define cru_writel(v, offset)   do { writel_relaxed(v, RK30_CRU_BASE + offset); dsb(); } while (0)
28
29 #define pmu_readl(offset)       readl_relaxed(RK30_PMU_BASE + offset)
30 #define pmu_writel(v,offset)    do { writel_relaxed(v, RK30_PMU_BASE + offset); dsb(); } while (0)
31
32 #define grf_readl(offset)       readl_relaxed(RK30_GRF_BASE + offset)
33 #define grf_writel(v, offset)   do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0)
34
35 #define gate_save_soc_clk(val,_save,cons,w_msk) \
36         (_save)=cru_readl(cons);\
37         cru_writel((((~(val)|(_save))&(w_msk))|((w_msk)<<16)),cons)
38
39 void __sramfunc sram_printch(char byte)
40 {
41 #ifdef DEBUG_UART_BASE
42         u32 clk_gate2, clk_gate4, clk_gate8;
43
44         gate_save_soc_clk(0
45                           | (1 << CLK_GATE_ACLK_PEIRPH % 16)
46                           | (1 << CLK_GATE_HCLK_PEIRPH % 16)
47                           | (1 << CLK_GATE_PCLK_PEIRPH % 16)
48                           , clk_gate2, CRU_CLKGATES_CON(2), 0
49                           | (1 << ((CLK_GATE_ACLK_PEIRPH % 16) + 16))
50                           | (1 << ((CLK_GATE_HCLK_PEIRPH % 16) + 16))
51                           | (1 << ((CLK_GATE_PCLK_PEIRPH % 16) + 16)));
52         gate_save_soc_clk((1 << CLK_GATE_ACLK_CPU_PERI % 16)
53                           , clk_gate4, CRU_CLKGATES_CON(4),
54                           (1 << ((CLK_GATE_ACLK_CPU_PERI % 16) + 16)));
55         gate_save_soc_clk((1 << ((CLK_GATE_PCLK_UART0 + CONFIG_RK_DEBUG_UART) % 16)),
56                           clk_gate8, CRU_CLKGATES_CON(8),
57                           (1 << (((CLK_GATE_PCLK_UART0 + CONFIG_RK_DEBUG_UART) % 16) + 16)));
58         sram_udelay(1);
59
60         writel_relaxed(byte, DEBUG_UART_BASE);
61         dsb();
62
63         /* loop check LSR[6], Transmitter Empty bit */
64         while (!(readl_relaxed(DEBUG_UART_BASE + 0x14) & 0x40))
65                 barrier();
66
67         cru_writel(0xffff0000 | clk_gate2, CRU_CLKGATES_CON(2));
68         cru_writel(0xffff0000 | clk_gate4, CRU_CLKGATES_CON(4));
69         cru_writel(0xffff0000 | clk_gate8, CRU_CLKGATES_CON(8));
70
71         if (byte == '\n')
72                 sram_printch('\r');
73 #endif
74 }
75
76 #ifdef CONFIG_DDR_TEST
77 static int ddr_debug=0;
78 module_param(ddr_debug, int, 0644);
79
80 static int inline calc_crc32(u32 addr, size_t len)
81 {
82         return crc32_le(~0, (const unsigned char *)addr, len);
83 }
84
85 extern __sramdata uint32_t mem_type;
86 static void __sramfunc ddr_testmode(void)
87 {
88         int32_t g_crc1, g_crc2;
89         uint32_t nMHz;
90         uint32_t n = 0;
91         uint32_t min,max;
92         extern char _stext[], _etext[];
93
94
95         if (ddr_debug == 1) {
96             switch(mem_type)
97             {
98                 case 0:  //LPDDR
99                 case 1:  //DDR
100                     max = 210;
101                     min = 100;
102                     break;
103                 case 2:  //DDR2
104                 case 4:  //LPDDR2
105                     max=410;
106                     min=100;
107                     break;
108                 case 3:  //DDR3
109                 default:
110                     max=500;
111                     min=100;
112                     break;
113             }
114                 for (;;) {
115                         sram_printascii("\n change freq:");
116                         g_crc1 = calc_crc32((u32)_stext, (size_t)(_etext-_stext));
117                         do
118                         {
119                             nMHz = min + random32();
120                             nMHz %= max;
121                         }while(nMHz < min);
122                         sram_printhex(nMHz);
123                         sram_printch(' ');
124                         nMHz = ddr_change_freq(nMHz);                   
125                         sram_printhex(n++);
126                         sram_printch(' ');
127                         g_crc2 = calc_crc32((u32)_stext, (size_t)(_etext-_stext));
128                         if (g_crc1!=g_crc2) {
129                                 sram_printascii("fail\n");
130                         }
131                         //ddr_print("check image crc32 success--crc value = 0x%x!, count:%d\n",g_crc1, n++);
132                         //     sram_printascii("change freq success\n");
133                 }
134         } else if(ddr_debug == 2) {
135                 for (;;) {
136                         sram_printch(' ');
137                         sram_printch('9');
138                         sram_printch('9');
139                         sram_printch('9');
140                         sram_printch(' ');
141                         g_crc1 = calc_crc32((u32)_stext, (size_t)(_etext-_stext));
142                         nMHz = (random32()>>13);// 16.7s max
143                         ddr_suspend();
144                         sram_udelay(nMHz);
145                         ddr_resume();
146                         sram_printhex(nMHz);
147                         sram_printch(' ');
148                         sram_printhex(n++);
149                         g_crc2 = calc_crc32((u32)_stext, (size_t)(_etext-_stext));
150                         if (g_crc1 != g_crc2) {
151                                 sram_printch(' ');
152                                 sram_printch('f');
153                                 sram_printch('a');
154                                 sram_printch('i');
155                                 sram_printch('l');
156                         }
157                         // ddr_print("check image crc32 fail!, count:%d\n", n++);
158                         //    sram_printascii("self refresh fail\n");
159                         //else
160                         //ddr_print("check image crc32 success--crc value = 0x%x!, count:%d\n",g_crc1, n++);
161                         //    sram_printascii("self refresh success\n");
162                 }
163         } else if (ddr_debug == 3) {
164                 extern int memtester(void);
165                 memtester();
166         }
167         else
168         {
169             ddr_change_freq(ddr_debug);
170             ddr_debug=0;
171         }
172 }
173 #else
174 static void __sramfunc ddr_testmode(void) {}
175 #endif
176
177 static noinline void rk30_pm_dump_irq(void)
178 {
179         u32 irq_gpio = (readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 8) >> 22) & 0x7F;
180         printk("wakeup irq: %08x %08x %08x %08x\n",
181                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 4),
182                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 8),
183                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 12),
184                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 16));
185         if (irq_gpio & 1)
186                 printk("wakeup gpio0: %08x\n", readl_relaxed(RK30_GPIO0_BASE + GPIO_INT_STATUS));
187         if (irq_gpio & 2)
188                 printk("wakeup gpio1: %08x\n", readl_relaxed(RK30_GPIO1_BASE + GPIO_INT_STATUS));
189         if (irq_gpio & 4)
190                 printk("wakeup gpio2: %08x\n", readl_relaxed(RK30_GPIO2_BASE + GPIO_INT_STATUS));
191         if (irq_gpio & 8)
192                 printk("wakeup gpio3: %08x\n", readl_relaxed(RK30_GPIO3_BASE + GPIO_INT_STATUS));
193         if (irq_gpio & 0x10)
194                 printk("wakeup gpio4: %08x\n", readl_relaxed(RK30_GPIO4_BASE + GPIO_INT_STATUS));
195         if (irq_gpio & 0x40)
196                 printk("wakeup gpio6: %08x\n", readl_relaxed(RK30_GPIO6_BASE + GPIO_INT_STATUS));
197 }
198
199 #define DUMP_GPIO_INTEN(ID) \
200 do { \
201         u32 en = readl_relaxed(RK30_GPIO##ID##_BASE + GPIO_INTEN); \
202         if (en) { \
203                 sram_printascii("GPIO" #ID "_INTEN: "); \
204                 sram_printhex(en); \
205                 sram_printch('\n'); \
206         } \
207 } while (0)
208
209 static noinline void rk30_pm_dump_inten(void)
210 {
211         DUMP_GPIO_INTEN(0);
212         DUMP_GPIO_INTEN(1);
213         DUMP_GPIO_INTEN(2);
214         DUMP_GPIO_INTEN(3);
215         DUMP_GPIO_INTEN(4);
216         DUMP_GPIO_INTEN(6);
217 }
218
219 static void pm_pll_wait_lock(int pll_idx)
220 {
221         u32 pll_state[4] = { 1, 0, 2, 3 };
222         u32 bit = 0x10u << pll_state[pll_idx];
223         u32 delay = pll_idx == APLL_ID ? 24000000U : 2400000000U;
224         while (delay > 0) {
225                 if (grf_readl(GRF_SOC_STATUS0) & bit)
226                         break;
227                 delay--;
228         }
229         if (delay == 0) {
230                 //CRU_PRINTK_ERR("wait pll bit 0x%x time out!\n", bit); 
231                 sram_printch('p');
232                 sram_printch('l');
233                 sram_printch('l');
234                 sram_printhex(pll_idx);
235                 sram_printch('\n');
236         }
237 }
238
239 #define power_on_pll(id) \
240         cru_writel(PLL_PWR_DN_W_MSK|PLL_PWR_ON,PLL_CONS((id),3));\
241         pm_pll_wait_lock((id))
242
243 #define DDR_SAVE_SP(save_sp)            do { save_sp = ddr_save_sp(((unsigned long)SRAM_DATA_END & (~7))); } while (0)
244 #define DDR_RESTORE_SP(save_sp)         do { ddr_save_sp(save_sp); } while (0)
245
246 static unsigned long save_sp;
247
248 static noinline void interface_ctr_reg_pread(void)
249 {
250         u32 addr;
251
252         flush_cache_all();
253         outer_flush_all();
254         local_flush_tlb_all();
255
256         for (addr = (u32)SRAM_CODE_OFFSET; addr < (u32)SRAM_CODE_END; addr += PAGE_SIZE)
257                 readl_relaxed(addr);
258         for (addr = (u32)SRAM_DATA_OFFSET; addr < (u32)SRAM_DATA_END; addr += PAGE_SIZE)
259                 readl_relaxed(addr);
260         readl_relaxed(RK30_PMU_BASE);
261         readl_relaxed(RK30_GRF_BASE);
262         readl_relaxed(RK30_DDR_PCTL_BASE);
263         readl_relaxed(RK30_DDR_PUBL_BASE);
264         readl_relaxed(RK30_I2C1_BASE);
265 }
266
267 static inline bool pm_pmu_power_domain_is_on(enum pmu_power_domain pd, u32 pmu_pwrdn_st)
268 {
269         return !(pmu_pwrdn_st & (1 << pd));
270 }
271
272 static void rk30_pm_set_power_domain(u32 pmu_pwrdn_st, bool state)
273 {
274         if (pm_pmu_power_domain_is_on(PD_DBG, pmu_pwrdn_st))
275                 pmu_set_power_domain(PD_DBG, state);
276
277         if (pm_pmu_power_domain_is_on(PD_GPU, pmu_pwrdn_st)) {
278                 u32 gate[2];
279                 gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_GPU_SRC));
280                 gate[1] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_GPU));
281                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_GPU_SRC), CLK_GATE_CLKID_CONS(CLK_GATE_GPU_SRC));
282                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_GPU), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_GPU));
283                 pmu_set_power_domain(PD_GPU, state);
284                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_GPU_SRC) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_GPU_SRC));
285                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_GPU) | gate[1], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_GPU));
286         }
287
288         if (pm_pmu_power_domain_is_on(PD_VIDEO, pmu_pwrdn_st)) {
289                 u32 gate[3];
290                 gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VEPU));
291                 gate[1] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VDPU));
292                 gate[2] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VCODEC));
293                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VEPU), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VEPU));
294                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VDPU), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VDPU));
295                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VCODEC), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VCODEC));
296                 pmu_set_power_domain(PD_VIDEO, state);
297                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VEPU) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VEPU));
298                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VDPU) | gate[1], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VDPU));
299                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VCODEC) | gate[2], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VCODEC));
300         }
301
302         if (pm_pmu_power_domain_is_on(PD_VIO, pmu_pwrdn_st)) {
303                 u32 gate[10];
304                 gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC));
305                 gate[1] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC));
306                 gate[2] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0));
307                 gate[3] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1));
308                 gate[4] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF0));
309                 gate[5] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF1));
310                 gate[6] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO0));
311                 gate[7] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1));
312                 gate[8] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP));
313                 gate[9] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA));
314                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0_SRC), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC));
315                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1_SRC), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC));
316                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0));
317                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1));
318                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF0), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF0));
319                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF1));
320                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO0), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO0));
321                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1));
322                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_IPP), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP));
323                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_RGA), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA));
324                 pmu_set_power_domain(PD_VIO, state);
325                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0_SRC) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC));
326                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1_SRC) | gate[1], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC));
327                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0) | gate[2], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0));
328                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1) | gate[3], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1));
329                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF0) | gate[4], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF0));
330                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF1) | gate[5], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF1));
331                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO0) | gate[6], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO0));
332                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO1) | gate[7], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1));
333                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_IPP) | gate[8], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP));
334                 cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_RGA) | gate[9], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA));
335         }
336 }
337
338 __weak void board_gpio_suspend(void) {}
339 __weak void board_gpio_resume(void) {}
340 __weak void __sramfunc board_pmu_suspend(void) {}
341 __weak void __sramfunc board_pmu_resume(void) {}
342 __weak void __sramfunc rk30_suspend_voltage_set(unsigned int vol){}
343 __weak void __sramfunc rk30_suspend_voltage_resume(unsigned int vol){}
344
345 __weak void  rk30_pwm_suspend_voltage_set(void){}
346 __weak void  rk30_pwm_resume_voltage_set(void){}
347
348 __weak void __sramfunc rk30_pwm_logic_suspend_voltage(void){}
349 __weak void __sramfunc rk30_pwm_logic_resume_voltage(void){}
350
351 static void __sramfunc rk30_sram_suspend(void)
352 {
353         u32 cru_clksel0_con;
354         u32 clkgt_regs[CRU_CLKGATES_CON_CNT];
355         u32 cru_mode_con;
356         int i;
357         
358         sram_printch('5');
359         ddr_suspend();
360         sram_printch('6');
361         rk30_suspend_voltage_set(1000000);
362         rk30_pwm_logic_suspend_voltage();
363         sram_printch('7');
364         
365
366         for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) {
367                 clkgt_regs[i] = cru_readl(CRU_CLKGATES_CON(i));
368         }
369         gate_save_soc_clk(0
370                           | (1 << CLK_GATE_CORE_PERIPH)
371                           | (1 << CLK_GATE_ACLK_CPU)
372                           | (1 << CLK_GATE_HCLK_CPU)
373                           | (1 << CLK_GATE_PCLK_CPU)
374                           , clkgt_regs[0], CRU_CLKGATES_CON(0), 0xffff);
375         gate_save_soc_clk(0, clkgt_regs[1], CRU_CLKGATES_CON(1), 0xffff);
376         if(clkgt_regs[8]&((1<<12)|(1<13))){
377                 gate_save_soc_clk(0
378                                   | (1 << CLK_GATE_PEIRPH_SRC % 16)
379                                   | (1 << CLK_GATE_PCLK_PEIRPH % 16)
380                                 , clkgt_regs[2], CRU_CLKGATES_CON(2), 0xffff);
381         }else{
382                 gate_save_soc_clk(0
383                                 , clkgt_regs[2], CRU_CLKGATES_CON(2), 0xffff);
384
385         }
386         gate_save_soc_clk(0
387                           | (1 << CLK_GATE_ACLK_STRC_SYS % 16)
388                           | (1 << CLK_GATE_ACLK_INTMEM % 16)
389                           , clkgt_regs[4], CRU_CLKGATES_CON(4), 0xffff);
390         gate_save_soc_clk(0
391                           | (1 << CLK_GATE_PCLK_GRF % 16)
392                           | (1 << CLK_GATE_PCLK_PMU % 16)
393                           , clkgt_regs[5], CRU_CLKGATES_CON(5), 0xffff);
394          gate_save_soc_clk(0 , clkgt_regs[7], CRU_CLKGATES_CON(7), 0xffff);
395         gate_save_soc_clk(0
396                           | (1 << CLK_GATE_CLK_L2C % 16)
397                           | (1 << CLK_GATE_ACLK_INTMEM0 % 16)
398                           | (1 << CLK_GATE_ACLK_INTMEM1 % 16)
399                           | (1 << CLK_GATE_ACLK_INTMEM2 % 16)
400                           | (1 << CLK_GATE_ACLK_INTMEM3 % 16)
401                           , clkgt_regs[9], CRU_CLKGATES_CON(9), 0x07ff);
402         
403 #ifdef CONFIG_CLK_SWITCH_TO_32K
404         cru_mode_con = cru_readl(CRU_MODE_CON);
405         cru_writel(0|
406                 PLL_MODE_DEEP(APLL_ID)|
407                 PLL_MODE_DEEP(DPLL_ID)|
408                 PLL_MODE_DEEP(CPLL_ID)|PLL_MODE_DEEP(GPLL_ID),CRU_MODE_CON);
409         board_pmu_suspend();
410 #else
411         board_pmu_suspend();
412         cru_clksel0_con = cru_readl(CRU_CLKSELS_CON(0));
413         cru_writel((0x1f << 16) | 0x1f, CRU_CLKSELS_CON(0));
414 #endif
415
416         dsb();
417         wfi();
418
419 #ifdef CONFIG_CLK_SWITCH_TO_32K
420         board_pmu_resume();
421         cru_writel((0xffff<<16) | cru_mode_con, CRU_MODE_CON);
422 #else
423         cru_writel((0x1f << 16) | cru_clksel0_con, CRU_CLKSELS_CON(0));
424         board_pmu_resume();
425 #endif
426         
427         for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) {
428                 cru_writel(clkgt_regs[i] | 0xffff0000, CRU_CLKGATES_CON(i));
429         }
430
431         sram_printch('7');
432         rk30_pwm_logic_resume_voltage();
433         rk30_suspend_voltage_resume(1100000);
434         
435         sram_printch('6');
436         ddr_resume();
437         sram_printch('5');
438         
439 }
440
441 static void noinline rk30_suspend(void)
442 {
443         DDR_SAVE_SP(save_sp);
444         rk30_sram_suspend();
445         DDR_RESTORE_SP(save_sp);
446 }
447
448 static int rk30_pm_enter(suspend_state_t state)
449 {
450         u32 i;
451         u32 clkgt_regs[CRU_CLKGATES_CON_CNT];
452         u32 clk_sel0, clk_sel1, clk_sel10;
453         u32 cpll_con3;
454         u32 cru_mode_con;
455         u32 pmu_pwrdn_st;
456
457         // dump GPIO INTEN for debug
458         rk30_pm_dump_inten();
459         //gpio6_b7
460         grf_writel(0xc0004000, 0x10c);
461         cru_writel(0x07000000, CRU_MISC_CON);
462
463         sram_printch('0');
464
465         pmu_pwrdn_st = pmu_readl(PMU_PWRDN_ST);
466         rk30_pm_set_power_domain(pmu_pwrdn_st, false);
467
468 #ifdef CONFIG_DDR_TEST
469         // memory tester
470         if (ddr_debug != 0)
471                 ddr_testmode();
472  #endif
473
474         sram_printch('1');
475         local_fiq_disable();
476
477         for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) {
478                 clkgt_regs[i] = cru_readl(CRU_CLKGATES_CON(i));
479         }
480
481         gate_save_soc_clk(0
482                           | (1 << CLK_GATE_CORE_PERIPH)
483                           | (1 << CLK_GATE_DDRPHY)
484                           | (1 << CLK_GATE_ACLK_CPU)
485                           | (1 << CLK_GATE_HCLK_CPU)
486                           | (1 << CLK_GATE_PCLK_CPU)
487                           , clkgt_regs[0], CRU_CLKGATES_CON(0), 0xffff);
488         gate_save_soc_clk(0
489                           | (1 << CLK_GATE_DDR_GPLL % 16)
490                           , clkgt_regs[1], CRU_CLKGATES_CON(1), 0xffff);
491         gate_save_soc_clk(0
492                           | (1 << CLK_GATE_PEIRPH_SRC % 16)
493                           | (1 << CLK_GATE_PCLK_PEIRPH % 16)
494                           | (1 << CLK_GATE_ACLK_PEIRPH % 16)
495                           , clkgt_regs[2], CRU_CLKGATES_CON(2), 0xffff);
496         gate_save_soc_clk(0, clkgt_regs[3], CRU_CLKGATES_CON(3), 0xff9f);
497         gate_save_soc_clk(0
498                           | (1 << CLK_GATE_HCLK_PERI_AXI_MATRIX % 16)
499                           | (1 << CLK_GATE_PCLK_PERI_AXI_MATRIX % 16)
500                           | (1 << CLK_GATE_ACLK_CPU_PERI % 16)
501                           | (1 << CLK_GATE_ACLK_PERI_AXI_MATRIX % 16)
502                           | (1 << CLK_GATE_ACLK_PEI_NIU % 16)
503                           | (1 << CLK_GATE_HCLK_PERI_AHB_ARBI % 16)
504                           | (1 << CLK_GATE_HCLK_CPUBUS % 16)
505                           | (1 << CLK_GATE_ACLK_STRC_SYS % 16)
506                           | (1 << CLK_GATE_ACLK_INTMEM % 16)
507                           , clkgt_regs[4], CRU_CLKGATES_CON(4), 0xffff);
508         gate_save_soc_clk(0
509                           | (1 << CLK_GATE_PCLK_GRF % 16)
510                           | (1 << CLK_GATE_PCLK_PMU % 16)
511                           | (1 << CLK_GATE_PCLK_DDRUPCTL % 16)
512                           , clkgt_regs[5], CRU_CLKGATES_CON(5), 0xffff);
513         gate_save_soc_clk(0, clkgt_regs[6], CRU_CLKGATES_CON(6), 0xffff);
514         gate_save_soc_clk(0
515                         |(1 << CLK_GATE_PCLK_PWM23%16)
516                         , clkgt_regs[7], CRU_CLKGATES_CON(7), 0xffff);
517         gate_save_soc_clk(0 , clkgt_regs[8], CRU_CLKGATES_CON(8), 0x01ff);
518         gate_save_soc_clk(0
519                           | (1 << CLK_GATE_CLK_L2C % 16)
520                           | (1 << CLK_GATE_PCLK_PUBL % 16)
521                           | (1 << CLK_GATE_ACLK_INTMEM0 % 16)
522                           | (1 << CLK_GATE_ACLK_INTMEM1 % 16)
523                           | (1 << CLK_GATE_ACLK_INTMEM2 % 16)
524                           | (1 << CLK_GATE_ACLK_INTMEM3 % 16)
525                           , clkgt_regs[9], CRU_CLKGATES_CON(9), 0x07ff);
526
527         sram_printch('2');
528
529         cru_mode_con = cru_readl(CRU_MODE_CON);
530
531         //cpll
532         cru_writel(PLL_MODE_SLOW(CPLL_ID), CRU_MODE_CON);
533         cpll_con3 = cru_readl(PLL_CONS(CPLL_ID, 3));
534         cru_writel(PLL_PWR_DN_MSK | PLL_PWR_DN, PLL_CONS(CPLL_ID, 3));
535
536         //gpll
537         cru_writel(PLL_MODE_SLOW(GPLL_ID), CRU_MODE_CON);
538         clk_sel10 = cru_readl(CRU_CLKSELS_CON(10));
539         cru_writel(CRU_W_MSK_SETBITS(0, PERI_ACLK_DIV_OFF, PERI_ACLK_DIV_MASK)
540                    | CRU_W_MSK_SETBITS(0, PERI_HCLK_DIV_OFF, PERI_HCLK_DIV_MASK)
541                    | CRU_W_MSK_SETBITS(0, PERI_PCLK_DIV_OFF, PERI_PCLK_DIV_MASK)
542                    , CRU_CLKSELS_CON(10));
543         cru_writel(PLL_PWR_DN_MSK | PLL_PWR_DN, PLL_CONS(GPLL_ID, 3));
544
545         //apll
546         clk_sel0 = cru_readl(CRU_CLKSELS_CON(0));
547         clk_sel1 = cru_readl(CRU_CLKSELS_CON(1));
548
549         cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
550         cru_writel(CORE_PERIPH_MSK | CORE_PERIPH_2
551                    | CORE_CLK_DIV_W_MSK | CORE_CLK_DIV(1)
552                    , CRU_CLKSELS_CON(0));
553         cru_writel(CORE_ACLK_W_MSK | CORE_ACLK_11
554                    | ACLK_HCLK_W_MSK | ACLK_HCLK_11
555                    | ACLK_PCLK_W_MSK | ACLK_PCLK_11
556                    | AHB2APB_W_MSK | AHB2APB_11
557                    , CRU_CLKSELS_CON(1));
558         cru_writel(PLL_PWR_DN_W_MSK | PLL_PWR_DN, PLL_CONS(APLL_ID, 3));
559
560         sram_printch('3');
561         rk30_pwm_suspend_voltage_set();
562
563         board_gpio_suspend();
564
565         interface_ctr_reg_pread();
566
567         sram_printch('4');
568         rk30_suspend();
569         sram_printch('4');
570
571         board_gpio_resume();
572         rk30_pwm_resume_voltage_set();
573         sram_printch('3');
574
575         //apll
576         cru_writel(0xffff0000 | clk_sel1, CRU_CLKSELS_CON(1));
577         cru_writel(0xffff0000 | clk_sel0, CRU_CLKSELS_CON(0));
578         power_on_pll(APLL_ID);
579         cru_writel((PLL_MODE_MSK(APLL_ID) << 16) | (PLL_MODE_MSK(APLL_ID) & cru_mode_con), CRU_MODE_CON);
580
581         //gpll
582         cru_writel(0xffff0000 | clk_sel10, CRU_CLKSELS_CON(10));
583         cru_writel(clk_sel10, CRU_CLKSELS_CON(10));
584         power_on_pll(GPLL_ID);
585         cru_writel((PLL_MODE_MSK(GPLL_ID) << 16) | (PLL_MODE_MSK(GPLL_ID) & cru_mode_con), CRU_MODE_CON);
586
587         //cpll
588         if (((cpll_con3 & PLL_PWR_DN_MSK) == PLL_PWR_ON) &&
589             ((PLL_MODE_NORM(CPLL_ID) & PLL_MODE_MSK(CPLL_ID)) == (cru_mode_con & PLL_MODE_MSK(CPLL_ID)))) {
590                 power_on_pll(CPLL_ID);
591         }
592         cru_writel((PLL_MODE_MSK(CPLL_ID) << 16) | (PLL_MODE_MSK(CPLL_ID) & cru_mode_con), CRU_MODE_CON);
593
594         sram_printch('2');
595
596         for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) {
597                 cru_writel(clkgt_regs[i] | 0xffff0000, CRU_CLKGATES_CON(i));
598         }
599
600         local_fiq_enable();
601         sram_printch('1');
602
603         rk30_pm_set_power_domain(pmu_pwrdn_st, true);
604
605         sram_printascii("0\n");
606
607         rk30_pm_dump_irq();
608
609         return 0;
610 }
611
612 static int rk30_pm_prepare(void)
613 {
614         /* disable entering idle by disable_hlt() */
615         disable_hlt();
616         return 0;
617 }
618
619 static void rk30_pm_finish(void)
620 {
621         enable_hlt();
622 }
623
624 static struct platform_suspend_ops rk30_pm_ops = {
625         .enter          = rk30_pm_enter,
626         .valid          = suspend_valid_only_mem,
627         .prepare        = rk30_pm_prepare,
628         .finish         = rk30_pm_finish,
629 };
630
631 static int __init rk30_pm_init(void)
632 {
633         suspend_set_ops(&rk30_pm_ops);
634
635 #ifdef CONFIG_EARLYSUSPEND
636         pm_set_vt_switch(0); /* disable vt switch while suspend */
637 #endif
638
639         return 0;
640 }
641 __initcall(rk30_pm_init);