blob: de99f3aac2c5618992b8440be9c2ebc054cf95c3 [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
Michael Hennerich14b03202008-05-07 11:41:26 +08002 * Copyright 2004-2008 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -07003 *
Michael Hennerich14b03202008-05-07 11:41:26 +08004 * Licensed under the GPL-2 or later.
Bryan Wu1394f032007-05-06 14:50:22 -07005 */
6
7#include <linux/linkage.h>
8#include <asm/blackfin.h>
Bryan Wu639f6572008-08-27 10:51:02 +08009#include <mach/irq.h>
Michael Hennerich1efc80b2008-07-19 16:57:32 +080010#include <asm/dpmc.h>
Bryan Wu1394f032007-05-06 14:50:22 -070011
12.section .l1.text
Bryan Wu1394f032007-05-06 14:50:22 -070013ENTRY(_sleep_mode)
Mike Frysingerda31d6f2011-06-27 15:43:56 -040014 [--SP] = (R7:4, P5:3);
15 [--SP] = RETS;
Bryan Wu1394f032007-05-06 14:50:22 -070016
17 call _set_sic_iwr;
18
Bryan Wu1394f032007-05-06 14:50:22 -070019 P0.H = hi(PLL_CTL);
20 P0.L = lo(PLL_CTL);
21 R1 = W[P0](z);
22 BITSET (R1, 3);
23 W[P0] = R1.L;
24
25 CLI R2;
26 SSYNC;
27 IDLE;
28 STI R2;
29
30 call _test_pll_locked;
31
32 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080033 R1 = IWR_DISABLE_ALL;
34 R2 = IWR_DISABLE_ALL;
35
Bryan Wu1394f032007-05-06 14:50:22 -070036 call _set_sic_iwr;
37
38 P0.H = hi(PLL_CTL);
39 P0.L = lo(PLL_CTL);
40 R7 = w[p0](z);
41 BITCLR (R7, 3);
42 BITCLR (R7, 5);
43 w[p0] = R7.L;
44 IDLE;
Sonic Zhang72b099e2012-05-17 17:33:00 +080045
46 bfin_init_pm_bench_cycles;
47
Bryan Wu1394f032007-05-06 14:50:22 -070048 call _test_pll_locked;
49
50 RETS = [SP++];
Mike Frysingerda31d6f2011-06-27 15:43:56 -040051 (R7:4, P5:3) = [SP++];
Bryan Wu1394f032007-05-06 14:50:22 -070052 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +080053ENDPROC(_sleep_mode)
Bryan Wu1394f032007-05-06 14:50:22 -070054
Mike Frysingereed7b832011-06-26 23:11:19 -040055/*
56 * This func never returns as it puts the part into hibernate, and
57 * is only called from do_hibernate, so we don't bother saving or
58 * restoring any of the normal C runtime state. When we wake up,
59 * the entry point will be in do_hibernate and not here.
60 *
61 * We accept just one argument -- the value to write to VR_CTL.
62 */
Steven Miao93f89512012-05-16 18:26:10 +080063
Bryan Wu1394f032007-05-06 14:50:22 -070064ENTRY(_hibernate_mode)
Mike Frysingereed7b832011-06-26 23:11:19 -040065 /* Save/setup the regs we need early for minor pipeline optimization */
66 R4 = R0;
Steven Miao93f89512012-05-16 18:26:10 +080067
Mike Frysingereed7b832011-06-26 23:11:19 -040068 P3.H = hi(VR_CTL);
69 P3.L = lo(VR_CTL);
Mike Frysingereed7b832011-06-26 23:11:19 -040070 /* Disable all wakeup sources */
Michael Hennerich1efc80b2008-07-19 16:57:32 +080071 R0 = IWR_DISABLE_ALL;
72 R1 = IWR_DISABLE_ALL;
73 R2 = IWR_DISABLE_ALL;
Bryan Wu1394f032007-05-06 14:50:22 -070074 call _set_sic_iwr;
Michael Hennerich1efc80b2008-07-19 16:57:32 +080075 call _set_dram_srfs;
76 SSYNC;
Bryan Wu1394f032007-05-06 14:50:22 -070077
Mike Frysingereed7b832011-06-26 23:11:19 -040078 /* Finally, we climb into our cave to hibernate */
79 W[P3] = R4.L;
Sonic Zhang72b099e2012-05-17 17:33:00 +080080
81 bfin_init_pm_bench_cycles;
82
Bryan Wu1394f032007-05-06 14:50:22 -070083 CLI R2;
84 IDLE;
Michael Hennerich1efc80b2008-07-19 16:57:32 +080085.Lforever:
86 jump .Lforever;
Mike Frysinger1a8caee2008-07-16 17:07:26 +080087ENDPROC(_hibernate_mode)
Bryan Wu1394f032007-05-06 14:50:22 -070088
Bryan Wu1394f032007-05-06 14:50:22 -070089ENTRY(_sleep_deeper)
Mike Frysingerda31d6f2011-06-27 15:43:56 -040090 [--SP] = (R7:4, P5:3);
91 [--SP] = RETS;
Bryan Wu1394f032007-05-06 14:50:22 -070092
93 CLI R4;
94
95 P3 = R0;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080096 P4 = R1;
97 P5 = R2;
98
Bryan Wu1394f032007-05-06 14:50:22 -070099 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800100 R1 = IWR_DISABLE_ALL;
101 R2 = IWR_DISABLE_ALL;
102
Bryan Wu1394f032007-05-06 14:50:22 -0700103 call _set_sic_iwr;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800104 call _set_dram_srfs; /* Set SDRAM Self Refresh */
Bryan Wu1394f032007-05-06 14:50:22 -0700105
Bryan Wu1394f032007-05-06 14:50:22 -0700106 P0.H = hi(PLL_DIV);
107 P0.L = lo(PLL_DIV);
108 R6 = W[P0](z);
109 R0.L = 0xF;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800110 W[P0] = R0.l; /* Set Max VCO to SCLK divider */
Bryan Wu1394f032007-05-06 14:50:22 -0700111
112 P0.H = hi(PLL_CTL);
113 P0.L = lo(PLL_CTL);
114 R5 = W[P0](z);
Robin Getzf16295e2007-08-03 18:07:17 +0800115 R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800116 W[P0] = R0.l; /* Set Min CLKIN to VCO multiplier */
Bryan Wu1394f032007-05-06 14:50:22 -0700117
118 SSYNC;
119 IDLE;
120
121 call _test_pll_locked;
122
123 P0.H = hi(VR_CTL);
124 P0.L = lo(VR_CTL);
125 R7 = W[P0](z);
126 R1 = 0x6;
127 R1 <<= 16;
128 R2 = 0x0404(Z);
129 R1 = R1|R2;
130
131 R2 = DEPOSIT(R7, R1);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800132 W[P0] = R2; /* Set Min Core Voltage */
Bryan Wu1394f032007-05-06 14:50:22 -0700133
134 SSYNC;
135 IDLE;
136
137 call _test_pll_locked;
138
Michael Hennerich4521ef42008-01-11 17:21:41 +0800139 R0 = P3;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800140 R1 = P4;
141 R3 = P5;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800142 call _set_sic_iwr; /* Set Awake from IDLE */
143
Bryan Wu1394f032007-05-06 14:50:22 -0700144 P0.H = hi(PLL_CTL);
145 P0.L = lo(PLL_CTL);
146 R0 = W[P0](z);
147 BITSET (R0, 3);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800148 W[P0] = R0.L; /* Turn CCLK OFF */
Bryan Wu1394f032007-05-06 14:50:22 -0700149 SSYNC;
150 IDLE;
151
152 call _test_pll_locked;
153
154 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800155 R1 = IWR_DISABLE_ALL;
156 R2 = IWR_DISABLE_ALL;
157
Michael Hennerich4521ef42008-01-11 17:21:41 +0800158 call _set_sic_iwr; /* Set Awake from IDLE PLL */
Bryan Wu1394f032007-05-06 14:50:22 -0700159
160 P0.H = hi(VR_CTL);
161 P0.L = lo(VR_CTL);
162 W[P0]= R7;
163
164 SSYNC;
165 IDLE;
166
Sonic Zhang72b099e2012-05-17 17:33:00 +0800167 bfin_init_pm_bench_cycles;
168
Bryan Wu1394f032007-05-06 14:50:22 -0700169 call _test_pll_locked;
170
171 P0.H = hi(PLL_DIV);
172 P0.L = lo(PLL_DIV);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800173 W[P0]= R6; /* Restore CCLK and SCLK divider */
Bryan Wu1394f032007-05-06 14:50:22 -0700174
175 P0.H = hi(PLL_CTL);
176 P0.L = lo(PLL_CTL);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800177 w[p0] = R5; /* Restore VCO multiplier */
Bryan Wu1394f032007-05-06 14:50:22 -0700178 IDLE;
179 call _test_pll_locked;
180
Michael Hennerich4521ef42008-01-11 17:21:41 +0800181 call _unset_dram_srfs; /* SDRAM Self Refresh Off */
Bryan Wu1394f032007-05-06 14:50:22 -0700182
183 STI R4;
184
185 RETS = [SP++];
Mike Frysingerda31d6f2011-06-27 15:43:56 -0400186 (R7:4, P5:3) = [SP++];
Bryan Wu1394f032007-05-06 14:50:22 -0700187 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800188ENDPROC(_sleep_deeper)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800189
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800190ENTRY(_set_dram_srfs)
191 /* set the dram to self refresh mode */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800192 SSYNC;
193#if defined(EBIU_RSTCTL) /* DDR */
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800194 P0.H = hi(EBIU_RSTCTL);
195 P0.L = lo(EBIU_RSTCTL);
196 R2 = [P0];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800197 BITSET(R2, 3); /* SRREQ enter self-refresh mode */
Bryan Wu1394f032007-05-06 14:50:22 -0700198 [P0] = R2;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800199 SSYNC;
2001:
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800201 R2 = [P0];
202 CC = BITTST(R2, 4);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800203 if !CC JUMP 1b;
204#else /* SDRAM */
205 P0.L = lo(EBIU_SDGCTL);
206 P0.H = hi(EBIU_SDGCTL);
Mike Frysinger9e770f72011-06-27 15:46:40 -0400207 P1.L = lo(EBIU_SDSTAT);
208 P1.H = hi(EBIU_SDSTAT);
209
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800210 R2 = [P0];
211 BITSET(R2, 24); /* SRFS enter self-refresh mode */
212 [P0] = R2;
213 SSYNC;
214
Michael Hennerich1efc80b2008-07-19 16:57:32 +08002151:
Mike Frysinger9e770f72011-06-27 15:46:40 -0400216 R2 = w[P1];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800217 SSYNC;
218 cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
219 if !cc jump 1b;
220
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800221 R2 = [P0];
222 BITCLR(R2, 0); /* SCTLE disable CLKOUT */
223 [P0] = R2;
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800224#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700225 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800226ENDPROC(_set_dram_srfs)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800227
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800228ENTRY(_unset_dram_srfs)
229 /* set the dram out of self refresh mode */
Mike Frysinger9e770f72011-06-27 15:46:40 -0400230
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800231#if defined(EBIU_RSTCTL) /* DDR */
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800232 P0.H = hi(EBIU_RSTCTL);
233 P0.L = lo(EBIU_RSTCTL);
234 R2 = [P0];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800235 BITCLR(R2, 3); /* clear SRREQ bit */
Bryan Wu1394f032007-05-06 14:50:22 -0700236 [P0] = R2;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800237#elif defined(EBIU_SDGCTL) /* SDRAM */
Mike Frysinger9e770f72011-06-27 15:46:40 -0400238 /* release CLKOUT from self-refresh */
239 P0.L = lo(EBIU_SDGCTL);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800240 P0.H = hi(EBIU_SDGCTL);
Mike Frysinger9e770f72011-06-27 15:46:40 -0400241
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800242 R2 = [P0];
243 BITSET(R2, 0); /* SCTLE enable CLKOUT */
244 [P0] = R2
245 SSYNC;
246
Mike Frysinger9e770f72011-06-27 15:46:40 -0400247 /* release SDRAM from self-refresh */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800248 R2 = [P0];
249 BITCLR(R2, 24); /* clear SRFS bit */
250 [P0] = R2
251#endif
Mike Frysinger9e770f72011-06-27 15:46:40 -0400252
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800253 SSYNC;
Bryan Wu1394f032007-05-06 14:50:22 -0700254 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800255ENDPROC(_unset_dram_srfs)
Bryan Wu1394f032007-05-06 14:50:22 -0700256
257ENTRY(_set_sic_iwr)
Mike Frysinger85c27372011-06-26 13:55:24 -0400258#ifdef SIC_IWR0
Mike Frysinger4705a252011-06-26 14:07:17 -0400259 P0.H = hi(SYSMMR_BASE);
260 P0.L = lo(SYSMMR_BASE);
261 [P0 + (SIC_IWR0 - SYSMMR_BASE)] = R0;
262 [P0 + (SIC_IWR1 - SYSMMR_BASE)] = R1;
Mike Frysinger85c27372011-06-26 13:55:24 -0400263# ifdef SIC_IWR2
Mike Frysinger4705a252011-06-26 14:07:17 -0400264 [P0 + (SIC_IWR2 - SYSMMR_BASE)] = R2;
Mike Frysinger85c27372011-06-26 13:55:24 -0400265# endif
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800266#else
Bryan Wu1394f032007-05-06 14:50:22 -0700267 P0.H = hi(SIC_IWR);
268 P0.L = lo(SIC_IWR);
Bryan Wu1394f032007-05-06 14:50:22 -0700269 [P0] = R0;
Mike Frysinger4705a252011-06-26 14:07:17 -0400270#endif
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800271
Bryan Wu1394f032007-05-06 14:50:22 -0700272 SSYNC;
273 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800274ENDPROC(_set_sic_iwr)
Bryan Wu1394f032007-05-06 14:50:22 -0700275
Bryan Wu1394f032007-05-06 14:50:22 -0700276ENTRY(_test_pll_locked)
277 P0.H = hi(PLL_STAT);
278 P0.L = lo(PLL_STAT);
2791:
280 R0 = W[P0] (Z);
281 CC = BITTST(R0,5);
282 IF !CC JUMP 1b;
283 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800284ENDPROC(_test_pll_locked)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800285
286.section .text
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800287ENTRY(_do_hibernate)
Steven Miao93f89512012-05-16 18:26:10 +0800288 bfin_cpu_reg_save;
289 bfin_sys_mmr_save;
290 bfin_core_mmr_save;
Mike Frysingereed7b832011-06-26 23:11:19 -0400291
292 /* Setup args to hibernate mode early for pipeline optimization */
293 R0 = M3;
294 P1.H = _hibernate_mode;
295 P1.L = _hibernate_mode;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800296
297 /* Save Magic, return address and Stack Pointer */
Mike Frysingereed7b832011-06-26 23:11:19 -0400298 P0 = 0;
299 R1.H = 0xDEAD; /* Hibernate Magic */
300 R1.L = 0xBEEF;
301 R2.H = .Lpm_resume_here;
302 R2.L = .Lpm_resume_here;
303 [P0++] = R1; /* Store Hibernate Magic */
304 [P0++] = R2; /* Save Return Address */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800305 [P0++] = SP; /* Save Stack Pointer */
Mike Frysingereed7b832011-06-26 23:11:19 -0400306
307 /* Must use an indirect call as we need to jump to L1 */
308 call (P1); /* Goodbye */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800309
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800310.Lpm_resume_here:
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800311
Steven Miao93f89512012-05-16 18:26:10 +0800312 bfin_core_mmr_restore;
313 bfin_sys_mmr_restore;
314 bfin_cpu_reg_restore;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800315
316 [--sp] = RETI; /* Clear Global Interrupt Disable */
317 SP += 4;
318
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800319 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800320ENDPROC(_do_hibernate)