Linux 3.17-rc2
[linux/fpc-iii.git] / arch / blackfin / mach-common / dpmc_modes.S
blobde99f3aac2c5618992b8440be9c2ebc054cf95c3
1 /*
2  * Copyright 2004-2008 Analog Devices Inc.
3  *
4  * Licensed under the GPL-2 or later.
5  */
7 #include <linux/linkage.h>
8 #include <asm/blackfin.h>
9 #include <mach/irq.h>
10 #include <asm/dpmc.h>
12 .section .l1.text
13 ENTRY(_sleep_mode)
14         [--SP] = (R7:4, P5:3);
15         [--SP] = RETS;
17         call _set_sic_iwr;
19         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;
25         CLI R2;
26         SSYNC;
27         IDLE;
28         STI R2;
30         call _test_pll_locked;
32         R0 = IWR_ENABLE(0);
33         R1 = IWR_DISABLE_ALL;
34         R2 = IWR_DISABLE_ALL;
36         call _set_sic_iwr;
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;
46         bfin_init_pm_bench_cycles;
48         call _test_pll_locked;
50         RETS = [SP++];
51         (R7:4, P5:3) = [SP++];
52         RTS;
53 ENDPROC(_sleep_mode)
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  */
64 ENTRY(_hibernate_mode)
65         /* Save/setup the regs we need early for minor pipeline optimization */
66         R4 = R0;
68         P3.H = hi(VR_CTL);
69         P3.L = lo(VR_CTL);
70         /* Disable all wakeup sources */
71         R0 = IWR_DISABLE_ALL;
72         R1 = IWR_DISABLE_ALL;
73         R2 = IWR_DISABLE_ALL;
74         call _set_sic_iwr;
75         call _set_dram_srfs;
76         SSYNC;
78         /* Finally, we climb into our cave to hibernate */
79         W[P3] = R4.L;
81         bfin_init_pm_bench_cycles;
83         CLI R2;
84         IDLE;
85 .Lforever:
86         jump .Lforever;
87 ENDPROC(_hibernate_mode)
89 ENTRY(_sleep_deeper)
90         [--SP] = (R7:4, P5:3);
91         [--SP] = RETS;
93         CLI R4;
95         P3 = R0;
96         P4 = R1;
97         P5 = R2;
99         R0 = IWR_ENABLE(0);
100         R1 = IWR_DISABLE_ALL;
101         R2 = IWR_DISABLE_ALL;
103         call _set_sic_iwr;
104         call _set_dram_srfs;    /* Set SDRAM Self Refresh */
106         P0.H = hi(PLL_DIV);
107         P0.L = lo(PLL_DIV);
108         R6 = W[P0](z);
109         R0.L = 0xF;
110         W[P0] = R0.l;           /* Set Max VCO to SCLK divider */
112         P0.H = hi(PLL_CTL);
113         P0.L = lo(PLL_CTL);
114         R5 = W[P0](z);
115         R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
116         W[P0] = R0.l;           /* Set Min CLKIN to VCO multiplier */
118         SSYNC;
119         IDLE;
121         call _test_pll_locked;
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;
131         R2 = DEPOSIT(R7, R1);
132         W[P0] = R2;             /* Set Min Core Voltage */
134         SSYNC;
135         IDLE;
137         call _test_pll_locked;
139         R0 = P3;
140         R1 = P4;
141         R3 = P5;
142         call _set_sic_iwr;      /* Set Awake from IDLE */
144         P0.H = hi(PLL_CTL);
145         P0.L = lo(PLL_CTL);
146         R0 = W[P0](z);
147         BITSET (R0, 3);
148         W[P0] = R0.L;           /* Turn CCLK OFF */
149         SSYNC;
150         IDLE;
152         call _test_pll_locked;
154         R0 = IWR_ENABLE(0);
155         R1 = IWR_DISABLE_ALL;
156         R2 = IWR_DISABLE_ALL;
158         call _set_sic_iwr;      /* Set Awake from IDLE PLL */
160         P0.H = hi(VR_CTL);
161         P0.L = lo(VR_CTL);
162         W[P0]= R7;
164         SSYNC;
165         IDLE;
167         bfin_init_pm_bench_cycles;
169         call _test_pll_locked;
171         P0.H = hi(PLL_DIV);
172         P0.L = lo(PLL_DIV);
173         W[P0]= R6;              /* Restore CCLK and SCLK divider */
175         P0.H = hi(PLL_CTL);
176         P0.L = lo(PLL_CTL);
177         w[p0] = R5;             /* Restore VCO multiplier */
178         IDLE;
179         call _test_pll_locked;
181         call _unset_dram_srfs;  /* SDRAM Self Refresh Off */
183         STI R4;
185         RETS = [SP++];
186         (R7:4, P5:3) = [SP++];
187         RTS;
188 ENDPROC(_sleep_deeper)
190 ENTRY(_set_dram_srfs)
191         /*  set the dram to self refresh mode */
192         SSYNC;
193 #if defined(EBIU_RSTCTL)        /* DDR */
194         P0.H = hi(EBIU_RSTCTL);
195         P0.L = lo(EBIU_RSTCTL);
196         R2 = [P0];
197         BITSET(R2, 3); /* SRREQ enter self-refresh mode */
198         [P0] = R2;
199         SSYNC;
201         R2 = [P0];
202         CC = BITTST(R2, 4);
203         if !CC JUMP 1b;
204 #else                           /* SDRAM */
205         P0.L = lo(EBIU_SDGCTL);
206         P0.H = hi(EBIU_SDGCTL);
207         P1.L = lo(EBIU_SDSTAT);
208         P1.H = hi(EBIU_SDSTAT);
210         R2 = [P0];
211         BITSET(R2, 24); /* SRFS enter self-refresh mode */
212         [P0] = R2;
213         SSYNC;
216         R2 = w[P1];
217         SSYNC;
218         cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
219         if !cc jump 1b;
221         R2 = [P0];
222         BITCLR(R2, 0); /* SCTLE disable CLKOUT */
223         [P0] = R2;
224 #endif
225         RTS;
226 ENDPROC(_set_dram_srfs)
228 ENTRY(_unset_dram_srfs)
229         /*  set the dram out of self refresh mode */
231 #if defined(EBIU_RSTCTL)        /* DDR */
232         P0.H = hi(EBIU_RSTCTL);
233         P0.L = lo(EBIU_RSTCTL);
234         R2 = [P0];
235         BITCLR(R2, 3); /* clear SRREQ bit */
236         [P0] = R2;
237 #elif defined(EBIU_SDGCTL)      /* SDRAM */
238         /* release CLKOUT from self-refresh */
239         P0.L = lo(EBIU_SDGCTL);
240         P0.H = hi(EBIU_SDGCTL);
242         R2 = [P0];
243         BITSET(R2, 0); /* SCTLE enable CLKOUT */
244         [P0] = R2
245         SSYNC;
247         /* release SDRAM from self-refresh */
248         R2 = [P0];
249         BITCLR(R2, 24); /* clear SRFS bit */
250         [P0] = R2
251 #endif
253         SSYNC;
254         RTS;
255 ENDPROC(_unset_dram_srfs)
257 ENTRY(_set_sic_iwr)
258 #ifdef SIC_IWR0
259         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;
263 # ifdef SIC_IWR2
264         [P0 + (SIC_IWR2 - SYSMMR_BASE)] = R2;
265 # endif
266 #else
267         P0.H = hi(SIC_IWR);
268         P0.L = lo(SIC_IWR);
269         [P0] = R0;
270 #endif
272         SSYNC;
273         RTS;
274 ENDPROC(_set_sic_iwr)
276 ENTRY(_test_pll_locked)
277         P0.H = hi(PLL_STAT);
278         P0.L = lo(PLL_STAT);
280         R0 = W[P0] (Z);
281         CC = BITTST(R0,5);
282         IF !CC JUMP 1b;
283         RTS;
284 ENDPROC(_test_pll_locked)
286 .section .text
287 ENTRY(_do_hibernate)
288         bfin_cpu_reg_save;
289         bfin_sys_mmr_save;
290         bfin_core_mmr_save;
292         /* Setup args to hibernate mode early for pipeline optimization */
293         R0 = M3;
294         P1.H = _hibernate_mode;
295         P1.L = _hibernate_mode;
297         /* Save Magic, return address and Stack Pointer */
298         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 */
305         [P0++] = SP;    /* Save Stack Pointer */
307         /* Must use an indirect call as we need to jump to L1 */
308         call (P1); /* Goodbye */
310 .Lpm_resume_here:
312         bfin_core_mmr_restore;
313         bfin_sys_mmr_restore;
314         bfin_cpu_reg_restore;
316         [--sp] = RETI;  /* Clear Global Interrupt Disable */
317         SP += 4;
319         RTS;
320 ENDPROC(_do_hibernate)