Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * SA11x0 Assembler Sleep/WakeUp Management Routines | |
3 | * | |
4 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License. | |
8 | * | |
9 | * History: | |
10 | * | |
11 | * 2001-02-06: Cliff Brake Initial code | |
12 | * | |
13 | * 2001-08-29: Nicolas Pitre Simplified. | |
14 | * | |
15 | * 2002-05-27: Nicolas Pitre Revisited, more cleanup and simplification. | |
16 | * Storage is on the stack now. | |
17 | */ | |
18 | ||
19 | #include <linux/linkage.h> | |
20 | #include <asm/assembler.h> | |
21 | #include <asm/hardware.h> | |
22 | ||
23 | ||
24 | ||
25 | .text | |
26 | ||
27 | ||
28 | ||
29 | /* | |
30 | * sa1100_cpu_suspend() | |
31 | * | |
32 | * Causes sa11x0 to enter sleep state | |
33 | * | |
34 | */ | |
35 | ||
36 | ENTRY(sa1100_cpu_suspend) | |
37 | ||
38 | stmfd sp!, {r4 - r12, lr} @ save registers on stack | |
39 | ||
40 | @ get coprocessor registers | |
41 | mrc p15, 0, r4, c3, c0, 0 @ domain ID | |
42 | mrc p15, 0, r5, c2, c0, 0 @ translation table base addr | |
43 | mrc p15, 0, r6, c13, c0, 0 @ PID | |
44 | mrc p15, 0, r7, c1, c0, 0 @ control reg | |
45 | ||
46 | @ store them plus current virtual stack ptr on stack | |
47 | mov r8, sp | |
48 | stmfd sp!, {r4 - r8} | |
49 | ||
50 | @ preserve phys address of stack | |
51 | mov r0, sp | |
52 | bl sleep_phys_sp | |
53 | ldr r1, =sleep_save_sp | |
54 | str r0, [r1] | |
55 | ||
56 | @ clean data cache and invalidate WB | |
57 | bl v4wb_flush_kern_cache_all | |
58 | ||
59 | @ disable clock switching | |
60 | mcr p15, 0, r1, c15, c2, 2 | |
61 | ||
62 | @ Adjust memory timing before lowering CPU clock | |
63 | @ Clock speed adjustment without changing memory timing makes | |
64 | @ CPU hang in some cases | |
65 | ldr r0, =MDREFR | |
66 | ldr r1, [r0] | |
67 | orr r1, r1, #MDREFR_K1DB2 | |
68 | str r1, [r0] | |
69 | ||
70 | @ delay 90us and set CPU PLL to lowest speed | |
71 | @ fixes resume problem on high speed SA1110 | |
72 | mov r0, #90 | |
73 | bl __udelay | |
74 | ldr r0, =PPCR | |
75 | mov r1, #0 | |
76 | str r1, [r0] | |
77 | mov r0, #90 | |
78 | bl __udelay | |
79 | ||
80 | /* | |
81 | * SA1110 SDRAM controller workaround. register values: | |
82 | * | |
83 | * r0 = &MSC0 | |
84 | * r1 = &MSC1 | |
85 | * r2 = &MSC2 | |
86 | * r3 = MSC0 value | |
87 | * r4 = MSC1 value | |
88 | * r5 = MSC2 value | |
89 | * r6 = &MDREFR | |
90 | * r7 = first MDREFR value | |
91 | * r8 = second MDREFR value | |
92 | * r9 = &MDCNFG | |
93 | * r10 = MDCNFG value | |
94 | * r11 = third MDREFR value | |
95 | * r12 = &PMCR | |
96 | * r13 = PMCR value (1) | |
97 | */ | |
98 | ||
99 | ldr r0, =MSC0 | |
100 | ldr r1, =MSC1 | |
101 | ldr r2, =MSC2 | |
102 | ||
103 | ldr r3, [r0] | |
104 | bic r3, r3, #FMsk(MSC_RT) | |
105 | bic r3, r3, #FMsk(MSC_RT)<<16 | |
106 | ||
107 | ldr r4, [r1] | |
108 | bic r4, r4, #FMsk(MSC_RT) | |
109 | bic r4, r4, #FMsk(MSC_RT)<<16 | |
110 | ||
111 | ldr r5, [r2] | |
112 | bic r5, r5, #FMsk(MSC_RT) | |
113 | bic r5, r5, #FMsk(MSC_RT)<<16 | |
114 | ||
115 | ldr r6, =MDREFR | |
116 | ||
117 | ldr r7, [r6] | |
118 | bic r7, r7, #0x0000FF00 | |
119 | bic r7, r7, #0x000000F0 | |
120 | orr r8, r7, #MDREFR_SLFRSH | |
121 | ||
122 | ldr r9, =MDCNFG | |
123 | ldr r10, [r9] | |
124 | bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1) | |
125 | bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3) | |
126 | ||
127 | bic r11, r8, #MDREFR_SLFRSH | |
128 | bic r11, r11, #MDREFR_E1PIN | |
129 | ||
130 | ldr r12, =PMCR | |
131 | ||
132 | mov r13, #PMCR_SF | |
133 | ||
134 | b sa1110_sdram_controller_fix | |
135 | ||
136 | .align 5 | |
137 | sa1110_sdram_controller_fix: | |
138 | ||
139 | @ Step 1 clear RT field of all MSCx registers | |
140 | str r3, [r0] | |
141 | str r4, [r1] | |
142 | str r5, [r2] | |
143 | ||
144 | @ Step 2 clear DRI field in MDREFR | |
145 | str r7, [r6] | |
146 | ||
147 | @ Step 3 set SLFRSH bit in MDREFR | |
148 | str r8, [r6] | |
149 | ||
150 | @ Step 4 clear DE bis in MDCNFG | |
151 | str r10, [r9] | |
152 | ||
153 | @ Step 5 clear DRAM refresh control register | |
154 | str r11, [r6] | |
155 | ||
156 | @ Wow, now the hardware suspend request pins can be used, that makes them functional for | |
157 | @ about 7 ns out of the entire time that the CPU is running! | |
158 | ||
159 | @ Step 6 set force sleep bit in PMCR | |
160 | ||
161 | str r13, [r12] | |
162 | ||
163 | 20: b 20b @ loop waiting for sleep | |
164 | ||
165 | /* | |
166 | * cpu_sa1100_resume() | |
167 | * | |
168 | * entry point from bootloader into kernel during resume | |
169 | * | |
170 | * Note: Yes, part of the following code is located into the .data section. | |
171 | * This is to allow sleep_save_sp to be accessed with a relative load | |
172 | * while we can't rely on any MMU translation. We could have put | |
173 | * sleep_save_sp in the .text section as well, but some setups might | |
174 | * insist on it to be truly read-only. | |
175 | */ | |
176 | ||
177 | .data | |
178 | .align 5 | |
179 | ENTRY(sa1100_cpu_resume) | |
180 | mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC | |
181 | msr cpsr_c, r0 @ set SVC, irqs off | |
182 | ||
183 | ldr r0, sleep_save_sp @ stack phys addr | |
184 | ldr r2, =resume_after_mmu @ its absolute virtual address | |
185 | ldmfd r0, {r4 - r7, sp} @ CP regs + virt stack ptr | |
186 | ||
187 | mov r1, #0 | |
188 | mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs | |
189 | mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache | |
190 | mcr p15, 0, r1, c9, c0, 0 @ invalidate RB | |
191 | mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB | |
192 | ||
193 | mcr p15, 0, r4, c3, c0, 0 @ domain ID | |
194 | mcr p15, 0, r5, c2, c0, 0 @ translation table base addr | |
195 | mcr p15, 0, r6, c13, c0, 0 @ PID | |
196 | b resume_turn_on_mmu @ cache align execution | |
197 | ||
198 | .align 5 | |
199 | resume_turn_on_mmu: | |
200 | mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc. | |
201 | nop | |
202 | mov pc, r2 @ jump to virtual addr | |
203 | nop | |
204 | nop | |
205 | nop | |
206 | ||
207 | sleep_save_sp: | |
208 | .word 0 @ preserve stack phys ptr here | |
209 | ||
210 | .text | |
211 | resume_after_mmu: | |
212 | mcr p15, 0, r1, c15, c1, 2 @ enable clock switching | |
213 | ldmfd sp!, {r4 - r12, pc} @ return to caller | |
214 | ||
215 |