aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/pm.c')
-rw-r--r--arch/arm/plat-omap/pm.c632
1 files changed, 632 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
new file mode 100644
index 000000000000..e6536b16c385
--- /dev/null
+++ b/arch/arm/plat-omap/pm.c
@@ -0,0 +1,632 @@
1/*
2 * linux/arch/arm/plat-omap/pm.c
3 *
4 * OMAP Power Management Routines
5 *
6 * Original code for the SA11x0:
7 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
8 *
9 * Modified for the PXA250 by Nicolas Pitre:
10 * Copyright (c) 2002 Monta Vista Software, Inc.
11 *
12 * Modified for the OMAP1510 by David Singleton:
13 * Copyright (c) 2002 Monta Vista Software, Inc.
14 *
15 * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version.
21 *
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
25 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * You should have received a copy of the GNU General Public License along
34 * with this program; if not, write to the Free Software Foundation, Inc.,
35 * 675 Mass Ave, Cambridge, MA 02139, USA.
36 */
37
38#include <linux/pm.h>
39#include <linux/sched.h>
40#include <linux/proc_fs.h>
41#include <linux/pm.h>
42
43#include <asm/io.h>
44#include <asm/mach/time.h>
45#include <asm/mach-types.h>
46
47#include <asm/arch/omap16xx.h>
48#include <asm/arch/pm.h>
49#include <asm/arch/mux.h>
50#include <asm/arch/tc.h>
51#include <asm/arch/tps65010.h>
52
53#include "clock.h"
54
55static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
56static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
57static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
58static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
59
60/*
61 * Let's power down on idle, but only if we are really
62 * idle, because once we start down the path of
63 * going idle we continue to do idle even if we get
64 * a clock tick interrupt . .
65 */
66void omap_pm_idle(void)
67{
68 int (*func_ptr)(void) = 0;
69 unsigned int mask32 = 0;
70
71 /*
72 * If the DSP is being used let's just idle the CPU, the overhead
73 * to wake up from Big Sleep is big, milliseconds versus micro
74 * seconds for wait for interrupt.
75 */
76
77 local_irq_disable();
78 local_fiq_disable();
79 if (need_resched()) {
80 local_fiq_enable();
81 local_irq_enable();
82 return;
83 }
84 mask32 = omap_readl(ARM_SYSST);
85
86 /*
87 * Since an interrupt may set up a timer, we don't want to
88 * reprogram the hardware timer with interrupts enabled.
89 * Re-enable interrupts only after returning from idle.
90 */
91 timer_dyn_reprogram();
92
93 if ((mask32 & DSP_IDLE) == 0) {
94 __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
95 } else {
96
97 if (cpu_is_omap1510()) {
98 func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
99 } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
100 func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
101 } else if (cpu_is_omap5912()) {
102 func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
103 }
104
105 func_ptr();
106 }
107 local_fiq_enable();
108 local_irq_enable();
109}
110
111/*
112 * Configuration of the wakeup event is board specific. For the
113 * moment we put it into this helper function. Later it may move
114 * to board specific files.
115 */
116static void omap_pm_wakeup_setup(void)
117{
118 /*
119 * Enable ARM XOR clock and release peripheral from reset by
120 * writing 1 to PER_EN bit in ARM_RSTCT2, this is required
121 * for UART configuration to use UART2 to wake up.
122 */
123
124 omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
125 omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
126 omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
127
128 /*
129 * Turn off all interrupts except L1-2nd level cascade,
130 * and the L2 wakeup interrupts: keypad and UART2.
131 */
132
133 omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
134
135 if (cpu_is_omap1510()) {
136 omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
137 }
138
139 if (cpu_is_omap16xx()) {
140 omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
141
142 omap_writel(~0x0, OMAP_IH2_1_MIR);
143 omap_writel(~0x0, OMAP_IH2_2_MIR);
144 omap_writel(~0x0, OMAP_IH2_3_MIR);
145 }
146
147 /* New IRQ agreement */
148 omap_writel(1, OMAP_IH1_CONTROL);
149
150 /* external PULL to down, bit 22 = 0 */
151 omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
152}
153
154void omap_pm_suspend(void)
155{
156 unsigned int mask32 = 0;
157 unsigned long arg0 = 0, arg1 = 0;
158 int (*func_ptr)(unsigned short, unsigned short) = 0;
159 unsigned short save_dsp_idlect2;
160
161 printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
162
163 if (machine_is_omap_osk()) {
164 /* Stop LED1 (D9) blink */
165 tps65010_set_led(LED1, OFF);
166 }
167
168 /*
169 * Step 1: turn off interrupts
170 */
171
172 local_irq_disable();
173 local_fiq_disable();
174
175 /*
176 * Step 2: save registers
177 *
178 * The omap is a strange/beautiful device. The caches, memory
179 * and register state are preserved across power saves.
180 * We have to save and restore very little register state to
181 * idle the omap.
182 *
183 * Save interrupt, MPUI, ARM and UPLD control registers.
184 */
185
186 if (cpu_is_omap1510()) {
187 MPUI1510_SAVE(OMAP_IH1_MIR);
188 MPUI1510_SAVE(OMAP_IH2_MIR);
189 MPUI1510_SAVE(MPUI_CTRL);
190 MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
191 MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
192 MPUI1510_SAVE(EMIFS_CONFIG);
193 MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
194 } else if (cpu_is_omap16xx()) {
195 MPUI1610_SAVE(OMAP_IH1_MIR);
196 MPUI1610_SAVE(OMAP_IH2_0_MIR);
197 MPUI1610_SAVE(OMAP_IH2_1_MIR);
198 MPUI1610_SAVE(OMAP_IH2_2_MIR);
199 MPUI1610_SAVE(OMAP_IH2_3_MIR);
200 MPUI1610_SAVE(MPUI_CTRL);
201 MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
202 MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
203 MPUI1610_SAVE(EMIFS_CONFIG);
204 MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
205 }
206
207 ARM_SAVE(ARM_CKCTL);
208 ARM_SAVE(ARM_IDLECT1);
209 ARM_SAVE(ARM_IDLECT2);
210 ARM_SAVE(ARM_EWUPCT);
211 ARM_SAVE(ARM_RSTCT1);
212 ARM_SAVE(ARM_RSTCT2);
213 ARM_SAVE(ARM_SYSST);
214 ULPD_SAVE(ULPD_CLOCK_CTRL);
215 ULPD_SAVE(ULPD_STATUS_REQ);
216
217 /*
218 * Step 3: LOW_PWR signal enabling
219 *
220 * Allow the LOW_PWR signal to be visible on MPUIO5 ball.
221 */
222 if (cpu_is_omap1510()) {
223 /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
224 omap_writew(omap_readw(ULPD_POWER_CTRL) |
225 OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
226 } else if (cpu_is_omap16xx()) {
227 /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
228 omap_writew(omap_readw(ULPD_POWER_CTRL) |
229 OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
230 }
231
232 /* configure LOW_PWR pin */
233 omap_cfg_reg(T20_1610_LOW_PWR);
234
235 /*
236 * Step 4: OMAP DSP Shutdown
237 */
238
239 /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
240 omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
241 ARM_RSTCT1);
242
243 /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
244 omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
245
246 /* Set EN_DSPCK = 0, stop DSP block clock */
247 omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
248
249 /* Stop any DSP domain clocks */
250 omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
251 save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
252 __raw_writew(0, DSP_IDLECT2);
253
254 /*
255 * Step 5: Wakeup Event Setup
256 */
257
258 omap_pm_wakeup_setup();
259
260 /*
261 * Step 6a: ARM and Traffic controller shutdown
262 *
263 * Step 6 starts here with clock and watchdog disable
264 */
265
266 /* stop clocks */
267 mask32 = omap_readl(ARM_IDLECT2);
268 mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
269 mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
270 mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
271 mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
272 mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
273 mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
274 mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
275 mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
276 mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
277 omap_writel(mask32, ARM_IDLECT2);
278
279 /* disable ARM watchdog */
280 omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
281 omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
282
283 /*
284 * Step 6b: ARM and Traffic controller shutdown
285 *
286 * Step 6 continues here. Prepare jump to power management
287 * assembly code in internal SRAM.
288 *
289 * Since the omap_cpu_suspend routine has been copied to
290 * SRAM, we'll do an indirect procedure call to it and pass the
291 * contents of arm_idlect1 and arm_idlect2 so it can restore
292 * them when it wakes up and it will return.
293 */
294
295 arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
296 arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
297
298 if (cpu_is_omap1510()) {
299 func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
300 } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
301 func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
302 } else if (cpu_is_omap5912()) {
303 func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
304 }
305
306 /*
307 * Step 6c: ARM and Traffic controller shutdown
308 *
309 * Jump to assembly code. The processor will stay there
310 * until wake up.
311 */
312
313 func_ptr(arg0, arg1);
314
315 /*
316 * If we are here, processor is woken up!
317 */
318
319 if (cpu_is_omap1510()) {
320 /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
321 omap_writew(omap_readw(ULPD_POWER_CTRL) &
322 ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
323 } else if (cpu_is_omap16xx()) {
324 /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
325 omap_writew(omap_readw(ULPD_POWER_CTRL) &
326 ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
327 }
328
329
330 /* Restore DSP clocks */
331 omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
332 __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
333 ARM_RESTORE(ARM_IDLECT2);
334
335 /*
336 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
337 */
338
339 ARM_RESTORE(ARM_CKCTL);
340 ARM_RESTORE(ARM_EWUPCT);
341 ARM_RESTORE(ARM_RSTCT1);
342 ARM_RESTORE(ARM_RSTCT2);
343 ARM_RESTORE(ARM_SYSST);
344 ULPD_RESTORE(ULPD_CLOCK_CTRL);
345 ULPD_RESTORE(ULPD_STATUS_REQ);
346
347 if (cpu_is_omap1510()) {
348 MPUI1510_RESTORE(MPUI_CTRL);
349 MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
350 MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
351 MPUI1510_RESTORE(EMIFS_CONFIG);
352 MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
353 MPUI1510_RESTORE(OMAP_IH1_MIR);
354 MPUI1510_RESTORE(OMAP_IH2_MIR);
355 } else if (cpu_is_omap16xx()) {
356 MPUI1610_RESTORE(MPUI_CTRL);
357 MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
358 MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
359 MPUI1610_RESTORE(EMIFS_CONFIG);
360 MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
361
362 MPUI1610_RESTORE(OMAP_IH1_MIR);
363 MPUI1610_RESTORE(OMAP_IH2_0_MIR);
364 MPUI1610_RESTORE(OMAP_IH2_1_MIR);
365 MPUI1610_RESTORE(OMAP_IH2_2_MIR);
366 MPUI1610_RESTORE(OMAP_IH2_3_MIR);
367 }
368
369 /*
370 * Reenable interrupts
371 */
372
373 local_irq_enable();
374 local_fiq_enable();
375
376 printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
377
378 if (machine_is_omap_osk()) {
379 /* Let LED1 (D9) blink again */
380 tps65010_set_led(LED1, BLINK);
381 }
382}
383
384#if defined(DEBUG) && defined(CONFIG_PROC_FS)
385static int g_read_completed;
386
387/*
388 * Read system PM registers for debugging
389 */
390static int omap_pm_read_proc(
391 char *page_buffer,
392 char **my_first_byte,
393 off_t virtual_start,
394 int length,
395 int *eof,
396 void *data)
397{
398 int my_buffer_offset = 0;
399 char * const my_base = page_buffer;
400
401 ARM_SAVE(ARM_CKCTL);
402 ARM_SAVE(ARM_IDLECT1);
403 ARM_SAVE(ARM_IDLECT2);
404 ARM_SAVE(ARM_EWUPCT);
405 ARM_SAVE(ARM_RSTCT1);
406 ARM_SAVE(ARM_RSTCT2);
407 ARM_SAVE(ARM_SYSST);
408
409 ULPD_SAVE(ULPD_IT_STATUS);
410 ULPD_SAVE(ULPD_CLOCK_CTRL);
411 ULPD_SAVE(ULPD_SOFT_REQ);
412 ULPD_SAVE(ULPD_STATUS_REQ);
413 ULPD_SAVE(ULPD_DPLL_CTRL);
414 ULPD_SAVE(ULPD_POWER_CTRL);
415
416 if (cpu_is_omap1510()) {
417 MPUI1510_SAVE(MPUI_CTRL);
418 MPUI1510_SAVE(MPUI_DSP_STATUS);
419 MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
420 MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
421 MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
422 MPUI1510_SAVE(EMIFS_CONFIG);
423 } else if (cpu_is_omap16xx()) {
424 MPUI1610_SAVE(MPUI_CTRL);
425 MPUI1610_SAVE(MPUI_DSP_STATUS);
426 MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
427 MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
428 MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
429 MPUI1610_SAVE(EMIFS_CONFIG);
430 }
431
432 if (virtual_start == 0) {
433 g_read_completed = 0;
434
435 my_buffer_offset += sprintf(my_base + my_buffer_offset,
436 "ARM_CKCTL_REG: 0x%-8x \n"
437 "ARM_IDLECT1_REG: 0x%-8x \n"
438 "ARM_IDLECT2_REG: 0x%-8x \n"
439 "ARM_EWUPCT_REG: 0x%-8x \n"
440 "ARM_RSTCT1_REG: 0x%-8x \n"
441 "ARM_RSTCT2_REG: 0x%-8x \n"
442 "ARM_SYSST_REG: 0x%-8x \n"
443 "ULPD_IT_STATUS_REG: 0x%-4x \n"
444 "ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
445 "ULPD_SOFT_REQ_REG: 0x%-4x \n"
446 "ULPD_DPLL_CTRL_REG: 0x%-4x \n"
447 "ULPD_STATUS_REQ_REG: 0x%-4x \n"
448 "ULPD_POWER_CTRL_REG: 0x%-4x \n",
449 ARM_SHOW(ARM_CKCTL),
450 ARM_SHOW(ARM_IDLECT1),
451 ARM_SHOW(ARM_IDLECT2),
452 ARM_SHOW(ARM_EWUPCT),
453 ARM_SHOW(ARM_RSTCT1),
454 ARM_SHOW(ARM_RSTCT2),
455 ARM_SHOW(ARM_SYSST),
456 ULPD_SHOW(ULPD_IT_STATUS),
457 ULPD_SHOW(ULPD_CLOCK_CTRL),
458 ULPD_SHOW(ULPD_SOFT_REQ),
459 ULPD_SHOW(ULPD_DPLL_CTRL),
460 ULPD_SHOW(ULPD_STATUS_REQ),
461 ULPD_SHOW(ULPD_POWER_CTRL));
462
463 if (cpu_is_omap1510()) {
464 my_buffer_offset += sprintf(my_base + my_buffer_offset,
465 "MPUI1510_CTRL_REG 0x%-8x \n"
466 "MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
467 "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
468 "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
469 "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
470 "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
471 MPUI1510_SHOW(MPUI_CTRL),
472 MPUI1510_SHOW(MPUI_DSP_STATUS),
473 MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
474 MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
475 MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
476 MPUI1510_SHOW(EMIFS_CONFIG));
477 } else if (cpu_is_omap16xx()) {
478 my_buffer_offset += sprintf(my_base + my_buffer_offset,
479 "MPUI1610_CTRL_REG 0x%-8x \n"
480 "MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
481 "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
482 "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
483 "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
484 "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
485 MPUI1610_SHOW(MPUI_CTRL),
486 MPUI1610_SHOW(MPUI_DSP_STATUS),
487 MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
488 MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
489 MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
490 MPUI1610_SHOW(EMIFS_CONFIG));
491 }
492
493 g_read_completed++;
494 } else if (g_read_completed >= 1) {
495 *eof = 1;
496 return 0;
497 }
498 g_read_completed++;
499
500 *my_first_byte = page_buffer;
501 return my_buffer_offset;
502}
503
504static void omap_pm_init_proc(void)
505{
506 struct proc_dir_entry *entry;
507
508 entry = create_proc_read_entry("driver/omap_pm",
509 S_IWUSR | S_IRUGO, NULL,
510 omap_pm_read_proc, 0);
511}
512
513#endif /* DEBUG && CONFIG_PROC_FS */
514
515/*
516 * omap_pm_prepare - Do preliminary suspend work.
517 * @state: suspend state we're entering.
518 *
519 */
520//#include <asm/arch/hardware.h>
521
522static int omap_pm_prepare(suspend_state_t state)
523{
524 int error = 0;
525
526 switch (state)
527 {
528 case PM_SUSPEND_STANDBY:
529 case PM_SUSPEND_MEM:
530 break;
531
532 case PM_SUSPEND_DISK:
533 return -ENOTSUPP;
534
535 default:
536 return -EINVAL;
537 }
538
539 return error;
540}
541
542
543/*
544 * omap_pm_enter - Actually enter a sleep state.
545 * @state: State we're entering.
546 *
547 */
548
549static int omap_pm_enter(suspend_state_t state)
550{
551 switch (state)
552 {
553 case PM_SUSPEND_STANDBY:
554 case PM_SUSPEND_MEM:
555 omap_pm_suspend();
556 break;
557
558 case PM_SUSPEND_DISK:
559 return -ENOTSUPP;
560
561 default:
562 return -EINVAL;
563 }
564
565 return 0;
566}
567
568
569/**
570 * omap_pm_finish - Finish up suspend sequence.
571 * @state: State we're coming out of.
572 *
573 * This is called after we wake back up (or if entering the sleep state
574 * failed).
575 */
576
577static int omap_pm_finish(suspend_state_t state)
578{
579 return 0;
580}
581
582
583struct pm_ops omap_pm_ops ={
584 .pm_disk_mode = 0,
585 .prepare = omap_pm_prepare,
586 .enter = omap_pm_enter,
587 .finish = omap_pm_finish,
588};
589
590static int __init omap_pm_init(void)
591{
592 printk("Power Management for TI OMAP.\n");
593 pm_idle = omap_pm_idle;
594 /*
595 * We copy the assembler sleep/wakeup routines to SRAM.
596 * These routines need to be in SRAM as that's the only
597 * memory the MPU can see when it wakes up.
598 */
599
600#ifdef CONFIG_ARCH_OMAP1510
601 if (cpu_is_omap1510()) {
602 memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
603 omap1510_idle_loop_suspend,
604 omap1510_idle_loop_suspend_sz);
605 memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
606 omap1510_cpu_suspend_sz);
607 } else
608#endif
609 if (cpu_is_omap1610() || cpu_is_omap1710()) {
610 memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
611 omap1610_idle_loop_suspend,
612 omap1610_idle_loop_suspend_sz);
613 memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
614 omap1610_cpu_suspend_sz);
615 } else if (cpu_is_omap5912()) {
616 memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
617 omap1610_idle_loop_suspend,
618 omap1610_idle_loop_suspend_sz);
619 memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
620 omap1610_cpu_suspend_sz);
621 }
622
623 pm_set_ops(&omap_pm_ops);
624
625#if defined(DEBUG) && defined(CONFIG_PROC_FS)
626 omap_pm_init_proc();
627#endif
628
629 return 0;
630}
631__initcall(omap_pm_init);
632