blob: 62cc31994298a81b2830c5e49d05eab5e94ac65b [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)
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