d7eee99b7e3fef12029d700f9550e6e0a96a3df7
[linux-2.6.git] / arch / arm / mach-omap2 / pm.c
1 /*
2  * linux/arch/arm/mach-omap2/pm.c
3  *
4  * OMAP2 Power Management Routines
5  *
6  * Copyright (C) 2006 Nokia Corporation
7  * Tony Lindgren <tony@atomide.com>
8  *
9  * Copyright (C) 2005 Texas Instruments, Inc.
10  * Richard Woodruff <r-woodruff2@ti.com>
11  *
12  * Based on pm.c for omap1
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18
19 #include <linux/pm.h>
20 #include <linux/sched.h>
21 #include <linux/proc_fs.h>
22 #include <linux/pm.h>
23 #include <linux/interrupt.h>
24 #include <linux/sysfs.h>
25 #include <linux/module.h>
26 #include <linux/delay.h>
27
28 #include <asm/io.h>
29 #include <asm/irq.h>
30 #include <asm/atomic.h>
31 #include <asm/mach/time.h>
32 #include <asm/mach/irq.h>
33 #include <asm/mach-types.h>
34
35 #include <asm/arch/irqs.h>
36 #include <asm/arch/clock.h>
37 #include <asm/arch/sram.h>
38 #include <asm/arch/pm.h>
39
40 #include "prcm-regs.h"
41
42 static struct clk *vclk;
43 static void (*omap2_sram_idle)(void);
44 static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
45 static void (*saved_idle)(void);
46
47 extern void __init pmdomain_init(void);
48 extern void pmdomain_set_autoidle(void);
49
50 static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
51
52 void omap2_pm_idle(void)
53 {
54         local_irq_disable();
55         local_fiq_disable();
56         if (need_resched()) {
57                 local_fiq_enable();
58                 local_irq_enable();
59                 return;
60         }
61
62         /*
63          * Since an interrupt may set up a timer, we don't want to
64          * reprogram the hardware timer with interrupts enabled.
65          * Re-enable interrupts only after returning from idle.
66          */
67         timer_dyn_reprogram();
68
69         omap2_sram_idle();
70         local_fiq_enable();
71         local_irq_enable();
72 }
73
74 static int omap2_pm_prepare(suspend_state_t state)
75 {
76         int error = 0;
77
78         /* We cannot sleep in idle until we have resumed */
79         saved_idle = pm_idle;
80         pm_idle = NULL;
81
82         switch (state)
83         {
84         case PM_SUSPEND_STANDBY:
85         case PM_SUSPEND_MEM:
86                 break;
87
88         case PM_SUSPEND_DISK:
89                 return -ENOTSUPP;
90
91         default:
92                 return -EINVAL;
93         }
94
95         return error;
96 }
97
98 #define INT0_WAKE_MASK  (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) |    \
99                         OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) |     \
100                         OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3))
101
102 #define INT1_WAKE_MASK  (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
103
104 #define INT2_WAKE_MASK  (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) |     \
105                         OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) |      \
106                         OMAP_IRQ_BIT(INT_24XX_UART3_IRQ))
107
108 #define preg(reg)       printk("%s\t(0x%p):\t0x%08x\n", #reg, &reg, reg);
109
110 static void omap2_pm_debug(char * desc)
111 {
112         printk("%s:\n", desc);
113
114         preg(CM_CLKSTCTRL_MPU);
115         preg(CM_CLKSTCTRL_CORE);
116         preg(CM_CLKSTCTRL_GFX);
117         preg(CM_CLKSTCTRL_DSP);
118         preg(CM_CLKSTCTRL_MDM);
119
120         preg(PM_PWSTCTRL_MPU);
121         preg(PM_PWSTCTRL_CORE);
122         preg(PM_PWSTCTRL_GFX);
123         preg(PM_PWSTCTRL_DSP);
124         preg(PM_PWSTCTRL_MDM);
125
126         preg(PM_PWSTST_MPU);
127         preg(PM_PWSTST_CORE);
128         preg(PM_PWSTST_GFX);
129         preg(PM_PWSTST_DSP);
130         preg(PM_PWSTST_MDM);
131
132         preg(CM_AUTOIDLE1_CORE);
133         preg(CM_AUTOIDLE2_CORE);
134         preg(CM_AUTOIDLE3_CORE);
135         preg(CM_AUTOIDLE4_CORE);
136         preg(CM_AUTOIDLE_WKUP);
137         preg(CM_AUTOIDLE_PLL);
138         preg(CM_AUTOIDLE_DSP);
139         preg(CM_AUTOIDLE_MDM);
140
141         preg(CM_ICLKEN1_CORE);
142         preg(CM_ICLKEN2_CORE);
143         preg(CM_ICLKEN3_CORE);
144         preg(CM_ICLKEN4_CORE);
145         preg(CM_ICLKEN_GFX);
146         preg(CM_ICLKEN_WKUP);
147         preg(CM_ICLKEN_DSP);
148         preg(CM_ICLKEN_MDM);
149
150         preg(CM_IDLEST1_CORE);
151         preg(CM_IDLEST2_CORE);
152         preg(CM_IDLEST3_CORE);
153         preg(CM_IDLEST4_CORE);
154         preg(CM_IDLEST_GFX);
155         preg(CM_IDLEST_WKUP);
156         preg(CM_IDLEST_CKGEN);
157         preg(CM_IDLEST_DSP);
158         preg(CM_IDLEST_MDM);
159
160         preg(RM_RSTST_MPU);
161         preg(RM_RSTST_GFX);
162         preg(RM_RSTST_WKUP);
163         preg(RM_RSTST_DSP);
164         preg(RM_RSTST_MDM);
165
166         preg(PM_WKDEP_MPU);
167         preg(PM_WKDEP_CORE);
168         preg(PM_WKDEP_GFX);
169         preg(PM_WKDEP_DSP);
170         preg(PM_WKDEP_MDM);
171
172         preg(CM_FCLKEN_WKUP);
173         preg(CM_ICLKEN_WKUP);
174         preg(CM_IDLEST_WKUP);
175         preg(CM_AUTOIDLE_WKUP);
176         preg(CM_CLKSEL_WKUP);
177
178         preg(PM_WKEN_WKUP);
179         preg(PM_WKST_WKUP);
180 }
181
182 static inline void omap2_pm_save_registers(void)
183 {
184         /* Save interrupt registers */
185         OMAP24XX_SAVE(INTC_MIR0);
186         OMAP24XX_SAVE(INTC_MIR1);
187         OMAP24XX_SAVE(INTC_MIR2);
188
189         /* Save power control registers */
190         OMAP24XX_SAVE(CM_CLKSTCTRL_MPU);
191         OMAP24XX_SAVE(CM_CLKSTCTRL_CORE);
192         OMAP24XX_SAVE(CM_CLKSTCTRL_GFX);
193         OMAP24XX_SAVE(CM_CLKSTCTRL_DSP);
194         OMAP24XX_SAVE(CM_CLKSTCTRL_MDM);
195
196         /* Save power state registers */
197         OMAP24XX_SAVE(PM_PWSTCTRL_MPU);
198         OMAP24XX_SAVE(PM_PWSTCTRL_CORE);
199         OMAP24XX_SAVE(PM_PWSTCTRL_GFX);
200         OMAP24XX_SAVE(PM_PWSTCTRL_DSP);
201         OMAP24XX_SAVE(PM_PWSTCTRL_MDM);
202
203         /* Save autoidle registers */
204         OMAP24XX_SAVE(CM_AUTOIDLE1_CORE);
205         OMAP24XX_SAVE(CM_AUTOIDLE2_CORE);
206         OMAP24XX_SAVE(CM_AUTOIDLE3_CORE);
207         OMAP24XX_SAVE(CM_AUTOIDLE4_CORE);
208         OMAP24XX_SAVE(CM_AUTOIDLE_WKUP);
209         OMAP24XX_SAVE(CM_AUTOIDLE_PLL);
210         OMAP24XX_SAVE(CM_AUTOIDLE_DSP);
211         OMAP24XX_SAVE(CM_AUTOIDLE_MDM);
212
213         /* Save idle state registers */
214         OMAP24XX_SAVE(CM_IDLEST1_CORE);
215         OMAP24XX_SAVE(CM_IDLEST2_CORE);
216         OMAP24XX_SAVE(CM_IDLEST3_CORE);
217         OMAP24XX_SAVE(CM_IDLEST4_CORE);
218         OMAP24XX_SAVE(CM_IDLEST_GFX);
219         OMAP24XX_SAVE(CM_IDLEST_WKUP);
220         OMAP24XX_SAVE(CM_IDLEST_CKGEN);
221         OMAP24XX_SAVE(CM_IDLEST_DSP);
222         OMAP24XX_SAVE(CM_IDLEST_MDM);
223
224         /* Save clock registers */
225         OMAP24XX_SAVE(CM_FCLKEN1_CORE);
226         OMAP24XX_SAVE(CM_FCLKEN2_CORE);
227         OMAP24XX_SAVE(CM_ICLKEN1_CORE);
228         OMAP24XX_SAVE(CM_ICLKEN2_CORE);
229         OMAP24XX_SAVE(CM_ICLKEN3_CORE);
230         OMAP24XX_SAVE(CM_ICLKEN4_CORE);
231 }
232
233 static inline void omap2_pm_restore_registers(void)
234 {
235         /* Restore clock state registers */
236         OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU);
237         OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE);
238         OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX);
239         OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP);
240         OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM);
241
242         /* Restore power state registers */
243         OMAP24XX_RESTORE(PM_PWSTCTRL_MPU);
244         OMAP24XX_RESTORE(PM_PWSTCTRL_CORE);
245         OMAP24XX_RESTORE(PM_PWSTCTRL_GFX);
246         OMAP24XX_RESTORE(PM_PWSTCTRL_DSP);
247         OMAP24XX_RESTORE(PM_PWSTCTRL_MDM);
248
249         /* Restore idle state registers */
250         OMAP24XX_RESTORE(CM_IDLEST1_CORE);
251         OMAP24XX_RESTORE(CM_IDLEST2_CORE);
252         OMAP24XX_RESTORE(CM_IDLEST3_CORE);
253         OMAP24XX_RESTORE(CM_IDLEST4_CORE);
254         OMAP24XX_RESTORE(CM_IDLEST_GFX);
255         OMAP24XX_RESTORE(CM_IDLEST_WKUP);
256         OMAP24XX_RESTORE(CM_IDLEST_CKGEN);
257         OMAP24XX_RESTORE(CM_IDLEST_DSP);
258         OMAP24XX_RESTORE(CM_IDLEST_MDM);
259
260         /* Restore autoidle registers */
261         OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE);
262         OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE);
263         OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE);
264         OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE);
265         OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP);
266         OMAP24XX_RESTORE(CM_AUTOIDLE_PLL);
267         OMAP24XX_RESTORE(CM_AUTOIDLE_DSP);
268         OMAP24XX_RESTORE(CM_AUTOIDLE_MDM);
269
270         /* Restore clock registers */
271         OMAP24XX_RESTORE(CM_FCLKEN1_CORE);
272         OMAP24XX_RESTORE(CM_FCLKEN2_CORE);
273         OMAP24XX_RESTORE(CM_ICLKEN1_CORE);
274         OMAP24XX_RESTORE(CM_ICLKEN2_CORE);
275         OMAP24XX_RESTORE(CM_ICLKEN3_CORE);
276         OMAP24XX_RESTORE(CM_ICLKEN4_CORE);
277
278         /* REVISIT: Clear interrupts here */
279
280         /* Restore interrupt registers */
281         OMAP24XX_RESTORE(INTC_MIR0);
282         OMAP24XX_RESTORE(INTC_MIR1);
283         OMAP24XX_RESTORE(INTC_MIR2);
284 }
285
286 static int omap2_pm_suspend(void)
287 {
288         int processor_type = 0;
289
290         /* REVISIT: 0x21 or 0x26? */
291         if (cpu_is_omap2420())
292                 processor_type = 0x21;
293
294         if (!processor_type)
295                 return -ENOTSUPP;
296
297         local_irq_disable();
298         local_fiq_disable();
299
300         omap2_pm_save_registers();
301
302         /* Disable interrupts except for the wake events */
303         INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK;
304         INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK;
305         INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK;
306
307         pmdomain_set_autoidle();
308
309         /* Clear old wake-up events */
310         PM_WKST1_CORE = 0;
311         PM_WKST2_CORE = 0;
312         PM_WKST_WKUP = 0;
313
314         /* Enable wake-up events */
315         PM_WKEN1_CORE = (1 << 22) | (1 << 21);  /* UART1 & 2 */
316         PM_WKEN2_CORE = (1 << 2);               /* UART3 */
317         PM_WKEN_WKUP = (1 << 2) | (1 << 0);     /* GPIO & GPT1 */
318
319         /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
320          * in the SRAM suspend code */
321         CM_FCLKEN1_CORE = 0;
322         CM_FCLKEN2_CORE = 0;
323         CM_ICLKEN1_CORE = 0;
324         CM_ICLKEN3_CORE = 0;
325         CM_ICLKEN4_CORE = 0;
326
327         omap2_pm_debug("Status before suspend");
328
329         /* Must wait for serial buffers to clear */
330         mdelay(200);
331
332         /* Jump to SRAM suspend code
333          * REVISIT: When is this SDRC_DLLB_CTRL?
334          */
335         omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type);
336
337         /* Back from sleep */
338         omap2_pm_restore_registers();
339
340         local_fiq_enable();
341         local_irq_enable();
342
343         return 0;
344 }
345
346 static int omap2_pm_enter(suspend_state_t state)
347 {
348         int ret = 0;
349
350         switch (state)
351         {
352         case PM_SUSPEND_STANDBY:
353         case PM_SUSPEND_MEM:
354                 ret = omap2_pm_suspend();
355                 break;
356         case PM_SUSPEND_DISK:
357                 ret = -ENOTSUPP;
358                 break;
359         default:
360                 ret = -EINVAL;
361         }
362
363         return ret;
364 }
365
366 static int omap2_pm_finish(suspend_state_t state)
367 {
368         pm_idle = saved_idle;
369         return 0;
370 }
371
372 static struct pm_ops omap_pm_ops = {
373         .pm_disk_mode   = 0,
374         .prepare        = omap2_pm_prepare,
375         .enter          = omap2_pm_enter,
376         .finish         = omap2_pm_finish,
377 };
378
379 int __init omap2_pm_init(void)
380 {
381         printk("Power Management for TI OMAP.\n");
382
383         vclk = clk_get(NULL, "virt_prcm_set");
384         if (IS_ERR(vclk)) {
385                 printk(KERN_ERR "Could not get PM vclk\n");
386                 return -ENODEV;
387         }
388
389         /*
390          * We copy the assembler sleep/wakeup routines to SRAM.
391          * These routines need to be in SRAM as that's the only
392          * memory the MPU can see when it wakes up.
393          */
394         omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
395                                          omap24xx_idle_loop_suspend_sz);
396
397         omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
398                                             omap24xx_cpu_suspend_sz);
399
400         pm_set_ops(&omap_pm_ops);
401         pm_idle = omap2_pm_idle;
402
403         pmdomain_init();
404
405         return 0;
406 }
407
408 __initcall(omap2_pm_init);