aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2006-04-02 12:46:25 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-04-02 12:46:25 -0400
commit670c104ae8e7bcc28be0289a16dac2ddfb88b285 (patch)
tree1c55f3a466775fd1d3b73ca28947500221e47134 /arch/arm/mach-omap2
parent6e60e79a1d46eaa3369febc2f6c31e0acfaaae3f (diff)
[ARM] 3430/1: ARM: OMAP: 5/8 Update PM
Patch from Tony Lindgren Update OMAP PM code from linux-omap tree: - Move PM code from plat-omap to mach-omap1 and mach-omap2 by Tony Lindgren - Add minimal PM support for omap24xx by Tony Lindgren and Richard Woodruff - Misc updates to omap1 PM code by Tuukka Tikkanen et al - Updates to the SRAM code needed for PM and FB by Imre Deak Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/pm.c149
-rw-r--r--arch/arm/mach-omap2/sleep.S144
-rw-r--r--arch/arm/mach-omap2/sram-fn.S4
3 files changed, 295 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644
index 000000000000..562168fa2b16
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.c
@@ -0,0 +1,149 @@
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
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
39static struct clk *vclk;
40static void (*omap2_sram_idle)(void);
41static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
42static void (*saved_idle)(void);
43
44void omap2_pm_idle(void)
45{
46 local_irq_disable();
47 local_fiq_disable();
48 if (need_resched()) {
49 local_fiq_enable();
50 local_irq_enable();
51 return;
52 }
53
54 /*
55 * Since an interrupt may set up a timer, we don't want to
56 * reprogram the hardware timer with interrupts enabled.
57 * Re-enable interrupts only after returning from idle.
58 */
59 timer_dyn_reprogram();
60
61 omap2_sram_idle();
62 local_fiq_enable();
63 local_irq_enable();
64}
65
66static int omap2_pm_prepare(suspend_state_t state)
67{
68 int error = 0;
69
70 /* We cannot sleep in idle until we have resumed */
71 saved_idle = pm_idle;
72 pm_idle = NULL;
73
74 switch (state)
75 {
76 case PM_SUSPEND_STANDBY:
77 case PM_SUSPEND_MEM:
78 break;
79
80 case PM_SUSPEND_DISK:
81 return -ENOTSUPP;
82
83 default:
84 return -EINVAL;
85 }
86
87 return error;
88}
89
90static int omap2_pm_enter(suspend_state_t state)
91{
92 switch (state)
93 {
94 case PM_SUSPEND_STANDBY:
95 case PM_SUSPEND_MEM:
96 /* FIXME: Add suspend */
97 break;
98
99 case PM_SUSPEND_DISK:
100 return -ENOTSUPP;
101
102 default:
103 return -EINVAL;
104 }
105
106 return 0;
107}
108
109static int omap2_pm_finish(suspend_state_t state)
110{
111 pm_idle = saved_idle;
112 return 0;
113}
114
115static struct pm_ops omap_pm_ops = {
116 .pm_disk_mode = 0,
117 .prepare = omap2_pm_prepare,
118 .enter = omap2_pm_enter,
119 .finish = omap2_pm_finish,
120};
121
122int __init omap2_pm_init(void)
123{
124 printk("Power Management for TI OMAP.\n");
125
126 vclk = clk_get(NULL, "virt_prcm_set");
127 if (IS_ERR(vclk)) {
128 printk(KERN_ERR "Could not get PM vclk\n");
129 return -ENODEV;
130 }
131
132 /*
133 * We copy the assembler sleep/wakeup routines to SRAM.
134 * These routines need to be in SRAM as that's the only
135 * memory the MPU can see when it wakes up.
136 */
137 omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
138 omap24xx_idle_loop_suspend_sz);
139
140 omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
141 omap24xx_cpu_suspend_sz);
142
143 pm_set_ops(&omap_pm_ops);
144 pm_idle = omap2_pm_idle;
145
146 return 0;
147}
148
149__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644
index 000000000000..00299cbeb911
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep.S
@@ -0,0 +1,144 @@
1/*
2 * linux/arch/arm/mach-omap2/sleep.S
3 *
4 * (C) Copyright 2004
5 * Texas Instruments, <www.ti.com>
6 * Richard Woodruff <r-woodruff2@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <linux/config.h>
25#include <linux/linkage.h>
26#include <asm/assembler.h>
27#include <asm/arch/io.h>
28#include <asm/arch/pm.h>
29
30#define A_32KSYNC_CR_V IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
31#define A_PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
32#define A_PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
33#define A_CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
34#define A_CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
35#define A_CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
36#define A_CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
37
38#define A_SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
39#define A_SDRC_POWER_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
40#define A_SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
41#define A_SDRC0_V (0xC0000000)
42#define A_SDRC_MANUAL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
43
44 .text
45
46/*
47 * Forces OMAP into idle state
48 *
49 * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
50 * for normal idles.
51 *
52 * Note: This code get's copied to internal SRAM at boot. When the OMAP
53 * wakes up it continues execution at the point it went to sleep.
54 */
55ENTRY(omap24xx_idle_loop_suspend)
56 stmfd sp!, {r0, lr} @ save registers on stack
57 mov r0, #0 @ clear for mcr setup
58 mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
59 ldmfd sp!, {r0, pc} @ restore regs and return
60
61ENTRY(omap24xx_idle_loop_suspend_sz)
62 .word . - omap24xx_idle_loop_suspend
63
64/*
65 * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
66 * SDRC shutdown then ARM shutdown. Upon wake MPU is back on so just restore
67 * SDRC.
68 *
69 * Input:
70 * R0 : DLL ctrl value pre-Sleep
71 * R1 : Processor+Revision
72 * 2420: 0x21 = 242xES1, 0x26 = 242xES2.2
73 * 2430: 0x31 = 2430ES1, 0x32 = 2430ES2
74 *
75 * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
76 * when we get called, but the DLL probably isn't. We will wait a bit more in
77 * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
78 * if in unlocked mode.
79 *
80 * For less than 242x-ES2.2 upon wake from a sleep mode where the external
81 * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
82 * clock can pass into the PRCM can cause problems at DSP and IVA.
83 * To work around this the code will switch to the 32kHz source prior to sleep.
84 * Post sleep we will shift back to using the DPLL. Apparently,
85 * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
86 * 3x12MHz + 3x32kHz clocks for a full switch.
87 *
88 * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
89 * at wake
90 */
91ENTRY(omap24xx_cpu_suspend)
92 stmfd sp!, {r0 - r12, lr} @ save registers on stack
93 mov r3, #0x0 @ clear for mrc call
94 mcr p15, 0, r3, c7, c10, 4 @ memory barrier, hope SDR/DDR finished
95 nop
96 nop
97 ldr r3, A_SDRC_POWER @ addr of sdrc power
98 ldr r4, [r3] @ value of sdrc power
99 orr r4, r4, #0x40 @ enable self refresh on idle req
100 mov r5, #0x2000 @ set delay (DPLL relock + DLL relock)
101 str r4, [r3] @ make it so
102 mov r2, #0
103 nop
104 mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
105 nop
106loop:
107 subs r5, r5, #0x1 @ awake, wait just a bit
108 bne loop
109
110 /* The DPLL has on before we take the DDR out of self refresh */
111 bic r4, r4, #0x40 @ now clear self refresh bit.
112 str r4, [r3] @ put vlaue back.
113 ldr r4, A_SDRC0 @ make a clock happen
114 ldr r4, [r4]
115 nop @ start auto refresh only after clk ok
116 movs r0, r0 @ see if DDR or SDR
117 ldrne r1, A_SDRC_DLLA_CTRL_S @ get addr of DLL ctrl
118 strne r0, [r1] @ rewrite DLLA to force DLL reload
119 addne r1, r1, #0x8 @ move to DLLB
120 strne r0, [r1] @ rewrite DLLB to force DLL reload
121
122 mov r5, #0x1000
123loop2:
124 subs r5, r5, #0x1
125 bne loop2
126 /* resume*/
127 ldmfd sp!, {r0 - r12, pc} @ restore regs and return
128
129A_SDRC_POWER:
130 .word A_SDRC_POWER_V
131A_SDRC0:
132 .word A_SDRC0_V
133A_CM_CLKSEL2_PLL_S:
134 .word A_CM_CLKSEL2_PLL_V
135A_CM_CLKEN_PLL:
136 .word A_CM_CLKEN_PLL_V
137A_SDRC_DLLA_CTRL_S:
138 .word A_SDRC_DLLA_CTRL_V
139A_SDRC_MANUAL_S:
140 .word A_SDRC_MANUAL_V
141
142ENTRY(omap24xx_cpu_suspend_sz)
143 .word . - omap24xx_cpu_suspend
144
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
index 2a869e203342..d261e4ff4d9b 100644
--- a/arch/arm/mach-omap2/sram-fn.S
+++ b/arch/arm/mach-omap2/sram-fn.S
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-omap1/sram.S 2 * linux/arch/arm/mach-omap2/sram.S
3 * 3 *
4 * Omap2 specific functions that need to be run in internal SRAM 4 * Omap2 specific functions that need to be run in internal SRAM
5 * 5 *
@@ -28,7 +28,7 @@
28#include <asm/arch/io.h> 28#include <asm/arch/io.h>
29#include <asm/hardware.h> 29#include <asm/hardware.h>
30 30
31#include <asm/arch/prcm.h> 31#include "prcm-regs.h"
32 32
33#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010) 33#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
34 34