rk3288 sleep support
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / pm-rk3188.c
1
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 #include <asm/cacheflush.h>
5 #include <asm/tlbflush.h>
6 #include <asm/hardware/cache-l2x0.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9
10 #include <linux/pm.h>
11 #include <linux/suspend.h>
12 #include <linux/of.h>
13 #include <asm/io.h>
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16
17 #include <linux/rockchip/cpu.h>
18 #include <linux/rockchip/cru.h>
19 #include <linux/rockchip/grf.h>
20 #include <linux/rockchip/iomap.h>
21 #include "pm.h"
22
23 #define CPU 3188
24 //#include "sram.h"
25 #include "pm-pie.c"
26
27 #define RK3188_CLK_GATING_OPS(ID) cru_writel((0x1<<((ID%16)+16))|(0x1<<(ID%16)),RK3188_CRU_GATEID_CONS(ID))
28 #define RK3188_CLK_UNGATING_OPS(ID) cru_writel(0x1<<((ID%16)+16),RK3188_CRU_GATEID_CONS(ID))
29
30 /*************************cru define********************************************/
31 /*******************CRU BITS*******************************/
32 #define CRU_W_MSK(bits_shift, msk)      ((msk) << ((bits_shift) + 16))
33 #define CRU_SET_BITS(val, bits_shift, msk)      (((val)&(msk)) << (bits_shift))
34 #define CRU_W_MSK_SETBITS(val, bits_shift,msk) \
35         (CRU_W_MSK(bits_shift, msk) | CRU_SET_BITS(val, bits_shift, msk))
36         
37 #define RK3188_CRU_GET_REG_BITS_VAL(reg,bits_shift, msk)  (((reg) >> (bits_shift))&(msk))
38 #define RK3188_CRU_W_MSK(bits_shift, msk)       ((msk) << ((bits_shift) + 16))
39 #define RK3188_CRU_SET_BITS(val,bits_shift, msk)        (((val)&(msk)) << (bits_shift))
40     
41 #define RK3188_CRU_W_MSK_SETBITS(val,bits_shift,msk) \
42         (RK3188_CRU_W_MSK(bits_shift, msk)|RK3188_CRU_SET_BITS(val,bits_shift, msk))
43     
44     
45 /*******************RK3188_PLL CON3 BITS***************************/
46
47 #define RK3188_PLL_PWR_DN_MSK           (1 << 1)
48 #define RK3188_PLL_PWR_DN_W_MSK (RK3188_PLL_PWR_DN_MSK << 16)
49 #define RK3188_PLL_PWR_DN               (1 << 1)
50 #define RK3188_PLL_PWR_ON               (0 << 1)
51     
52
53
54 /*******************CLKSEL0 BITS***************************/
55 //RK3188_CORE_preiph div
56 #define RK3188_CORE_PERIPH_W_MSK        (3 << 22)
57 #define RK3188_CORE_PERIPH_MSK          (3 << 6)
58 #define RK3188_CORE_PERIPH_2            (0 << 6)
59 #define RK3188_CORE_PERIPH_4            (1 << 6)
60 #define RK3188_CORE_PERIPH_8            (2 << 6)
61 #define RK3188_CORE_PERIPH_16           (3 << 6)
62
63 //clk_RK3188_CORE
64 #define RK3188_CORE_SEL_PLL_MSK (1 << 8)
65 #define RK3188_CORE_SEL_PLL_W_MSK       (1 << 24)
66 #define RK3188_CORE_SEL_APLL            (0 << 8)
67 #define RK3188_CORE_SEL_GPLL            (1 << 8)
68
69 #define RK3188_CORE_CLK_DIV_W_MSK       (0x1F << 25)
70 #define RK3188_CORE_CLK_DIV_MSK (0x1F << 9)
71 #define RK3188_CORE_CLK_DIV(i)          ((((i) - 1) & 0x1F) << 9)
72 #define RK3188_CORE_CLK_MAX_DIV 32
73
74 #define RK3188_CPU_SEL_PLL_MSK          (1 << 5)
75 #define RK3188_CPU_SEL_PLL_W_MSK        (1 << 21)
76 #define RK3188_CPU_SEL_APLL             (0 << 5)
77 #define RK3188_CPU_SEL_GPLL             (1 << 5)
78
79 #define RK3188_CPU_CLK_DIV_W_MSK        (0x1F << 16)
80 #define RK3188_CPU_CLK_DIV_MSK          (0x1F)
81 #define RK3188_CPU_CLK_DIV(i)           (((i) - 1) & 0x1F)
82
83 /*******************CLKSEL1 BITS***************************/
84 //aclk div
85 #define RK3188_GET_CORE_ACLK_VAL(reg) ((reg)>=4 ?8:((reg)+1))
86
87 #define RK3188_CORE_ACLK_W_MSK          (7 << 19)
88 #define RK3188_CORE_ACLK_MSK            (7 << 3)
89 #define RK3188_CORE_ACLK_11             (0 << 3)
90 #define RK3188_CORE_ACLK_21             (1 << 3)
91 #define RK3188_CORE_ACLK_31             (2 << 3)
92 #define RK3188_CORE_ACLK_41             (3 << 3)
93 #define RK3188_CORE_ACLK_81             (4 << 3)
94 //hclk div
95 #define RK3188_ACLK_HCLK_W_MSK          (3 << 24)
96 #define RK3188_ACLK_HCLK_MSK            (3 << 8)
97 #define RK3188_ACLK_HCLK_11             (0 << 8)
98 #define RK3188_ACLK_HCLK_21             (1 << 8)
99 #define RK3188_ACLK_HCLK_41             (2 << 8)
100 // pclk div
101 #define RK3188_ACLK_PCLK_W_MSK          (3 << 28)
102 #define RK3188_ACLK_PCLK_MSK            (3 << 12)
103 #define RK3188_ACLK_PCLK_11             (0 << 12)
104 #define RK3188_ACLK_PCLK_21             (1 << 12)
105 #define RK3188_ACLK_PCLK_41             (2 << 12)
106 #define RK3188_ACLK_PCLK_81             (3 << 12)
107 // ahb2apb div
108 #define RK3188_AHB2APB_W_MSK            (3 << 30)
109 #define RK3188_AHB2APB_MSK              (3 << 14)
110 #define RK3188_AHB2APB_11               (0 << 14)
111 #define RK3188_AHB2APB_21               (1 << 14)
112 #define RK3188_AHB2APB_41               (2 << 14)
113
114 /*******************clksel10***************************/
115
116 #define RK3188_PERI_ACLK_DIV_MASK 0x1f
117 #define RK3188_PERI_ACLK_DIV_W_MSK      (RK3188_PERI_ACLK_DIV_MASK << 16)
118 #define RK3188_PERI_ACLK_DIV(i) (((i) - 1) & RK3188_PERI_ACLK_DIV_MASK)
119 #define RK3188_PERI_ACLK_DIV_OFF 0
120
121 #define RK3188_PERI_HCLK_DIV_MASK 0x3
122 #define RK3188_PERI_HCLK_DIV_OFF 8
123
124 #define RK3188_PERI_PCLK_DIV_MASK 0x3
125 #define RK3188_PERI_PCLK_DIV_OFF 12
126
127
128
129 /*************************gate id**************************************/
130 #define RK3188_CLK_GATEID(i)    (16 * (i))
131
132
133 enum cru_clk_gate {
134         /* SCU CLK GATE 0 CON */
135         RK3188_CLKGATE_CORE_PERIPH = RK3188_CLK_GATEID(0),
136
137         RK3188_CLKGATE_TIMER0 = RK3188_CLK_GATEID(1),
138         RK3188_CLKGATE_UART0_SRC=RK3188_CLK_GATEID(1)+8,
139         RK3188_CLKGATE_UART0_FRAC_SRC,
140
141         RK3188_CLKGATE_PCLK_UART0 = RK3188_CLK_GATEID(8),
142         
143
144         RK3188_CLKGATE_CLK_CORE_DBG = RK3188_CLK_GATEID(9),
145
146         RK3188_CLKGATE_MAX= RK3188_CLK_GATEID(10),
147 };
148 /*******************************gpio define **********************************************/
149 #define GPIO_INTEN                      0x30
150 #define GPIO_INTMASK            0x34
151 #define GPIO_INTTYPE_LEVEL      0x38
152 #define GPIO_INT_POLARITY       0x3c
153 #define GPIO_INT_STATUS         0x40
154
155 /*******************************common code  for rkxxx*********************************/
156
157 static void  inline uart_printch(char byte)
158 {
159         u32 reg_save[2];
160         u32 u_clk_id=(RK3188_CLKGATE_UART0_SRC+CONFIG_RK_DEBUG_UART);
161         u32 u_pclk_id=(RK3188_CLKGATE_PCLK_UART0+CONFIG_RK_DEBUG_UART);
162         
163         reg_save[0]=cru_readl(RK3188_CRU_GATEID_CONS(u_clk_id));
164         reg_save[1]=cru_readl(RK3188_CRU_GATEID_CONS(u_pclk_id));
165         RK3188_CLK_UNGATING_OPS(u_clk_id);
166         RK3188_CLK_UNGATING_OPS(u_pclk_id);
167         
168         rkpm_udelay(1);
169         
170         writel_relaxed(byte, RK_DEBUG_UART_VIRT);
171         dsb();
172
173         /* loop check LSR[6], Transmitter Empty bit */
174         while (!(readl_relaxed(RK_DEBUG_UART_VIRT + 0x14) & 0x40))
175                 barrier();
176     
177          cru_writel(reg_save[0]|0x1<<((u_pclk_id%16)+16),RK3188_CRU_GATEID_CONS(u_clk_id));         
178          cru_writel(reg_save[1]|0x1<<((u_pclk_id%16)+16),RK3188_CRU_GATEID_CONS(u_pclk_id));
179         
180         if (byte == '\n')
181                 uart_printch('\r');
182 }
183
184 void PIE_FUNC(sram_printch)(char byte)
185 {
186         uart_printch(byte);
187 }
188
189 static void  ddr_printch(char byte)
190 {
191         uart_printch(byte);
192 }
193 /*******************************clk gating config*******************************************/
194 #define CLK_MSK_GATING(msk, con) cru_writel((msk << 16) | 0xffff, con)
195 #define CLK_MSK_UNGATING(msk, con) cru_writel(((~msk) << 16) | 0xffff, con)
196
197
198 static u32 clk_ungt_msk[RK3188_CRU_CLKGATES_CON_CNT];// first clk gating setting
199 static u32 clk_ungt_save[RK3188_CRU_CLKGATES_CON_CNT]; //first clk gating value saveing
200
201
202 u32 DEFINE_PIE_DATA(rkpm_clkgt_last_set[RK3188_CRU_CLKGATES_CON_CNT]);
203 static u32 *p_rkpm_clkgt_last_set;
204
205 u32 DEFINE_PIE_DATA(rkpm_clkgt_last_save[RK3188_CRU_CLKGATES_CON_CNT]);
206 static u32 *p_rkpm_clkgt_last_save;
207
208 void PIE_FUNC(gtclks_sram_suspend)(void)
209 {
210     int i;
211    // u32 u_clk_id=(RK3188_CLKGATE_UART0_SRC+CONFIG_RK_DEBUG_UART);
212    // u32 u_pclk_id=(RK3188_CLKGATE_PCLK_UART0+CONFIG_RK_DEBUG_UART);
213
214     for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
215     {
216         DATA(rkpm_clkgt_last_save[i])=cru_readl(RK3188_CRU_CLKGATES_CON(i));     
217         CLK_MSK_UNGATING( DATA(rkpm_clkgt_last_set[i]), RK3188_CRU_CLKGATES_CON(i));      
218         #if 0
219         rkpm_sram_printch('\n');   
220         rkpm_sram_printhex(DATA(rkpm_clkgt_last_save[i]));
221         rkpm_sram_printch('-');   
222         rkpm_sram_printhex(DATA(rkpm_clkgt_last_set[i]));
223         rkpm_sram_printch('-');   
224         rkpm_sram_printhex(cru_readl(RK3188_CRU_CLKGATES_CON(i)));
225         if(i==(RK3188_CRU_CLKGATES_CON_CNT-1))         
226         rkpm_sram_printch('\n');   
227         #endif
228     }
229     
230         //RK3188_CLK_UNGATING_OPS(u_clk_id);
231         //RK3188_CLK_UNGATING_OPS(u_pclk_id);
232  
233 }
234
235 void PIE_FUNC(gtclks_sram_resume)(void)
236 {
237     int i;
238     for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
239     {
240         cru_writel(DATA(rkpm_clkgt_last_save[i])|0xffff0000, RK3188_CRU_CLKGATES_CON(i));
241     }
242 }
243
244 static void gtclks_suspend(void)
245 {
246     int i;
247     
248     for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
249     {
250     
251         clk_ungt_save[i]=cru_readl(RK3188_CRU_CLKGATES_CON(i));    
252         //if(i!=4||i!=0)
253         CLK_MSK_UNGATING(clk_ungt_msk[i],RK3188_CRU_CLKGATES_CON(i));
254        #if 0
255         rkpm_ddr_printch('\n');   
256         rkpm_ddr_printhex(clk_ungt_save[i]);
257         rkpm_ddr_printch('-');   
258         rkpm_ddr_printhex(clk_ungt_msk[i]);
259         rkpm_ddr_printch('-');   
260         rkpm_ddr_printhex(cru_readl(RK3188_CRU_CLKGATES_CON(i))) ;  
261         if(i==(RK3188_CRU_CLKGATES_CON_CNT-1))            
262             rkpm_ddr_printch('\n');   
263         #endif
264     }
265
266 }
267
268 static void gtclks_resume(void)
269 {
270     int i;
271      for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
272     {
273        cru_writel(clk_ungt_save[i]|0xffff0000,RK3188_CRU_CLKGATES_CON(i));
274     }
275     
276 }
277
278 /********************************pll power down***************************************/
279
280 #define power_off_pll(id) \
281         cru_writel(RK3188_PLL_PWR_DN_W_MSK | RK3188_PLL_PWR_DN, RK3188_PLL_CONS((id), 3))
282
283 static void pm_pll_wait_lock(u32 pll_idx)
284 {
285         u32 pll_state[4] = { 1, 0, 2, 3 };
286         u32 bit = 0x20u << pll_state[pll_idx];
287         u32 delay = pll_idx == RK3188_APLL_ID ? 600000U : 30000000U;
288         dsb();
289         dsb();
290         dsb();
291         dsb();
292         dsb();
293         dsb();
294         while (delay > 0) {
295                 if (grf_readl(RK3188_GRF_SOC_STATUS0) & bit)
296                         break;
297                 delay--;
298         }
299         if (delay == 0) {
300                 //CRU_PRINTK_ERR("wait pll bit 0x%x time out!\n", bit); 
301                 rkpm_ddr_printch('p');
302                 rkpm_ddr_printch('l');
303                 rkpm_ddr_printch('l');
304                 rkpm_ddr_printhex(pll_idx);
305                 rkpm_ddr_printch('\n');
306         }
307 }       
308 static void power_on_pll(u32 pll_id)
309 {
310         cru_writel(RK3188_PLL_PWR_DN_W_MSK | RK3188_PLL_PWR_ON, RK3188_PLL_CONS((pll_id), 3));
311         pm_pll_wait_lock((pll_id));
312 }
313
314 static u32 clk_sel0, clk_sel1, clk_sel10;
315 static u32 cpll_con3;
316 static u32 cru_mode_con;
317
318 static void plls_suspend(void)
319 {
320     cru_mode_con = cru_readl(RK3188_CRU_MODE_CON);
321     cru_writel(RK3188_PLL_MODE_SLOW(RK3188_CPLL_ID), RK3188_CRU_MODE_CON);
322
323     cpll_con3 = cru_readl(RK3188_PLL_CONS(RK3188_CPLL_ID, 3));
324    //power_off_pll(RK3188_CPLL_ID);
325        
326
327        //apll
328        clk_sel0 = cru_readl(RK3188_CRU_CLKSELS_CON(0));
329        clk_sel1 = cru_readl(RK3188_CRU_CLKSELS_CON(1));
330
331        cru_writel(RK3188_PLL_MODE_SLOW(RK3188_APLL_ID), RK3188_CRU_MODE_CON);
332        
333        /* To make sure aclk_cpu select apll before div effect */
334        cru_writel(RK3188_CPU_SEL_PLL_W_MSK | RK3188_CPU_SEL_APLL
335                           | RK3188_CORE_SEL_PLL_W_MSK | RK3188_CORE_SEL_APLL
336                           , RK3188_CRU_CLKSELS_CON(0));
337        cru_writel(RK3188_CORE_PERIPH_W_MSK | RK3188_CORE_PERIPH_2
338               | RK3188_CORE_CLK_DIV_W_MSK | RK3188_CORE_CLK_DIV(1)
339               | RK3188_CPU_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV(1)
340               , RK3188_CRU_CLKSELS_CON(0));
341        cru_writel(RK3188_CORE_ACLK_W_MSK | RK3188_CORE_ACLK_11
342               | RK3188_ACLK_HCLK_W_MSK | RK3188_ACLK_HCLK_11
343               | RK3188_ACLK_PCLK_W_MSK | RK3188_ACLK_PCLK_11
344               | RK3188_AHB2APB_W_MSK | RK3188_AHB2APB_11
345               , RK3188_CRU_CLKSELS_CON(1));
346        //power_off_pll(RK3188_APLL_ID);
347     cru_writel(RK3188_PLL_MODE_SLOW(RK3188_GPLL_ID), RK3188_CRU_MODE_CON);
348
349        
350     clk_sel10 = cru_readl(RK3188_CRU_CLKSELS_CON(10));
351     cru_writel(RK3188_CRU_W_MSK_SETBITS(0, RK3188_PERI_ACLK_DIV_OFF, RK3188_PERI_ACLK_DIV_MASK)
352     | RK3188_CRU_W_MSK_SETBITS(0,RK3188_PERI_HCLK_DIV_OFF, RK3188_PERI_HCLK_DIV_MASK)
353     | RK3188_CRU_W_MSK_SETBITS(0, RK3188_PERI_PCLK_DIV_OFF, RK3188_PERI_PCLK_DIV_MASK)
354     , RK3188_CRU_CLKSELS_CON(10));
355     
356   //power_off_pll(RK3188_GPLL_ID);
357
358 }
359
360 static void plls_resume(void)
361 {
362     //gpll
363        
364         cru_writel(0xffff0000 | clk_sel10, RK3188_CRU_CLKSELS_CON(10));
365     
366       // power_on_pll(RK3188_GPLL_ID);
367         cru_writel((RK3188_PLL_MODE_MSK(RK3188_GPLL_ID) << 16) 
368                         | (RK3188_PLL_MODE_MSK(RK3188_GPLL_ID) & cru_mode_con)
369                         ,  RK3188_CRU_MODE_CON);
370
371         //apll
372         cru_writel(0xffff0000 | clk_sel1, RK3188_CRU_CLKSELS_CON(1));
373         /* To make sure aclk_cpu select gpll after div effect */
374         cru_writel((0xffff0000 & ~RK3188_CPU_SEL_PLL_W_MSK & ~RK3188_CORE_SEL_PLL_W_MSK) 
375                          | clk_sel0
376                          , RK3188_CRU_CLKSELS_CON(0));
377         
378         cru_writel(RK3188_CPU_SEL_PLL_W_MSK 
379                         | RK3188_CORE_SEL_PLL_W_MSK 
380                         | clk_sel0
381                         , RK3188_CRU_CLKSELS_CON(0));
382         
383      //   power_on_pll(RK3188_APLL_ID);
384         cru_writel((RK3188_PLL_MODE_MSK(RK3188_APLL_ID) << 16)
385                         | (RK3188_PLL_MODE_MSK(RK3188_APLL_ID) & cru_mode_con)
386                         , RK3188_CRU_MODE_CON);
387
388     
389         // it was power off ,don't need to power up
390         if (((cpll_con3 & RK3188_PLL_PWR_DN_MSK) == RK3188_PLL_PWR_ON) 
391             &&((RK3188_PLL_MODE_NORM(RK3188_CPLL_ID) & RK3188_PLL_MODE_MSK(RK3188_CPLL_ID)) 
392             == (cru_mode_con & RK3188_PLL_MODE_MSK(RK3188_CPLL_ID)))) {
393        //     power_on_pll(RK3188_CPLL_ID);
394         }
395         cru_writel((RK3188_PLL_MODE_MSK(RK3188_CPLL_ID) << 16) 
396                         | (RK3188_PLL_MODE_MSK(RK3188_CPLL_ID) & cru_mode_con)
397                         , RK3188_CRU_MODE_CON);
398 }
399
400 u32  DEFINE_PIE_DATA(sysclk_cru_clksel0_con);
401 u32  DEFINE_PIE_DATA(sysclk_cru_clksel10_con);
402 u32  DEFINE_PIE_DATA(sysclk_cru_mode_con);
403
404 void PIE_FUNC(sysclk_suspend)(u32 sel_clk)
405 {
406       DATA(sysclk_cru_clksel0_con) = cru_readl(RK3188_CRU_CLKSELS_CON(0));
407       if(sel_clk&(RKPM_CTR_SYSCLK_32K))
408         {
409             DATA(sysclk_cru_mode_con) = cru_readl(RK3188_CRU_MODE_CON);
410             DATA(sysclk_cru_clksel10_con) = cru_readl(RK3188_CRU_CLKSELS_CON(10));
411             
412             cru_writel(RK3188_PERI_ACLK_DIV_W_MSK | RK3188_PERI_ACLK_DIV(4), RK3188_CRU_CLKSELS_CON(10));
413             cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CORE_CLK_DIV(4) 
414                             | RK3188_CPU_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV(4)
415                             , RK3188_CRU_CLKSELS_CON(0));
416             
417             cru_writel(0
418                             | RK3188_PLL_MODE_DEEP(RK3188_APLL_ID)
419                             //| RK3188_PLL_MODE_DEEP(RK3188_DPLL_ID)
420                             | RK3188_PLL_MODE_DEEP(RK3188_CPLL_ID)
421                             | RK3188_PLL_MODE_DEEP(RK3188_GPLL_ID)
422                             , RK3188_CRU_MODE_CON);
423             rkpm_sram_printch('8');
424         }
425         else if(sel_clk&(RKPM_CTR_SYSCLK_DIV))
426         {
427             //set core_clk_div and cpu_clk_div to the largest
428             cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CORE_CLK_DIV_MSK
429                         | RK3188_CPU_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV_MSK, RK3188_CRU_CLKSELS_CON(0));
430         }
431 }
432
433 void PIE_FUNC(sysclk_resume)(u32 sel_clk)
434 {
435
436     if(sel_clk&(RKPM_CTR_SYSCLK_32K))
437     {
438         cru_writel((0xffff<<16) | DATA(sysclk_cru_mode_con), RK3188_CRU_MODE_CON);
439         cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV_W_MSK
440                         | DATA(sysclk_cru_clksel0_con), RK3188_CRU_CLKSELS_CON(0));
441         cru_writel(RK3188_PERI_ACLK_DIV_W_MSK | DATA(sysclk_cru_clksel10_con),
442                         RK3188_CRU_CLKSELS_CON(10));
443         
444         rkpm_sram_printch('8');
445     }
446     else if(sel_clk&(RKPM_CTR_SYSCLK_DIV))
447     {
448         cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV_W_MSK
449                         | DATA(sysclk_cru_clksel0_con), RK3188_CRU_CLKSELS_CON(0));
450     }
451
452 }
453
454 static void clks_gating_suspend_init(void)
455 {
456     // get clk gating info
457     p_rkpm_clkgt_last_set= kern_to_pie(rockchip_pie_chunk, &DATA(rkpm_clkgt_last_set[0]));
458     p_rkpm_clkgt_last_save= kern_to_pie(rockchip_pie_chunk, &DATA(rkpm_clkgt_last_save[0]));
459     
460     if(clk_suspend_clkgt_info_get(clk_ungt_msk,p_rkpm_clkgt_last_set, RK3188_CRU_CLKGATES_CON_CNT) 
461         ==RK3188_CRU_CLKGATES_CON(0))
462     {
463         rkpm_set_ops_gtclks(gtclks_suspend,gtclks_resume);
464         rkpm_set_sram_ops_gtclks(fn_to_pie(rockchip_pie_chunk, &FUNC(gtclks_sram_suspend)), 
465                         fn_to_pie(rockchip_pie_chunk, &FUNC(gtclks_sram_resume)));
466         
467         PM_LOG("%s:clkgt info ok\n",__FUNCTION__);
468
469     }
470     rkpm_set_sram_ops_sysclk(fn_to_pie(rockchip_pie_chunk, &FUNC(sysclk_suspend))
471                                                 ,fn_to_pie(rockchip_pie_chunk, &FUNC(sysclk_resume))); 
472 }
473
474 /***************************prepare and finish reg_pread***********************************/
475
476 static noinline void rk30_pm_dump_irq(void)
477 {
478 #if 0
479         u32 irq_gpio = (readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 8) >> 22) & 0x7F;
480         printk("wakeup irq: %08x %08x %08x %08x\n",
481                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 4),
482                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 8),
483                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 12),
484                 readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 16));
485         DUMP_GPIO_INT_STATUS(0);
486         DUMP_GPIO_INT_STATUS(1);
487         DUMP_GPIO_INT_STATUS(2);
488         DUMP_GPIO_INT_STATUS(3);
489     #if GPIO_BANKS > 4
490         DUMP_GPIO_INT_STATUS(4);
491     #endif
492     #if GPIO_BANKS > 5
493         DUMP_GPIO_INT_STATUS(6);
494     #endif
495     #endif
496 }
497
498
499 #define DUMP_GPIO_INTEN(ID) \
500 do { \
501         u32 en = readl_relaxed(RK_GPIO_VIRT(ID) + GPIO_INTEN); \
502         if (en) { \
503                 rkpm_ddr_printascii("GPIO" #ID "_INTEN: "); \
504                 rkpm_ddr_printhex(en); \
505                 rkpm_ddr_printch('\n'); \
506                 printk(KERN_DEBUG "GPIO%d_INTEN: %08x\n", ID, en); \
507         } \
508 } while (0)
509 static noinline void rk30_pm_dump_inten(void)
510 {
511         DUMP_GPIO_INTEN(0);
512         DUMP_GPIO_INTEN(1);
513         DUMP_GPIO_INTEN(2);
514         DUMP_GPIO_INTEN(3);
515 }
516
517
518 static  void rkpm_prepare(void)
519 {   
520     #if 1
521         u32 temp =reg_readl(RK_GPIO_VIRT(0)+0x30);
522
523        // rkpm_ddr_printhex(temp);
524         reg_writel(temp|0x1<<4,RK_GPIO_VIRT(0)+0x30);
525         temp =reg_readl(RK_GPIO_VIRT(0)+0x30);
526        // rkpm_ddr_printhex(temp);
527 #endif
528         
529         // dump GPIO INTEN for debug
530         rk30_pm_dump_inten();
531         #ifdef CONFIG_DDR_TEST
532         // memory tester
533         ddr_testmode();
534         #endif
535 }
536
537 static void rkpm_finish(void)
538 {
539         rk30_pm_dump_irq();
540 }
541
542
543 static  void interface_ctr_reg_pread(void)
544 {
545         //u32 addr;
546         flush_cache_all();
547         outer_flush_all();
548         local_flush_tlb_all();
549         #if 0  // do it in ddr suspend 
550         for (addr = (u32)SRAM_CODE_OFFSET; addr < (u32)(SRAM_CODE_OFFSET+rockchip_sram_size); addr += PAGE_SIZE)
551                 readl_relaxed(addr);
552         #endif
553         readl_relaxed(RK_PMU_VIRT);
554         readl_relaxed(RK_GRF_VIRT);
555         readl_relaxed(RK_DDR_VIRT);
556         readl_relaxed(RK_GPIO_VIRT(0));     
557         //readl_relaxed(RK30_I2C1_BASE+SZ_4K);
558         //readl_relaxed(RK_GPIO_VIRT(3));
559 }
560
561 static u32 gpios_data[2];
562
563 static void __init  rk3188_suspend_init(void)
564 {
565
566     struct device_node *parent;
567     u32 pm_ctrbits;
568
569     PM_LOG("%s enter\n",__FUNCTION__);
570
571     parent = of_find_node_by_name(NULL, "rockchip_suspend");    
572
573     if (IS_ERR_OR_NULL(parent)) {
574                 PM_ERR("%s dev node err\n", __func__);
575                 return;
576         }
577
578
579     if(of_property_read_u32_array(parent,"rockchip,ctrbits",&pm_ctrbits,1))
580     {
581             PM_ERR("%s:get pm ctr error\n",__FUNCTION__);
582             return ;
583     }
584     PM_LOG("%s: pm_ctrbits =%x\n",__FUNCTION__,pm_ctrbits);
585
586     if(of_property_read_u32_array(parent,"rockchip,pmic-gpios",gpios_data,ARRAY_SIZE(gpios_data)))
587     {
588             PM_ERR("%s:get pm ctr error\n",__FUNCTION__);
589             return ;
590     }
591     rkpm_set_ctrbits(pm_ctrbits);
592     clks_gating_suspend_init();
593     rkpm_set_ops_plls(plls_suspend,plls_resume);
594     rkpm_set_ops_prepare_finish(rkpm_prepare,rkpm_finish);
595     rkpm_set_ops_regs_pread(interface_ctr_reg_pread); 
596     
597     //rkpm_set_sram_ops_ddr(fn_to_pie(rockchip_pie_chunk, &FUNC(ddr_suspend))
598                                    //     ,fn_to_pie(rockchip_pie_chunk, &FUNC(ddr_resume)));
599                                    
600     rkpm_set_sram_ops_printch(fn_to_pie(rockchip_pie_chunk, &FUNC(sram_printch)));
601     rkpm_set_ops_printch(ddr_printch);  
602     
603 }
604