pm: at91: pm_slowclock: fix suspend/resume hang up in timeouts
[deliverable/linux.git] / arch / arm / mach-at91 / pm_slowclock.S
CommitLineData
eaad2db0
AV
1/*
2 * arch/arm/mach-at91/pm_slow_clock.S
3 *
4 * Copyright (C) 2006 Savin Zlobec
5 *
6 * AT91SAM9 support:
7 * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/linkage.h>
2edb90ae 16#include <linux/clk/at91_pmc.h>
eaad2db0 17#include <mach/hardware.h>
f363c407 18#include <mach/at91_ramc.h>
eaad2db0 19
eaad2db0
AV
20/*
21 * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
22 * clock during suspend by adjusting its prescalar and divisor.
23 * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
24 * are errata regarding adjusting the prescalar and divisor.
25 */
26#undef SLOWDOWN_MASTER_CLOCK
27
8ff12ad3
JCPV
28pmc .req r0
29sdramc .req r1
30ramc1 .req r2
fb7e197b
JCPV
31memctrl .req r3
32tmp1 .req r4
33tmp2 .req r5
eaad2db0
AV
34
35/*
36 * Wait until master clock is ready (after switching master clock source)
37 */
38 .macro wait_mckrdy
ad4a38d2 391: ldr tmp1, [pmc, #AT91_PMC_SR]
0dcfed14 40 tst tmp1, #AT91_PMC_MCKRDY
eaad2db0 41 beq 1b
eaad2db0
AV
42 .endm
43
44/*
45 * Wait until master oscillator has stabilized.
46 */
47 .macro wait_moscrdy
ad4a38d2 481: ldr tmp1, [pmc, #AT91_PMC_SR]
0dcfed14 49 tst tmp1, #AT91_PMC_MOSCS
eaad2db0 50 beq 1b
eaad2db0
AV
51 .endm
52
53/*
54 * Wait until PLLA has locked.
55 */
56 .macro wait_pllalock
ad4a38d2 571: ldr tmp1, [pmc, #AT91_PMC_SR]
0dcfed14 58 tst tmp1, #AT91_PMC_LOCKA
eaad2db0 59 beq 1b
eaad2db0
AV
60 .endm
61
62/*
63 * Wait until PLLB has locked.
64 */
65 .macro wait_pllblock
ad4a38d2 661: ldr tmp1, [pmc, #AT91_PMC_SR]
0dcfed14 67 tst tmp1, #AT91_PMC_LOCKB
eaad2db0 68 beq 1b
eaad2db0
AV
69 .endm
70
71 .text
72
fb7e197b
JCPV
73/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
74 * void __iomem *ramc1, int memctrl)
75 */
eaad2db0
AV
76ENTRY(at91_slow_clock)
77 /* Save registers on stack */
fb7e197b 78 stmfd sp!, {r4 - r12, lr}
eaad2db0
AV
79
80 /*
81 * Register usage:
8ff12ad3
JCPV
82 * R0 = Base address of AT91_PMC
83 * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
84 * R2 = Base address of second RAM Controller or 0 if not present
fb7e197b 85 * R3 = Memory controller
eaad2db0 86 * R4 = temporary register
fb7e197b 87 * R5 = temporary register
eaad2db0 88 */
eaad2db0
AV
89
90 /* Drain write buffer */
0dcfed14
JCPV
91 mov tmp1, #0
92 mcr p15, 0, tmp1, c7, c10, 4
eaad2db0 93
fb7e197b
JCPV
94 cmp memctrl, #AT91_MEMCTRL_MC
95 bne ddr_sr_enable
96
97 /*
98 * at91rm9200 Memory controller
99 */
eaad2db0 100 /* Put SDRAM in self-refresh mode */
0dcfed14 101 mov tmp1, #1
1a269ade 102 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
fb7e197b
JCPV
103 b sdr_sr_done
104
105 /*
106 * DDRSDR Memory controller
107 */
108ddr_sr_enable:
109 cmp memctrl, #AT91_MEMCTRL_DDRSDR
110 bne sdr_sr_enable
eaad2db0 111
7dca3343 112 /* prepare for DDRAM self-refresh mode */
0dcfed14
JCPV
113 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
114 str tmp1, .saved_sam9_lpr
115 bic tmp1, #AT91_DDRSDRC_LPCB
116 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
7dca3343
NF
117
118 /* figure out if we use the second ram controller */
0dcfed14
JCPV
119 cmp ramc1, #0
120 ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
121 strne tmp2, .saved_sam9_lpr1
122 bicne tmp2, #AT91_DDRSDRC_LPCB
123 orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
7dca3343
NF
124
125 /* Enable DDRAM self-refresh mode */
0dcfed14
JCPV
126 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
127 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
fb7e197b
JCPV
128
129 b sdr_sr_done
130
131 /*
132 * SDRAMC Memory controller
133 */
134sdr_sr_enable:
eaad2db0 135 /* Enable SDRAM self-refresh mode */
0dcfed14
JCPV
136 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
137 str tmp1, .saved_sam9_lpr
eaad2db0 138
0dcfed14
JCPV
139 bic tmp1, #AT91_SDRAMC_LPCB
140 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
141 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
eaad2db0 142
fb7e197b 143sdr_sr_done:
eaad2db0 144 /* Save Master clock setting */
b5514952 145 ldr tmp1, [pmc, #AT91_PMC_MCKR]
0dcfed14 146 str tmp1, .saved_mckr
eaad2db0
AV
147
148 /*
149 * Set the Master clock source to slow clock
150 */
0dcfed14 151 bic tmp1, tmp1, #AT91_PMC_CSS
b5514952 152 str tmp1, [pmc, #AT91_PMC_MCKR]
eaad2db0
AV
153
154 wait_mckrdy
155
156#ifdef SLOWDOWN_MASTER_CLOCK
157 /*
158 * Set the Master Clock PRES and MDIV fields.
159 *
160 * See AT91RM9200 errata #27 and #28 for details.
161 */
0dcfed14 162 mov tmp1, #0
b5514952 163 str tmp1, [pmc, #AT91_PMC_MCKR]
eaad2db0
AV
164
165 wait_mckrdy
166#endif
167
168 /* Save PLLA setting and disable it */
b5514952 169 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
0dcfed14 170 str tmp1, .saved_pllar
eaad2db0 171
0dcfed14
JCPV
172 mov tmp1, #AT91_PMC_PLLCOUNT
173 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
b5514952 174 str tmp1, [pmc, #AT91_CKGR_PLLAR]
eaad2db0 175
eaad2db0 176 /* Save PLLB setting and disable it */
b5514952 177 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
0dcfed14 178 str tmp1, .saved_pllbr
eaad2db0 179
0dcfed14 180 mov tmp1, #AT91_PMC_PLLCOUNT
b5514952 181 str tmp1, [pmc, #AT91_CKGR_PLLBR]
eaad2db0 182
eaad2db0 183 /* Turn off the main oscillator */
b5514952 184 ldr tmp1, [pmc, #AT91_CKGR_MOR]
0dcfed14 185 bic tmp1, tmp1, #AT91_PMC_MOSCEN
b5514952 186 str tmp1, [pmc, #AT91_CKGR_MOR]
eaad2db0
AV
187
188 /* Wait for interrupt */
0dcfed14 189 mcr p15, 0, tmp1, c7, c0, 4
eaad2db0
AV
190
191 /* Turn on the main oscillator */
b5514952 192 ldr tmp1, [pmc, #AT91_CKGR_MOR]
0dcfed14 193 orr tmp1, tmp1, #AT91_PMC_MOSCEN
b5514952 194 str tmp1, [pmc, #AT91_CKGR_MOR]
eaad2db0
AV
195
196 wait_moscrdy
197
198 /* Restore PLLB setting */
0dcfed14 199 ldr tmp1, .saved_pllbr
b5514952 200 str tmp1, [pmc, #AT91_CKGR_PLLBR]
eaad2db0 201
0dcfed14 202 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
9823f1a8 203 bne 1f
0dcfed14 204 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
9823f1a8
AL
205 beq 2f
2061:
eaad2db0 207 wait_pllblock
9823f1a8 2082:
eaad2db0
AV
209
210 /* Restore PLLA setting */
0dcfed14 211 ldr tmp1, .saved_pllar
b5514952 212 str tmp1, [pmc, #AT91_CKGR_PLLAR]
eaad2db0 213
0dcfed14 214 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
9823f1a8 215 bne 3f
0dcfed14 216 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
9823f1a8
AL
217 beq 4f
2183:
eaad2db0 219 wait_pllalock
9823f1a8 2204:
eaad2db0
AV
221
222#ifdef SLOWDOWN_MASTER_CLOCK
223 /*
224 * First set PRES if it was not 0,
225 * than set CSS and MDIV fields.
226 *
227 * See AT91RM9200 errata #27 and #28 for details.
228 */
0dcfed14
JCPV
229 ldr tmp1, .saved_mckr
230 tst tmp1, #AT91_PMC_PRES
eaad2db0 231 beq 2f
0dcfed14 232 and tmp1, tmp1, #AT91_PMC_PRES
b5514952 233 str tmp1, [pmc, #AT91_PMC_MCKR]
eaad2db0
AV
234
235 wait_mckrdy
236#endif
237
238 /*
239 * Restore master clock setting
240 */
0dcfed14 2412: ldr tmp1, .saved_mckr
b5514952 242 str tmp1, [pmc, #AT91_PMC_MCKR]
eaad2db0
AV
243
244 wait_mckrdy
245
fb7e197b
JCPV
246 /*
247 * at91rm9200 Memory controller
248 * Do nothing - self-refresh is automatically disabled.
249 */
250 cmp memctrl, #AT91_MEMCTRL_MC
251 beq ram_restored
252
253 /*
254 * DDRSDR Memory controller
255 */
256 cmp memctrl, #AT91_MEMCTRL_DDRSDR
257 bne sdr_en_restore
7dca3343 258 /* Restore LPR on AT91 with DDRAM */
0dcfed14
JCPV
259 ldr tmp1, .saved_sam9_lpr
260 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
7dca3343
NF
261
262 /* if we use the second ram controller */
0dcfed14
JCPV
263 cmp ramc1, #0
264 ldrne tmp2, .saved_sam9_lpr1
265 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
7dca3343 266
fb7e197b
JCPV
267 b ram_restored
268
269 /*
270 * SDRAMC Memory controller
271 */
272sdr_en_restore:
7dca3343 273 /* Restore LPR on AT91 with SDRAM */
0dcfed14
JCPV
274 ldr tmp1, .saved_sam9_lpr
275 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
eaad2db0 276
fb7e197b 277ram_restored:
eaad2db0 278 /* Restore registers, and return */
fb7e197b 279 ldmfd sp!, {r4 - r12, pc}
eaad2db0
AV
280
281
282.saved_mckr:
283 .word 0
284
285.saved_pllar:
286 .word 0
287
288.saved_pllbr:
289 .word 0
290
291.saved_sam9_lpr:
292 .word 0
293
7dca3343
NF
294.saved_sam9_lpr1:
295 .word 0
296
eaad2db0
AV
297ENTRY(at91_slow_clock_sz)
298 .word .-at91_slow_clock
This page took 1.095865 seconds and 5 git commands to generate.