db1e8cffbfd91532bad2443cd2d9b0c0835d63b2
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk29 / pm.c
1 #define DEBUG
2
3 #include <linux/clk.h>
4 #include <linux/delay.h>
5 #include <linux/err.h>
6 #include <linux/kernel.h>
7 #include <linux/init.h>
8 #include <linux/pm.h>
9 #include <linux/suspend.h>
10 #ifdef CONFIG_RK29_PWM_REGULATOR
11 #include <linux/regulator/rk29-pwm-regulator.h>
12 #endif
13 #include <linux/io.h>
14 #include <linux/wakelock.h>
15 #include <asm/tlbflush.h>
16 #include <asm/hardware/gic.h>
17
18 #include <mach/rk29_iomap.h>
19 #include <mach/cru.h>
20 #include <mach/pmu.h>
21 #include <mach/board.h>
22 #include <mach/system.h>
23 #include <mach/sram.h>
24 #include <mach/gpio.h>
25
26 #define cru_readl(offset)       readl(RK29_CRU_BASE + offset)
27 #define cru_writel(v, offset)   do { writel(v, RK29_CRU_BASE + offset); readl(RK29_CRU_BASE + offset); } while (0)
28 #define pmu_readl(offset)       readl(RK29_PMU_BASE + offset)
29 #define pmu_writel(v, offset)   do { writel(v, RK29_PMU_BASE + offset); readl(RK29_PMU_BASE + offset); } while (0)
30 static unsigned long save_sp;
31
32 #define LOOPS_PER_USEC  13
33 #define LOOP(loops) do { int i = loops; barrier(); while (i--) barrier(); } while (0)
34
35 static inline void delay_500ns(void)
36 {
37         LOOP(LOOPS_PER_USEC);
38 }
39
40 static inline void delay_300us(void)
41 {
42         LOOP(300 * LOOPS_PER_USEC);
43 }
44
45 extern void ddr_suspend(void);
46 extern void ddr_resume(void);
47
48 #ifdef DEBUG
49 static void inline printch(char byte)
50 {
51         unsigned long flags;
52         unsigned int delay;
53         u32 gate1, gate2;
54
55         local_irq_save(flags);
56         gate1 = cru_readl(CRU_CLKGATE1_CON);
57         gate2 = cru_readl(CRU_CLKGATE2_CON);
58         cru_writel(gate1 & ~((1 << CLK_GATE_PCLK_PEIRPH % 32) | (1 << CLK_GATE_ACLK_PEIRPH % 32) | (1 << CLK_GATE_ACLK_CPU_PERI % 32)), CRU_CLKGATE1_CON);
59         cru_writel(gate2 & ~(1 << CLK_GATE_UART1 % 32), CRU_CLKGATE2_CON);
60         delay_500ns();
61
62         writel(byte, RK29_UART1_BASE);
63
64         /* loop check LSR[6], Transmitter Empty bit */
65         while (!(readl(RK29_UART1_BASE + 0x14) & 0x40))
66                 barrier();
67
68         cru_writel(gate2, CRU_CLKGATE2_CON);
69         cru_writel(gate1, CRU_CLKGATE1_CON);
70         local_irq_restore(flags);
71         if (byte == '\n')
72                 printch('\r');
73 }
74
75 static void inline printascii(const char *s)
76 {
77         while (*s) {
78                 printch(*s);
79                 s++;
80         }
81 }
82
83 static void inline printhex(unsigned int hex)
84 {
85         int i = 8;
86         printch('0');
87         printch('x');
88         while (i--) {
89                 unsigned char c = (hex & 0xF0000000) >> 28;
90                 printch(c < 0xa ? c + '0' : c - 0xa + 'a');
91                 hex <<= 4;
92         }
93 }
94 #else
95 static void inline printch(char byte) {}
96 static void inline printascii(const char *s) {}
97 static void inline printhex(unsigned int hex) {}
98 #endif /* DEBUG */
99
100 #ifdef CONFIG_RK29_PWM_REGULATOR
101 #define pwm_write_reg(addr, val)        __raw_writel(val, addr + (RK29_PWM_BASE + 2*0x10))
102 #define pwm_read_reg(addr)              __raw_readl(addr + (RK29_PWM_BASE + 2*0x10))
103
104 static u32 __sramdata pwm_lrc, pwm_hrc;
105 static void __sramfunc rk29_set_core_voltage(int uV)
106 {
107         u32 gate1;
108
109         gate1 = cru_readl(CRU_CLKGATE1_CON);
110         cru_writel(gate1 & ~((1 << CLK_GATE_PCLK_PEIRPH % 32) | (1 << CLK_GATE_ACLK_PEIRPH % 32) | (1 << CLK_GATE_ACLK_CPU_PERI % 32)), CRU_CLKGATE1_CON);
111
112         /* iomux pwm2 */
113         writel((readl(RK29_GRF_BASE + 0x58) & ~(0x3<<6)) | (0x2<<6), RK29_GRF_BASE + 0x58);
114
115         if (uV) {
116                 pwm_lrc = pwm_read_reg(PWM_REG_LRC);
117                 pwm_hrc = pwm_read_reg(PWM_REG_HRC);
118         }
119
120         pwm_write_reg(PWM_REG_CTRL, PWM_DIV|PWM_RESET);
121         if (uV == 1000000) {
122                 pwm_write_reg(PWM_REG_LRC, 12);
123                 pwm_write_reg(PWM_REG_HRC, 10);
124         } else {
125                 pwm_write_reg(PWM_REG_LRC, pwm_lrc);
126                 pwm_write_reg(PWM_REG_HRC, pwm_hrc);
127         }
128         pwm_write_reg(PWM_REG_CNTR, 0);
129         pwm_write_reg(PWM_REG_CTRL, PWM_DIV|PWM_ENABLE|PWM_TimeEN);
130
131         LOOP(5 * 1000 * LOOPS_PER_USEC); /* delay 5ms */
132
133         cru_writel(gate1, CRU_CLKGATE1_CON);
134 }
135 #endif /* CONFIG_RK29_PWM_REGULATOR */
136
137 static void __sramfunc rk29_sram_suspend(void)
138 {
139         u32 clksel0;
140
141         printch('5');
142         ddr_suspend();
143
144         printch('6');
145 #ifdef CONFIG_RK29_PWM_REGULATOR
146         rk29_set_core_voltage(1000000);
147 #endif
148         printch('7');
149         clksel0 = cru_readl(CRU_CLKSEL0_CON);
150         /* set arm clk 24MHz/32 = 750KHz */
151         cru_writel(clksel0 | 0x1F, CRU_CLKSEL0_CON);
152
153         printch('8');
154         asm("wfi");
155         printch('8');
156
157         /* resume arm clk */
158         cru_writel(clksel0, CRU_CLKSEL0_CON);
159         printch('7');
160
161 #ifdef CONFIG_RK29_PWM_REGULATOR
162         rk29_set_core_voltage(0);
163 #endif
164         printch('6');
165
166         ddr_resume();
167         printch('5');
168 }
169
170 static void noinline rk29_suspend(void)
171 {
172         DDR_SAVE_SP(save_sp);
173         rk29_sram_suspend();
174         DDR_RESTORE_SP(save_sp);
175 }
176
177 static void dump_irq(void)
178 {
179         u32 irq_gpio = (readl(RK29_GICPERI_BASE + GIC_DIST_PENDING_SET + 8) >> 23) & 0x7F;
180         printk("wakeup irq: %08x %08x %01x\n",
181                 readl(RK29_GICPERI_BASE + GIC_DIST_PENDING_SET + 4),
182                 readl(RK29_GICPERI_BASE + GIC_DIST_PENDING_SET + 8),
183                 readl(RK29_GICPERI_BASE + GIC_DIST_PENDING_SET + 12) & 0xf);
184         if (irq_gpio & 1)
185                 printk("wakeup gpio0: %08x\n", readl(RK29_GPIO0_BASE + GPIO_INT_STATUS));
186         if (irq_gpio & 2)
187                 printk("wakeup gpio1: %08x\n", readl(RK29_GPIO1_BASE + GPIO_INT_STATUS));
188         if (irq_gpio & 4)
189                 printk("wakeup gpio2: %08x\n", readl(RK29_GPIO2_BASE + GPIO_INT_STATUS));
190         if (irq_gpio & 8)
191                 printk("wakeup gpio3: %08x\n", readl(RK29_GPIO3_BASE + GPIO_INT_STATUS));
192         if (irq_gpio & 0x10)
193                 printk("wakeup gpio4: %08x\n", readl(RK29_GPIO4_BASE + GPIO_INT_STATUS));
194         if (irq_gpio & 0x20)
195                 printk("wakeup gpio5: %08x\n", readl(RK29_GPIO5_BASE + GPIO_INT_STATUS));
196         if (irq_gpio & 0x40)
197                 printk("wakeup gpio6: %08x\n", readl(RK29_GPIO6_BASE + GPIO_INT_STATUS));
198 }
199
200 static int rk29_pm_enter(suspend_state_t state)
201 {
202         u32 apll, cpll, gpll, mode, clksel0;
203         u32 clkgate[4];
204         printch('0');
205
206 #ifdef CONFIG_RK29_PWM_REGULATOR
207         /* touch TLB */
208         flush_tlb_all();
209         readl(RK29_PWM_BASE);
210         readl(RK29_GRF_BASE);
211 #endif
212
213         /* disable clock */
214         clkgate[0] = cru_readl(CRU_CLKGATE0_CON);
215         clkgate[1] = cru_readl(CRU_CLKGATE1_CON);
216         clkgate[2] = cru_readl(CRU_CLKGATE2_CON);
217         clkgate[3] = cru_clkgate3_con_mirror;
218         cru_writel(~((1 << CLK_GATE_CORE)
219                    | (1 << CLK_GATE_ACLK_CPU)
220                    | (1 << CLK_GATE_ACLK_CPU2)
221                    | (1 << CLK_GATE_PCLK_CPU)
222                    | (1 << CLK_GATE_GIC)
223                    | (1 << CLK_GATE_INTMEM)
224                    | (1 << CLK_GATE_DDR_PHY)
225                    | (1 << CLK_GATE_DDR_REG)
226                    | (1 << CLK_GATE_DDR_CPU)
227                    | (1 << CLK_GATE_GPIO0)
228                    | (1 << CLK_GATE_RTC)
229                    | (1 << CLK_GATE_GRF)
230                    ) | clkgate[0], CRU_CLKGATE0_CON);
231         cru_writel(~0, CRU_CLKGATE1_CON);
232         cru_writel(~((1 << CLK_GATE_GPIO1 % 32)
233                    | (1 << CLK_GATE_GPIO2 % 32)
234                    | (1 << CLK_GATE_GPIO3 % 32)
235                    | (1 << CLK_GATE_GPIO4 % 32)
236                    | (1 << CLK_GATE_GPIO5 % 32)
237                    | (1 << CLK_GATE_GPIO6 % 32)
238                    | (1 << CLK_GATE_PWM % 32)
239                    ) | clkgate[2], CRU_CLKGATE2_CON);
240         cru_writel(~0, CRU_CLKGATE3_CON);
241         printch('1');
242
243         mode = cru_readl(CRU_MODE_CON);
244         clksel0 = cru_readl(CRU_CLKSEL0_CON);
245
246         /* suspend arm pll */
247         apll = cru_readl(CRU_APLL_CON);
248         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON);
249         cru_writel(apll | PLL_BYPASS, CRU_APLL_CON);
250         cru_writel(apll | PLL_PD | PLL_BYPASS, CRU_APLL_CON);
251         delay_500ns();
252         /* set core = aclk_cpu = hclk_cpu = pclk_cpu = 24MHz */
253         cru_writel(clksel0 & 0xFFFFF000, CRU_CLKSEL0_CON);
254         printch('2');
255
256         /* suspend codec pll */
257         cpll = cru_readl(CRU_CPLL_CON);
258         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_SLOW, CRU_MODE_CON);
259         cru_writel(cpll | PLL_BYPASS, CRU_CPLL_CON);
260         cru_writel(cpll | PLL_PD | PLL_BYPASS, CRU_CPLL_CON);
261         delay_500ns();
262         printch('3');
263
264         /* suspend general pll */
265         gpll = cru_readl(CRU_GPLL_CON);
266         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | CRU_GENERAL_MODE_SLOW, CRU_MODE_CON);
267         cru_writel(gpll | PLL_BYPASS, CRU_GPLL_CON);
268         cru_writel(gpll | PLL_PD | PLL_BYPASS, CRU_GPLL_CON);
269         delay_500ns();
270         /* set aclk_periph = hclk_periph = pclk_periph = 24MHz */
271         cru_writel(clksel0 & ~0x7FC000, CRU_CLKSEL0_CON);
272
273         printch('4');
274         rk29_suspend();
275         printch('4');
276
277         /* resume general pll */
278         cru_writel(gpll, CRU_GPLL_CON);
279         delay_300us();
280         /* restore aclk_periph/hclk_periph/pclk_periph */
281         cru_writel(cru_readl(CRU_CLKSEL0_CON) | (clksel0 & 0x7FC000), CRU_CLKSEL0_CON);
282         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | (mode & CRU_GENERAL_MODE_MASK), CRU_MODE_CON);
283         printch('3');
284
285         /* resume codec pll */
286         cru_writel(cpll, CRU_CPLL_CON);
287         delay_300us();
288         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | (mode & CRU_CODEC_MODE_MASK), CRU_MODE_CON);
289         printch('2');
290
291         /* resume arm pll */
292         cru_writel(apll, CRU_APLL_CON);
293         delay_300us();
294         /* restore core/aclk_cpu/hclk_cpu/pclk_cpu */
295         cru_writel(cru_readl(CRU_CLKSEL0_CON) | (clksel0 & 0xFFF), CRU_CLKSEL0_CON);
296         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | (mode & CRU_CPU_MODE_MASK), CRU_MODE_CON);
297         printch('1');
298
299         /* enable clock */
300         cru_writel(clkgate[0], CRU_CLKGATE0_CON);
301         cru_writel(clkgate[1], CRU_CLKGATE1_CON);
302         cru_writel(clkgate[2], CRU_CLKGATE2_CON);
303         cru_writel(clkgate[3], CRU_CLKGATE3_CON);
304         printascii("0\n");
305
306         dump_irq();
307         return 0;
308 }
309
310 static int rk29_pm_prepare(void)
311 {
312         /* disable entering rk29_idle() by disable_hlt() */
313         disable_hlt();
314         return 0;
315 }
316
317 static void rk29_pm_finish(void)
318 {
319         enable_hlt();
320 }
321
322 static struct platform_suspend_ops rk29_pm_ops = {
323         .enter          = rk29_pm_enter,
324         .valid          = suspend_valid_only_mem,
325         .prepare        = rk29_pm_prepare,
326         .finish         = rk29_pm_finish,
327 };
328
329 static void rk29_idle(void)
330 {
331         if (!need_resched()) {
332                 int allow_sleep = 1;
333 #ifdef CONFIG_HAS_WAKELOCK
334                 allow_sleep = !has_wake_lock(WAKE_LOCK_IDLE);
335 #endif
336                 if (allow_sleep) {
337                         u32 mode_con = cru_readl(CRU_MODE_CON);
338                         cru_writel((mode_con & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON);
339                         arch_idle();
340                         cru_writel(mode_con, CRU_MODE_CON);
341                 } else {
342                         arch_idle();
343                 }
344         }
345         local_irq_enable();
346 }
347
348 static int __init rk29_pm_init(void)
349 {
350         suspend_set_ops(&rk29_pm_ops);
351
352         /* set idle function */
353         pm_idle = rk29_idle;
354
355         return 0;
356 }
357 __initcall(rk29_pm_init);