blob: 54d50c689db138ebfd9d187cd45cb998fbbafe60 [file] [log] [blame]
Sonic Zhangc7e48e12012-07-23 11:35:30 +08001#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)
Steven Miao68bcdd42012-07-18 14:17:46 +080072 LINK 0xC;
Sonic Zhangc7e48e12012-07-23 11:35:30 +080073 [--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
Sonic Zhang928a8e62012-05-31 18:40:20 +0800108 bfin_init_pm_bench_cycles;
109
Sonic Zhangc7e48e12012-07-23 11:35:30 +0800110 /* Fall into deep sleep in idle*/
111 idle;
112 SSYNC;
113
114 /* Restore PLL after wake up from deep sleep */
115 call _bf609_resume_ccbuf;
116
117 /* turn ddr out of self refresh mode */
118 call _bf609_ddr_sr_exit;
119
120 SP = EX_SCRATCH_REG;
121
122 (R7:0,P5:0) = [SP++];
123 UNLINK;
124 RTS;
125ENDPROC(_enter_deepsleep)
126
127.section .text
128ENTRY(_bf609_hibernate)
129 bfin_cpu_reg_save;
130 bfin_core_mmr_save;
131
132 P0.H = _bf609_pm_data;
133 P0.L = _bf609_pm_data;
134 R1.H = 0xDEAD;
135 R1.L = 0xBEEF;
136 R2.H = .Lpm_resume_here;
137 R2.L = .Lpm_resume_here;
138 [P0++] = R1;
139 [P0++] = R2;
140 [P0++] = SP;
141
142 P1.H = _enter_hibernate;
143 P1.L = _enter_hibernate;
144
145 call (P1);
146.Lpm_resume_here:
147
148 bfin_core_mmr_restore;
149 bfin_cpu_reg_restore;
150
151 [--sp] = RETI; /* Clear Global Interrupt Disable */
152 SP += 4;
153
154 RTS;
155
156ENDPROC(_bf609_hibernate)
157