blob: 2bec509cd7e24210513b8fa606a04fb9c882882a [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
Steven Miao93f89512012-05-16 18:26:10 +080013#ifndef CONFIG_BF60x
Bryan Wu1394f032007-05-06 14:50:22 -070014ENTRY(_sleep_mode)
Mike Frysingerda31d6f2011-06-27 15:43:56 -040015 [--SP] = (R7:4, P5:3);
16 [--SP] = RETS;
Bryan Wu1394f032007-05-06 14:50:22 -070017
18 call _set_sic_iwr;
19
Bryan Wu1394f032007-05-06 14:50:22 -070020 P0.H = hi(PLL_CTL);
21 P0.L = lo(PLL_CTL);
22 R1 = W[P0](z);
23 BITSET (R1, 3);
24 W[P0] = R1.L;
25
26 CLI R2;
27 SSYNC;
28 IDLE;
29 STI R2;
30
31 call _test_pll_locked;
32
33 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080034 R1 = IWR_DISABLE_ALL;
35 R2 = IWR_DISABLE_ALL;
36
Bryan Wu1394f032007-05-06 14:50:22 -070037 call _set_sic_iwr;
38
39 P0.H = hi(PLL_CTL);
40 P0.L = lo(PLL_CTL);
41 R7 = w[p0](z);
42 BITCLR (R7, 3);
43 BITCLR (R7, 5);
44 w[p0] = R7.L;
45 IDLE;
46 call _test_pll_locked;
47
48 RETS = [SP++];
Mike Frysingerda31d6f2011-06-27 15:43:56 -040049 (R7:4, P5:3) = [SP++];
Bryan Wu1394f032007-05-06 14:50:22 -070050 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +080051ENDPROC(_sleep_mode)
Steven Miao93f89512012-05-16 18:26:10 +080052#endif
Bryan Wu1394f032007-05-06 14:50:22 -070053
Mike Frysingereed7b832011-06-26 23:11:19 -040054/*
55 * This func never returns as it puts the part into hibernate, and
56 * is only called from do_hibernate, so we don't bother saving or
57 * restoring any of the normal C runtime state. When we wake up,
58 * the entry point will be in do_hibernate and not here.
59 *
60 * We accept just one argument -- the value to write to VR_CTL.
61 */
Steven Miao93f89512012-05-16 18:26:10 +080062
Bryan Wu1394f032007-05-06 14:50:22 -070063ENTRY(_hibernate_mode)
Mike Frysingereed7b832011-06-26 23:11:19 -040064 /* Save/setup the regs we need early for minor pipeline optimization */
65 R4 = R0;
Steven Miao93f89512012-05-16 18:26:10 +080066
67#ifndef CONFIG_BF60x
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;
Steven Miao93f89512012-05-16 18:26:10 +080077#endif
Bryan Wu1394f032007-05-06 14:50:22 -070078
Mike Frysingereed7b832011-06-26 23:11:19 -040079 /* Finally, we climb into our cave to hibernate */
80 W[P3] = R4.L;
Bryan Wu1394f032007-05-06 14:50:22 -070081 CLI R2;
82 IDLE;
Michael Hennerich1efc80b2008-07-19 16:57:32 +080083.Lforever:
84 jump .Lforever;
Mike Frysinger1a8caee2008-07-16 17:07:26 +080085ENDPROC(_hibernate_mode)
Bryan Wu1394f032007-05-06 14:50:22 -070086
Steven Miao93f89512012-05-16 18:26:10 +080087#ifndef CONFIG_BF60x
Bryan Wu1394f032007-05-06 14:50:22 -070088ENTRY(_sleep_deeper)
Mike Frysingerda31d6f2011-06-27 15:43:56 -040089 [--SP] = (R7:4, P5:3);
90 [--SP] = RETS;
Bryan Wu1394f032007-05-06 14:50:22 -070091
92 CLI R4;
93
94 P3 = R0;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080095 P4 = R1;
96 P5 = R2;
97
Bryan Wu1394f032007-05-06 14:50:22 -070098 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080099 R1 = IWR_DISABLE_ALL;
100 R2 = IWR_DISABLE_ALL;
101
Bryan Wu1394f032007-05-06 14:50:22 -0700102 call _set_sic_iwr;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800103 call _set_dram_srfs; /* Set SDRAM Self Refresh */
Bryan Wu1394f032007-05-06 14:50:22 -0700104
Bryan Wu1394f032007-05-06 14:50:22 -0700105 P0.H = hi(PLL_DIV);
106 P0.L = lo(PLL_DIV);
107 R6 = W[P0](z);
108 R0.L = 0xF;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800109 W[P0] = R0.l; /* Set Max VCO to SCLK divider */
Bryan Wu1394f032007-05-06 14:50:22 -0700110
111 P0.H = hi(PLL_CTL);
112 P0.L = lo(PLL_CTL);
113 R5 = W[P0](z);
Robin Getzf16295e2007-08-03 18:07:17 +0800114 R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800115 W[P0] = R0.l; /* Set Min CLKIN to VCO multiplier */
Bryan Wu1394f032007-05-06 14:50:22 -0700116
117 SSYNC;
118 IDLE;
119
120 call _test_pll_locked;
121
122 P0.H = hi(VR_CTL);
123 P0.L = lo(VR_CTL);
124 R7 = W[P0](z);
125 R1 = 0x6;
126 R1 <<= 16;
127 R2 = 0x0404(Z);
128 R1 = R1|R2;
129
130 R2 = DEPOSIT(R7, R1);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800131 W[P0] = R2; /* Set Min Core Voltage */
Bryan Wu1394f032007-05-06 14:50:22 -0700132
133 SSYNC;
134 IDLE;
135
136 call _test_pll_locked;
137
Michael Hennerich4521ef42008-01-11 17:21:41 +0800138 R0 = P3;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800139 R1 = P4;
140 R3 = P5;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800141 call _set_sic_iwr; /* Set Awake from IDLE */
142
Bryan Wu1394f032007-05-06 14:50:22 -0700143 P0.H = hi(PLL_CTL);
144 P0.L = lo(PLL_CTL);
145 R0 = W[P0](z);
146 BITSET (R0, 3);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800147 W[P0] = R0.L; /* Turn CCLK OFF */
Bryan Wu1394f032007-05-06 14:50:22 -0700148 SSYNC;
149 IDLE;
150
151 call _test_pll_locked;
152
153 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800154 R1 = IWR_DISABLE_ALL;
155 R2 = IWR_DISABLE_ALL;
156
Michael Hennerich4521ef42008-01-11 17:21:41 +0800157 call _set_sic_iwr; /* Set Awake from IDLE PLL */
Bryan Wu1394f032007-05-06 14:50:22 -0700158
159 P0.H = hi(VR_CTL);
160 P0.L = lo(VR_CTL);
161 W[P0]= R7;
162
163 SSYNC;
164 IDLE;
165
166 call _test_pll_locked;
167
168 P0.H = hi(PLL_DIV);
169 P0.L = lo(PLL_DIV);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800170 W[P0]= R6; /* Restore CCLK and SCLK divider */
Bryan Wu1394f032007-05-06 14:50:22 -0700171
172 P0.H = hi(PLL_CTL);
173 P0.L = lo(PLL_CTL);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800174 w[p0] = R5; /* Restore VCO multiplier */
Bryan Wu1394f032007-05-06 14:50:22 -0700175 IDLE;
176 call _test_pll_locked;
177
Michael Hennerich4521ef42008-01-11 17:21:41 +0800178 call _unset_dram_srfs; /* SDRAM Self Refresh Off */
Bryan Wu1394f032007-05-06 14:50:22 -0700179
180 STI R4;
181
182 RETS = [SP++];
Mike Frysingerda31d6f2011-06-27 15:43:56 -0400183 (R7:4, P5:3) = [SP++];
Bryan Wu1394f032007-05-06 14:50:22 -0700184 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800185ENDPROC(_sleep_deeper)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800186
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800187ENTRY(_set_dram_srfs)
188 /* set the dram to self refresh mode */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800189 SSYNC;
190#if defined(EBIU_RSTCTL) /* DDR */
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800191 P0.H = hi(EBIU_RSTCTL);
192 P0.L = lo(EBIU_RSTCTL);
193 R2 = [P0];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800194 BITSET(R2, 3); /* SRREQ enter self-refresh mode */
Bryan Wu1394f032007-05-06 14:50:22 -0700195 [P0] = R2;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800196 SSYNC;
1971:
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800198 R2 = [P0];
199 CC = BITTST(R2, 4);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800200 if !CC JUMP 1b;
201#else /* SDRAM */
202 P0.L = lo(EBIU_SDGCTL);
203 P0.H = hi(EBIU_SDGCTL);
Mike Frysinger9e770f72011-06-27 15:46:40 -0400204 P1.L = lo(EBIU_SDSTAT);
205 P1.H = hi(EBIU_SDSTAT);
206
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800207 R2 = [P0];
208 BITSET(R2, 24); /* SRFS enter self-refresh mode */
209 [P0] = R2;
210 SSYNC;
211
Michael Hennerich1efc80b2008-07-19 16:57:32 +08002121:
Mike Frysinger9e770f72011-06-27 15:46:40 -0400213 R2 = w[P1];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800214 SSYNC;
215 cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
216 if !cc jump 1b;
217
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800218 R2 = [P0];
219 BITCLR(R2, 0); /* SCTLE disable CLKOUT */
220 [P0] = R2;
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800221#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700222 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800223ENDPROC(_set_dram_srfs)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800224
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800225ENTRY(_unset_dram_srfs)
226 /* set the dram out of self refresh mode */
Mike Frysinger9e770f72011-06-27 15:46:40 -0400227
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800228#if defined(EBIU_RSTCTL) /* DDR */
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800229 P0.H = hi(EBIU_RSTCTL);
230 P0.L = lo(EBIU_RSTCTL);
231 R2 = [P0];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800232 BITCLR(R2, 3); /* clear SRREQ bit */
Bryan Wu1394f032007-05-06 14:50:22 -0700233 [P0] = R2;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800234#elif defined(EBIU_SDGCTL) /* SDRAM */
Mike Frysinger9e770f72011-06-27 15:46:40 -0400235 /* release CLKOUT from self-refresh */
236 P0.L = lo(EBIU_SDGCTL);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800237 P0.H = hi(EBIU_SDGCTL);
Mike Frysinger9e770f72011-06-27 15:46:40 -0400238
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800239 R2 = [P0];
240 BITSET(R2, 0); /* SCTLE enable CLKOUT */
241 [P0] = R2
242 SSYNC;
243
Mike Frysinger9e770f72011-06-27 15:46:40 -0400244 /* release SDRAM from self-refresh */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800245 R2 = [P0];
246 BITCLR(R2, 24); /* clear SRFS bit */
247 [P0] = R2
248#endif
Mike Frysinger9e770f72011-06-27 15:46:40 -0400249
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800250 SSYNC;
Bryan Wu1394f032007-05-06 14:50:22 -0700251 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800252ENDPROC(_unset_dram_srfs)
Bryan Wu1394f032007-05-06 14:50:22 -0700253
254ENTRY(_set_sic_iwr)
Mike Frysinger85c27372011-06-26 13:55:24 -0400255#ifdef SIC_IWR0
Mike Frysinger4705a252011-06-26 14:07:17 -0400256 P0.H = hi(SYSMMR_BASE);
257 P0.L = lo(SYSMMR_BASE);
258 [P0 + (SIC_IWR0 - SYSMMR_BASE)] = R0;
259 [P0 + (SIC_IWR1 - SYSMMR_BASE)] = R1;
Mike Frysinger85c27372011-06-26 13:55:24 -0400260# ifdef SIC_IWR2
Mike Frysinger4705a252011-06-26 14:07:17 -0400261 [P0 + (SIC_IWR2 - SYSMMR_BASE)] = R2;
Mike Frysinger85c27372011-06-26 13:55:24 -0400262# endif
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800263#else
Bryan Wu1394f032007-05-06 14:50:22 -0700264 P0.H = hi(SIC_IWR);
265 P0.L = lo(SIC_IWR);
Bryan Wu1394f032007-05-06 14:50:22 -0700266 [P0] = R0;
Mike Frysinger4705a252011-06-26 14:07:17 -0400267#endif
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800268
Bryan Wu1394f032007-05-06 14:50:22 -0700269 SSYNC;
270 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800271ENDPROC(_set_sic_iwr)
Bryan Wu1394f032007-05-06 14:50:22 -0700272
Bryan Wu1394f032007-05-06 14:50:22 -0700273ENTRY(_test_pll_locked)
274 P0.H = hi(PLL_STAT);
275 P0.L = lo(PLL_STAT);
2761:
277 R0 = W[P0] (Z);
278 CC = BITTST(R0,5);
279 IF !CC JUMP 1b;
280 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800281ENDPROC(_test_pll_locked)
Steven Miao93f89512012-05-16 18:26:10 +0800282#endif
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800283
284.section .text
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800285ENTRY(_do_hibernate)
Steven Miao93f89512012-05-16 18:26:10 +0800286 bfin_cpu_reg_save;
287 bfin_sys_mmr_save;
288 bfin_core_mmr_save;
Mike Frysingereed7b832011-06-26 23:11:19 -0400289
290 /* Setup args to hibernate mode early for pipeline optimization */
291 R0 = M3;
292 P1.H = _hibernate_mode;
293 P1.L = _hibernate_mode;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800294
295 /* Save Magic, return address and Stack Pointer */
Mike Frysingereed7b832011-06-26 23:11:19 -0400296 P0 = 0;
297 R1.H = 0xDEAD; /* Hibernate Magic */
298 R1.L = 0xBEEF;
299 R2.H = .Lpm_resume_here;
300 R2.L = .Lpm_resume_here;
301 [P0++] = R1; /* Store Hibernate Magic */
302 [P0++] = R2; /* Save Return Address */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800303 [P0++] = SP; /* Save Stack Pointer */
Mike Frysingereed7b832011-06-26 23:11:19 -0400304
305 /* Must use an indirect call as we need to jump to L1 */
306 call (P1); /* Goodbye */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800307
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800308.Lpm_resume_here:
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800309
Steven Miao93f89512012-05-16 18:26:10 +0800310 bfin_core_mmr_restore;
311 bfin_sys_mmr_restore;
312 bfin_cpu_reg_restore;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800313
314 [--sp] = RETI; /* Clear Global Interrupt Disable */
315 SP += 4;
316
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800317 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800318ENDPROC(_do_hibernate)