diff options
Diffstat (limited to 'arch/arm/mach-sa1100/sleep.S')
-rw-r--r-- | arch/arm/mach-sa1100/sleep.S | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S new file mode 100644 index 000000000000..2fa1e289d177 --- /dev/null +++ b/arch/arm/mach-sa1100/sleep.S | |||
@@ -0,0 +1,215 @@ | |||
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 | |||