aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/sleep.S
diff options
context:
space:
mode:
authorSekhar Nori <nsekhar@ti.com>2009-12-17 07:59:31 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2010-02-04 16:29:55 -0500
commitefc1bb8a6fd56f6df5b797dff5156c935175c319 (patch)
tree47b79c7f2d585ae73650acbf9d11058fb00ecb52 /arch/arm/mach-davinci/sleep.S
parent7307d093e6f05d845fc5ce47893c391c819a5c2b (diff)
davinci: add power management support
This patch adds core power management (suspend-to-RAM) support for DaVinci SoCs. The code depends on the the "deepsleep" feature to suspend the SoC and saves power by gating the input clock. The wakeup can be based on an external event as supported by the SoC. Assembly code (in sleep.S) is added to aid gating DDR2 clocks. Code doing this work should not be accessing DDR2. The assembly code is relocated to SRAM by the code in pm.c The support has been validated on DA850/OMAP-L138 only though the code is (hopefully) generic enough that other SoCs supporting deepsleep feature simply requires SoC specific code to start using this driver. Note that all the device drivers don't support suspend/resume still and are being worked on. Signed-off-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/sleep.S')
-rw-r--r--arch/arm/mach-davinci/sleep.S224
1 files changed, 224 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/sleep.S b/arch/arm/mach-davinci/sleep.S
new file mode 100644
index 000000000000..fb5e72b532b0
--- /dev/null
+++ b/arch/arm/mach-davinci/sleep.S
@@ -0,0 +1,224 @@
1/*
2 * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
16 * MA 02111-1307 USA
17 */
18
19/* replicated define because linux/bitops.h cannot be included in assembly */
20#define BIT(nr) (1 << (nr))
21
22#include <linux/linkage.h>
23#include <asm/assembler.h>
24#include <mach/psc.h>
25#include <mach/memory.h>
26
27#include "clock.h"
28
29/* Arbitrary, hardware currently does not update PHYRDY correctly */
30#define PHYRDY_CYCLES 0x1000
31
32/* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
33#define PLL_BYPASS_CYCLES (PLL_BYPASS_TIME * 25)
34#define PLL_RESET_CYCLES (PLL_RESET_TIME * 25)
35#define PLL_LOCK_CYCLES (PLL_LOCK_TIME * 25)
36
37#define DEEPSLEEP_SLEEPENABLE_BIT BIT(31)
38
39 .text
40/*
41 * Move DaVinci into deep sleep state
42 *
43 * Note: This code is copied to internal SRAM by PM code. When the DaVinci
44 * wakes up it continues execution at the point it went to sleep.
45 * Register Usage:
46 * r0: contains virtual base for DDR2 controller
47 * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
48 * r2: contains PSC number for DDR2
49 * r3: contains virtual base DDR2 PLL controller
50 * r4: contains virtual address of the DEEPSLEEP register
51 */
52ENTRY(davinci_cpu_suspend)
53 stmfd sp!, {r0-r12, lr} @ save registers on stack
54
55 ldr ip, CACHE_FLUSH
56 blx ip
57
58 ldmia r0, {r0-r4}
59
60 /*
61 * Switch DDR to self-refresh mode.
62 */
63
64 /* calculate SDRCR address */
65 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
66 bic ip, ip, #DDR2_SRPD_BIT
67 orr ip, ip, #DDR2_LPMODEN_BIT
68 str ip, [r0, #DDR2_SDRCR_OFFSET]
69
70 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
71 orr ip, ip, #DDR2_MCLKSTOPEN_BIT
72 str ip, [r0, #DDR2_SDRCR_OFFSET]
73
74 mov ip, #PHYRDY_CYCLES
751: subs ip, ip, #0x1
76 bne 1b
77
78 /* Disable DDR2 LPSC */
79 mov r7, r0
80 mov r0, #0x2
81 bl davinci_ddr_psc_config
82 mov r0, r7
83
84 /* Disable clock to DDR PHY */
85 ldr ip, [r3, #PLLDIV1]
86 bic ip, ip, #PLLDIV_EN
87 str ip, [r3, #PLLDIV1]
88
89 /* Put the DDR PLL in bypass and power down */
90 ldr ip, [r3, #PLLCTL]
91 bic ip, ip, #PLLCTL_PLLENSRC
92 bic ip, ip, #PLLCTL_PLLEN
93 str ip, [r3, #PLLCTL]
94
95 /* Wait for PLL to switch to bypass */
96 mov ip, #PLL_BYPASS_CYCLES
972: subs ip, ip, #0x1
98 bne 2b
99
100 /* Power down the PLL */
101 ldr ip, [r3, #PLLCTL]
102 orr ip, ip, #PLLCTL_PLLPWRDN
103 str ip, [r3, #PLLCTL]
104
105 /* Go to deep sleep */
106 ldr ip, [r4]
107 orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
108 /* System goes to sleep beyond after this instruction */
109 str ip, [r4]
110
111 /* Wake up from sleep */
112
113 /* Clear sleep enable */
114 ldr ip, [r4]
115 bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
116 str ip, [r4]
117
118 /* initialize the DDR PLL controller */
119
120 /* Put PLL in reset */
121 ldr ip, [r3, #PLLCTL]
122 bic ip, ip, #PLLCTL_PLLRST
123 str ip, [r3, #PLLCTL]
124
125 /* Clear PLL power down */
126 ldr ip, [r3, #PLLCTL]
127 bic ip, ip, #PLLCTL_PLLPWRDN
128 str ip, [r3, #PLLCTL]
129
130 mov ip, #PLL_RESET_CYCLES
1313: subs ip, ip, #0x1
132 bne 3b
133
134 /* Bring PLL out of reset */
135 ldr ip, [r3, #PLLCTL]
136 orr ip, ip, #PLLCTL_PLLRST
137 str ip, [r3, #PLLCTL]
138
139 /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
140 mov ip, #PLL_LOCK_CYCLES
1414: subs ip, ip, #0x1
142 bne 4b
143
144 /* Remove PLL from bypass mode */
145 ldr ip, [r3, #PLLCTL]
146 bic ip, ip, #PLLCTL_PLLENSRC
147 orr ip, ip, #PLLCTL_PLLEN
148 str ip, [r3, #PLLCTL]
149
150 /* Start 2x clock to DDR2 */
151
152 ldr ip, [r3, #PLLDIV1]
153 orr ip, ip, #PLLDIV_EN
154 str ip, [r3, #PLLDIV1]
155
156 /* Enable VCLK */
157
158 /* Enable DDR2 LPSC */
159 mov r7, r0
160 mov r0, #0x3
161 bl davinci_ddr_psc_config
162 mov r0, r7
163
164 /* clear MCLKSTOPEN */
165
166 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
167 bic ip, ip, #DDR2_MCLKSTOPEN_BIT
168 str ip, [r0, #DDR2_SDRCR_OFFSET]
169
170 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
171 bic ip, ip, #DDR2_LPMODEN_BIT
172 str ip, [r0, #DDR2_SDRCR_OFFSET]
173
174 /* Restore registers and return */
175 ldmfd sp!, {r0-r12, pc}
176
177ENDPROC(davinci_cpu_suspend)
178
179/*
180 * Disables or Enables DDR2 LPSC
181 * Register Usage:
182 * r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
183 * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
184 * r2: contains PSC number for DDR2
185 */
186ENTRY(davinci_ddr_psc_config)
187 /* Set next state in mdctl for DDR2 */
188 mov r6, #MDCTL
189 add r6, r6, r2, lsl #2
190 ldr ip, [r1, r6]
191 bic ip, ip, #MDSTAT_STATE_MASK
192 orr ip, ip, r0
193 str ip, [r1, r6]
194
195 /* Enable the Power Domain Transition Command */
196 ldr ip, [r1, #PTCMD]
197 orr ip, ip, #0x1
198 str ip, [r1, #PTCMD]
199
200 /* Check for Transition Complete (PTSTAT) */
201ptstat_done:
202 ldr ip, [r1, #PTSTAT]
203 and ip, ip, #0x1
204 cmp ip, #0x0
205 bne ptstat_done
206
207 /* Check for DDR2 clock disable completion; */
208 mov r6, #MDSTAT
209 add r6, r6, r2, lsl #2
210ddr2clk_stop_done:
211 ldr ip, [r1, r6]
212 and ip, ip, #MDSTAT_STATE_MASK
213 cmp ip, r0
214 bne ddr2clk_stop_done
215
216 mov pc, lr
217ENDPROC(davinci_ddr_psc_config)
218
219CACHE_FLUSH:
220 .word arm926_flush_kern_cache_all
221
222ENTRY(davinci_cpu_suspend_sz)
223 .word . - davinci_cpu_suspend
224ENDPROC(davinci_cpu_suspend_sz)