blob: cfb7c3c00370a6937c731a4f00824f5d0267cb58 [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;
45 call _test_pll_locked;
46
47 RETS = [SP++];
Mike Frysingerda31d6f2011-06-27 15:43:56 -040048 (R7:4, P5:3) = [SP++];
Bryan Wu1394f032007-05-06 14:50:22 -070049 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +080050ENDPROC(_sleep_mode)
Bryan Wu1394f032007-05-06 14:50:22 -070051
Mike Frysingereed7b832011-06-26 23:11:19 -040052/*
53 * This func never returns as it puts the part into hibernate, and
54 * is only called from do_hibernate, so we don't bother saving or
55 * restoring any of the normal C runtime state. When we wake up,
56 * the entry point will be in do_hibernate and not here.
57 *
58 * We accept just one argument -- the value to write to VR_CTL.
59 */
Steven Miao93f89512012-05-16 18:26:10 +080060
Bryan Wu1394f032007-05-06 14:50:22 -070061ENTRY(_hibernate_mode)
Mike Frysingereed7b832011-06-26 23:11:19 -040062 /* Save/setup the regs we need early for minor pipeline optimization */
63 R4 = R0;
Steven Miao93f89512012-05-16 18:26:10 +080064
Mike Frysingereed7b832011-06-26 23:11:19 -040065 P3.H = hi(VR_CTL);
66 P3.L = lo(VR_CTL);
Mike Frysingereed7b832011-06-26 23:11:19 -040067 /* Disable all wakeup sources */
Michael Hennerich1efc80b2008-07-19 16:57:32 +080068 R0 = IWR_DISABLE_ALL;
69 R1 = IWR_DISABLE_ALL;
70 R2 = IWR_DISABLE_ALL;
Bryan Wu1394f032007-05-06 14:50:22 -070071 call _set_sic_iwr;
Michael Hennerich1efc80b2008-07-19 16:57:32 +080072 call _set_dram_srfs;
73 SSYNC;
Bryan Wu1394f032007-05-06 14:50:22 -070074
Mike Frysingereed7b832011-06-26 23:11:19 -040075 /* Finally, we climb into our cave to hibernate */
76 W[P3] = R4.L;
Bryan Wu1394f032007-05-06 14:50:22 -070077 CLI R2;
78 IDLE;
Michael Hennerich1efc80b2008-07-19 16:57:32 +080079.Lforever:
80 jump .Lforever;
Mike Frysinger1a8caee2008-07-16 17:07:26 +080081ENDPROC(_hibernate_mode)
Bryan Wu1394f032007-05-06 14:50:22 -070082
Bryan Wu1394f032007-05-06 14:50:22 -070083ENTRY(_sleep_deeper)
Mike Frysingerda31d6f2011-06-27 15:43:56 -040084 [--SP] = (R7:4, P5:3);
85 [--SP] = RETS;
Bryan Wu1394f032007-05-06 14:50:22 -070086
87 CLI R4;
88
89 P3 = R0;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080090 P4 = R1;
91 P5 = R2;
92
Bryan Wu1394f032007-05-06 14:50:22 -070093 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +080094 R1 = IWR_DISABLE_ALL;
95 R2 = IWR_DISABLE_ALL;
96
Bryan Wu1394f032007-05-06 14:50:22 -070097 call _set_sic_iwr;
Michael Hennerich4521ef42008-01-11 17:21:41 +080098 call _set_dram_srfs; /* Set SDRAM Self Refresh */
Bryan Wu1394f032007-05-06 14:50:22 -070099
Bryan Wu1394f032007-05-06 14:50:22 -0700100 P0.H = hi(PLL_DIV);
101 P0.L = lo(PLL_DIV);
102 R6 = W[P0](z);
103 R0.L = 0xF;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800104 W[P0] = R0.l; /* Set Max VCO to SCLK divider */
Bryan Wu1394f032007-05-06 14:50:22 -0700105
106 P0.H = hi(PLL_CTL);
107 P0.L = lo(PLL_CTL);
108 R5 = W[P0](z);
Robin Getzf16295e2007-08-03 18:07:17 +0800109 R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800110 W[P0] = R0.l; /* Set Min CLKIN to VCO multiplier */
Bryan Wu1394f032007-05-06 14:50:22 -0700111
112 SSYNC;
113 IDLE;
114
115 call _test_pll_locked;
116
117 P0.H = hi(VR_CTL);
118 P0.L = lo(VR_CTL);
119 R7 = W[P0](z);
120 R1 = 0x6;
121 R1 <<= 16;
122 R2 = 0x0404(Z);
123 R1 = R1|R2;
124
125 R2 = DEPOSIT(R7, R1);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800126 W[P0] = R2; /* Set Min Core Voltage */
Bryan Wu1394f032007-05-06 14:50:22 -0700127
128 SSYNC;
129 IDLE;
130
131 call _test_pll_locked;
132
Michael Hennerich4521ef42008-01-11 17:21:41 +0800133 R0 = P3;
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800134 R1 = P4;
135 R3 = P5;
Michael Hennerich4521ef42008-01-11 17:21:41 +0800136 call _set_sic_iwr; /* Set Awake from IDLE */
137
Bryan Wu1394f032007-05-06 14:50:22 -0700138 P0.H = hi(PLL_CTL);
139 P0.L = lo(PLL_CTL);
140 R0 = W[P0](z);
141 BITSET (R0, 3);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800142 W[P0] = R0.L; /* Turn CCLK OFF */
Bryan Wu1394f032007-05-06 14:50:22 -0700143 SSYNC;
144 IDLE;
145
146 call _test_pll_locked;
147
148 R0 = IWR_ENABLE(0);
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800149 R1 = IWR_DISABLE_ALL;
150 R2 = IWR_DISABLE_ALL;
151
Michael Hennerich4521ef42008-01-11 17:21:41 +0800152 call _set_sic_iwr; /* Set Awake from IDLE PLL */
Bryan Wu1394f032007-05-06 14:50:22 -0700153
154 P0.H = hi(VR_CTL);
155 P0.L = lo(VR_CTL);
156 W[P0]= R7;
157
158 SSYNC;
159 IDLE;
160
161 call _test_pll_locked;
162
163 P0.H = hi(PLL_DIV);
164 P0.L = lo(PLL_DIV);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800165 W[P0]= R6; /* Restore CCLK and SCLK divider */
Bryan Wu1394f032007-05-06 14:50:22 -0700166
167 P0.H = hi(PLL_CTL);
168 P0.L = lo(PLL_CTL);
Michael Hennerich4521ef42008-01-11 17:21:41 +0800169 w[p0] = R5; /* Restore VCO multiplier */
Bryan Wu1394f032007-05-06 14:50:22 -0700170 IDLE;
171 call _test_pll_locked;
172
Michael Hennerich4521ef42008-01-11 17:21:41 +0800173 call _unset_dram_srfs; /* SDRAM Self Refresh Off */
Bryan Wu1394f032007-05-06 14:50:22 -0700174
175 STI R4;
176
177 RETS = [SP++];
Mike Frysingerda31d6f2011-06-27 15:43:56 -0400178 (R7:4, P5:3) = [SP++];
Bryan Wu1394f032007-05-06 14:50:22 -0700179 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800180ENDPROC(_sleep_deeper)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800181
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800182ENTRY(_set_dram_srfs)
183 /* set the dram to self refresh mode */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800184 SSYNC;
185#if defined(EBIU_RSTCTL) /* DDR */
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800186 P0.H = hi(EBIU_RSTCTL);
187 P0.L = lo(EBIU_RSTCTL);
188 R2 = [P0];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800189 BITSET(R2, 3); /* SRREQ enter self-refresh mode */
Bryan Wu1394f032007-05-06 14:50:22 -0700190 [P0] = R2;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800191 SSYNC;
1921:
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800193 R2 = [P0];
194 CC = BITTST(R2, 4);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800195 if !CC JUMP 1b;
196#else /* SDRAM */
197 P0.L = lo(EBIU_SDGCTL);
198 P0.H = hi(EBIU_SDGCTL);
Mike Frysinger9e770f72011-06-27 15:46:40 -0400199 P1.L = lo(EBIU_SDSTAT);
200 P1.H = hi(EBIU_SDSTAT);
201
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800202 R2 = [P0];
203 BITSET(R2, 24); /* SRFS enter self-refresh mode */
204 [P0] = R2;
205 SSYNC;
206
Michael Hennerich1efc80b2008-07-19 16:57:32 +08002071:
Mike Frysinger9e770f72011-06-27 15:46:40 -0400208 R2 = w[P1];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800209 SSYNC;
210 cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
211 if !cc jump 1b;
212
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800213 R2 = [P0];
214 BITCLR(R2, 0); /* SCTLE disable CLKOUT */
215 [P0] = R2;
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800216#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700217 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800218ENDPROC(_set_dram_srfs)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800219
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800220ENTRY(_unset_dram_srfs)
221 /* set the dram out of self refresh mode */
Mike Frysinger9e770f72011-06-27 15:46:40 -0400222
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800223#if defined(EBIU_RSTCTL) /* DDR */
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800224 P0.H = hi(EBIU_RSTCTL);
225 P0.L = lo(EBIU_RSTCTL);
226 R2 = [P0];
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800227 BITCLR(R2, 3); /* clear SRREQ bit */
Bryan Wu1394f032007-05-06 14:50:22 -0700228 [P0] = R2;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800229#elif defined(EBIU_SDGCTL) /* SDRAM */
Mike Frysinger9e770f72011-06-27 15:46:40 -0400230 /* release CLKOUT from self-refresh */
231 P0.L = lo(EBIU_SDGCTL);
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800232 P0.H = hi(EBIU_SDGCTL);
Mike Frysinger9e770f72011-06-27 15:46:40 -0400233
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800234 R2 = [P0];
235 BITSET(R2, 0); /* SCTLE enable CLKOUT */
236 [P0] = R2
237 SSYNC;
238
Mike Frysinger9e770f72011-06-27 15:46:40 -0400239 /* release SDRAM from self-refresh */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800240 R2 = [P0];
241 BITCLR(R2, 24); /* clear SRFS bit */
242 [P0] = R2
243#endif
Mike Frysinger9e770f72011-06-27 15:46:40 -0400244
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800245 SSYNC;
Bryan Wu1394f032007-05-06 14:50:22 -0700246 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800247ENDPROC(_unset_dram_srfs)
Bryan Wu1394f032007-05-06 14:50:22 -0700248
249ENTRY(_set_sic_iwr)
Mike Frysinger85c27372011-06-26 13:55:24 -0400250#ifdef SIC_IWR0
Mike Frysinger4705a252011-06-26 14:07:17 -0400251 P0.H = hi(SYSMMR_BASE);
252 P0.L = lo(SYSMMR_BASE);
253 [P0 + (SIC_IWR0 - SYSMMR_BASE)] = R0;
254 [P0 + (SIC_IWR1 - SYSMMR_BASE)] = R1;
Mike Frysinger85c27372011-06-26 13:55:24 -0400255# ifdef SIC_IWR2
Mike Frysinger4705a252011-06-26 14:07:17 -0400256 [P0 + (SIC_IWR2 - SYSMMR_BASE)] = R2;
Mike Frysinger85c27372011-06-26 13:55:24 -0400257# endif
Sonic Zhangfb5f0042007-12-23 23:02:13 +0800258#else
Bryan Wu1394f032007-05-06 14:50:22 -0700259 P0.H = hi(SIC_IWR);
260 P0.L = lo(SIC_IWR);
Bryan Wu1394f032007-05-06 14:50:22 -0700261 [P0] = R0;
Mike Frysinger4705a252011-06-26 14:07:17 -0400262#endif
Michael Hennerichcfefe3c2008-02-09 04:12:37 +0800263
Bryan Wu1394f032007-05-06 14:50:22 -0700264 SSYNC;
265 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800266ENDPROC(_set_sic_iwr)
Bryan Wu1394f032007-05-06 14:50:22 -0700267
Bryan Wu1394f032007-05-06 14:50:22 -0700268ENTRY(_test_pll_locked)
269 P0.H = hi(PLL_STAT);
270 P0.L = lo(PLL_STAT);
2711:
272 R0 = W[P0] (Z);
273 CC = BITTST(R0,5);
274 IF !CC JUMP 1b;
275 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800276ENDPROC(_test_pll_locked)
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800277
278.section .text
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800279ENTRY(_do_hibernate)
Steven Miao93f89512012-05-16 18:26:10 +0800280 bfin_cpu_reg_save;
281 bfin_sys_mmr_save;
282 bfin_core_mmr_save;
Mike Frysingereed7b832011-06-26 23:11:19 -0400283
284 /* Setup args to hibernate mode early for pipeline optimization */
285 R0 = M3;
286 P1.H = _hibernate_mode;
287 P1.L = _hibernate_mode;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800288
289 /* Save Magic, return address and Stack Pointer */
Mike Frysingereed7b832011-06-26 23:11:19 -0400290 P0 = 0;
291 R1.H = 0xDEAD; /* Hibernate Magic */
292 R1.L = 0xBEEF;
293 R2.H = .Lpm_resume_here;
294 R2.L = .Lpm_resume_here;
295 [P0++] = R1; /* Store Hibernate Magic */
296 [P0++] = R2; /* Save Return Address */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800297 [P0++] = SP; /* Save Stack Pointer */
Mike Frysingereed7b832011-06-26 23:11:19 -0400298
299 /* Must use an indirect call as we need to jump to L1 */
300 call (P1); /* Goodbye */
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800301
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800302.Lpm_resume_here:
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800303
Steven Miao93f89512012-05-16 18:26:10 +0800304 bfin_core_mmr_restore;
305 bfin_sys_mmr_restore;
306 bfin_cpu_reg_restore;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800307
308 [--sp] = RETI; /* Clear Global Interrupt Disable */
309 SP += 4;
310
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800311 RTS;
Mike Frysinger1a8caee2008-07-16 17:07:26 +0800312ENDPROC(_do_hibernate)