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