aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-bf609/dpm.S
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2012-07-22 23:35:30 -0400
committerBob Liu <lliubbo@gmail.com>2012-07-24 01:39:49 -0400
commitc7e48e1e3e926de21605f959c31689d56fb639e3 (patch)
tree4a598fd55ed79fdcf63077318e04d6f39be594d0 /arch/blackfin/mach-bf609/dpm.S
parenta5b4d4be6ce7939d1604fae05786833fffae02f9 (diff)
bfin: pm: add deepsleep for bf60x
Add add deepsleep for bf60x. 1. Call DMC init functions to enter and exit DDR self refresh mode. 2. Wait till CGU PLL is locked after wake up and exit DDR self refresh mode. 3. Make asessembly function enter_deepsleep comply with C funtion ABI in order to call other C functions. 4. Switch kernel stack by register EX_SCRATCH_REG. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Bob Liu <lliubbo@gmail.com>
Diffstat (limited to 'arch/blackfin/mach-bf609/dpm.S')
-rw-r--r--arch/blackfin/mach-bf609/dpm.S155
1 files changed, 155 insertions, 0 deletions
diff --git a/arch/blackfin/mach-bf609/dpm.S b/arch/blackfin/mach-bf609/dpm.S
new file mode 100644
index 000000000000..62cc31994298
--- /dev/null
+++ b/arch/blackfin/mach-bf609/dpm.S
@@ -0,0 +1,155 @@
1#include <linux/linkage.h>
2#include <asm/blackfin.h>
3#include <asm/dpmc.h>
4
5#include <asm/context.S>
6
7#define PM_STACK (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
8
9.section .l1.text
10ENTRY(_enter_hibernate)
11 /* switch stack to L1 scratch, prepare for ddr srfr */
12 P0.H = HI(PM_STACK);
13 P0.L = LO(PM_STACK);
14 SP = P0;
15
16 call _bf609_ddr_sr;
17 call _bfin_hibernate_syscontrol;
18
19 P0.H = HI(DPM0_RESTORE4);
20 P0.L = LO(DPM0_RESTORE4);
21 P1.H = _bf609_pm_data;
22 P1.L = _bf609_pm_data;
23 [P0] = P1;
24
25 P0.H = HI(DPM0_CTL);
26 P0.L = LO(DPM0_CTL);
27 R3.H = HI(0x00000010);
28 R3.L = LO(0x00000010);
29
30 bfin_init_pm_bench_cycles;
31
32 [P0] = R3;
33
34 SSYNC;
35ENDPROC(_enter_hibernate)
36
37/* DPM wake up interrupt won't wake up core on bf60x if its core IMASK
38 * is disabled. This behavior differ from bf5xx serial processor.
39 */
40ENTRY(_dummy_deepsleep)
41 [--sp] = SYSCFG;
42 [--sp] = (R7:0,P5:0);
43 cli r0;
44
45 /* get wake up interrupt ID */
46 P0.l = LO(SEC_SCI_BASE + SEC_CSID);
47 P0.h = HI(SEC_SCI_BASE + SEC_CSID);
48 R0 = [P0];
49
50 /* ACK wake up interrupt in SEC */
51 P1.l = LO(SEC_END);
52 P1.h = HI(SEC_END);
53
54 [P1] = R0;
55 SSYNC;
56
57 /* restore EVT 11 entry */
58 p0.h = hi(EVT11);
59 p0.l = lo(EVT11);
60 p1.h = _evt_evt11;
61 p1.l = _evt_evt11;
62
63 [p0] = p1;
64 SSYNC;
65
66 (R7:0,P5:0) = [sp++];
67 SYSCFG = [sp++];
68 RTI;
69ENDPROC(_dummy_deepsleep)
70
71ENTRY(_enter_deepsleep)
72 LINK 0x0;
73 [--sp] = (R7:0,P5:0);
74
75 /* Change EVT 11 entry to dummy handler for wake up event */
76 p0.h = hi(EVT11);
77 p0.l = lo(EVT11);
78 p1.h = _dummy_deepsleep;
79 p1.l = _dummy_deepsleep;
80
81 [p0] = p1;
82
83 P0.H = HI(PM_STACK);
84 P0.L = LO(PM_STACK);
85
86 EX_SCRATCH_REG = SP;
87 SP = P0;
88
89 SSYNC;
90
91 /* should put ddr to self refresh mode before sleep */
92 call _bf609_ddr_sr;
93
94 /* Set DPM controller to deep sleep mode */
95 P0.H = HI(DPM0_CTL);
96 P0.L = LO(DPM0_CTL);
97 R3.H = HI(0x00000008);
98 R3.L = LO(0x00000008);
99 [P0] = R3;
100 CSYNC;
101
102 /* Enable evt 11 in IMASK before idle, otherwise core doesn't wake up. */
103 r0.l = 0x800;
104 r0.h = 0;
105 sti r0;
106 SSYNC;
107
108 /* Fall into deep sleep in idle*/
109 idle;
110 SSYNC;
111
112 /* Restore PLL after wake up from deep sleep */
113 call _bf609_resume_ccbuf;
114
115 /* turn ddr out of self refresh mode */
116 call _bf609_ddr_sr_exit;
117
118 SP = EX_SCRATCH_REG;
119
120 (R7:0,P5:0) = [SP++];
121 UNLINK;
122 RTS;
123ENDPROC(_enter_deepsleep)
124
125.section .text
126ENTRY(_bf609_hibernate)
127 bfin_cpu_reg_save;
128 bfin_core_mmr_save;
129
130 P0.H = _bf609_pm_data;
131 P0.L = _bf609_pm_data;
132 R1.H = 0xDEAD;
133 R1.L = 0xBEEF;
134 R2.H = .Lpm_resume_here;
135 R2.L = .Lpm_resume_here;
136 [P0++] = R1;
137 [P0++] = R2;
138 [P0++] = SP;
139
140 P1.H = _enter_hibernate;
141 P1.L = _enter_hibernate;
142
143 call (P1);
144.Lpm_resume_here:
145
146 bfin_core_mmr_restore;
147 bfin_cpu_reg_restore;
148
149 [--sp] = RETI; /* Clear Global Interrupt Disable */
150 SP += 4;
151
152 RTS;
153
154ENDPROC(_bf609_hibernate)
155