blob: db5452123f17b5e564f6378db72dd6a75e8931ed [file] [log] [blame]
Andrew Victoreaad2db2008-09-21 21:35:18 +01001/*
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>
16#include <mach/hardware.h>
17#include <mach/at91_pmc.h>
Jean-Christophe PLAGNIOL-VILLARDf363c402012-02-13 12:58:53 +080018#include <mach/at91_ramc.h>
Andrew Victoreaad2db2008-09-21 21:35:18 +010019
20
21#ifdef CONFIG_ARCH_AT91SAM9263
22/*
23 * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
24 * handle those cases both here and in the Suspend-To-RAM support.
25 */
Andrew Victoreaad2db2008-09-21 21:35:18 +010026#warning Assuming EB1 SDRAM controller is *NOT* used
27#endif
28
29/*
30 * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
31 * clock during suspend by adjusting its prescalar and divisor.
32 * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
33 * are errata regarding adjusting the prescalar and divisor.
34 */
35#undef SLOWDOWN_MASTER_CLOCK
36
37#define MCKRDY_TIMEOUT 1000
38#define MOSCRDY_TIMEOUT 1000
39#define PLLALOCK_TIMEOUT 1000
40#define PLLBLOCK_TIMEOUT 1000
41
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +010042pmc .req r0
43sdramc .req r1
44ramc1 .req r2
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010045memctrl .req r3
46tmp1 .req r4
47tmp2 .req r5
Andrew Victoreaad2db2008-09-21 21:35:18 +010048
49/*
50 * Wait until master clock is ready (after switching master clock source)
51 */
52 .macro wait_mckrdy
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010053 mov tmp2, #MCKRDY_TIMEOUT
541: sub tmp2, tmp2, #1
55 cmp tmp2, #0
Andrew Victoreaad2db2008-09-21 21:35:18 +010056 beq 2f
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +080057 ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010058 tst tmp1, #AT91_PMC_MCKRDY
Andrew Victoreaad2db2008-09-21 21:35:18 +010059 beq 1b
602:
61 .endm
62
63/*
64 * Wait until master oscillator has stabilized.
65 */
66 .macro wait_moscrdy
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010067 mov tmp2, #MOSCRDY_TIMEOUT
681: sub tmp2, tmp2, #1
69 cmp tmp2, #0
Andrew Victoreaad2db2008-09-21 21:35:18 +010070 beq 2f
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +080071 ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010072 tst tmp1, #AT91_PMC_MOSCS
Andrew Victoreaad2db2008-09-21 21:35:18 +010073 beq 1b
742:
75 .endm
76
77/*
78 * Wait until PLLA has locked.
79 */
80 .macro wait_pllalock
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010081 mov tmp2, #PLLALOCK_TIMEOUT
821: sub tmp2, tmp2, #1
83 cmp tmp2, #0
Andrew Victoreaad2db2008-09-21 21:35:18 +010084 beq 2f
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +080085 ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010086 tst tmp1, #AT91_PMC_LOCKA
Andrew Victoreaad2db2008-09-21 21:35:18 +010087 beq 1b
882:
89 .endm
90
91/*
92 * Wait until PLLB has locked.
93 */
94 .macro wait_pllblock
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010095 mov tmp2, #PLLBLOCK_TIMEOUT
961: sub tmp2, tmp2, #1
97 cmp tmp2, #0
Andrew Victoreaad2db2008-09-21 21:35:18 +010098 beq 2f
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +080099 ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100100 tst tmp1, #AT91_PMC_LOCKB
Andrew Victoreaad2db2008-09-21 21:35:18 +0100101 beq 1b
1022:
103 .endm
104
105 .text
106
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100107/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
108 * void __iomem *ramc1, int memctrl)
109 */
Andrew Victoreaad2db2008-09-21 21:35:18 +0100110ENTRY(at91_slow_clock)
111 /* Save registers on stack */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100112 stmfd sp!, {r4 - r12, lr}
Andrew Victoreaad2db2008-09-21 21:35:18 +0100113
114 /*
115 * Register usage:
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +0100116 * R0 = Base address of AT91_PMC
117 * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
118 * R2 = Base address of second RAM Controller or 0 if not present
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100119 * R3 = Memory controller
Andrew Victoreaad2db2008-09-21 21:35:18 +0100120 * R4 = temporary register
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100121 * R5 = temporary register
Andrew Victoreaad2db2008-09-21 21:35:18 +0100122 */
Andrew Victoreaad2db2008-09-21 21:35:18 +0100123
124 /* Drain write buffer */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100125 mov tmp1, #0
126 mcr p15, 0, tmp1, c7, c10, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +0100127
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100128 cmp memctrl, #AT91_MEMCTRL_MC
129 bne ddr_sr_enable
130
131 /*
132 * at91rm9200 Memory controller
133 */
Andrew Victoreaad2db2008-09-21 21:35:18 +0100134 /* Put SDRAM in self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100135 mov tmp1, #1
Jean-Christophe PLAGNIOL-VILLARD1a269ad2011-11-16 02:58:31 +0800136 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100137 b sdr_sr_done
138
139 /*
140 * DDRSDR Memory controller
141 */
142ddr_sr_enable:
143 cmp memctrl, #AT91_MEMCTRL_DDRSDR
144 bne sdr_sr_enable
Andrew Victoreaad2db2008-09-21 21:35:18 +0100145
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100146 /* prepare for DDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100147 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
148 str tmp1, .saved_sam9_lpr
149 bic tmp1, #AT91_DDRSDRC_LPCB
150 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100151
152 /* figure out if we use the second ram controller */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100153 cmp ramc1, #0
154 ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
155 strne tmp2, .saved_sam9_lpr1
156 bicne tmp2, #AT91_DDRSDRC_LPCB
157 orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100158
159 /* Enable DDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100160 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
161 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100162
163 b sdr_sr_done
164
165 /*
166 * SDRAMC Memory controller
167 */
168sdr_sr_enable:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100169 /* Enable SDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100170 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
171 str tmp1, .saved_sam9_lpr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100172
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100173 bic tmp1, #AT91_SDRAMC_LPCB
174 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
175 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100176
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100177sdr_sr_done:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100178 /* Save Master clock setting */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800179 ldr tmp1, [pmc, #AT91_PMC_MCKR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100180 str tmp1, .saved_mckr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100181
182 /*
183 * Set the Master clock source to slow clock
184 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100185 bic tmp1, tmp1, #AT91_PMC_CSS
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800186 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100187
188 wait_mckrdy
189
190#ifdef SLOWDOWN_MASTER_CLOCK
191 /*
192 * Set the Master Clock PRES and MDIV fields.
193 *
194 * See AT91RM9200 errata #27 and #28 for details.
195 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100196 mov tmp1, #0
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800197 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100198
199 wait_mckrdy
200#endif
201
202 /* Save PLLA setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800203 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100204 str tmp1, .saved_pllar
Andrew Victoreaad2db2008-09-21 21:35:18 +0100205
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100206 mov tmp1, #AT91_PMC_PLLCOUNT
207 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800208 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100209
Andrew Victoreaad2db2008-09-21 21:35:18 +0100210 /* Save PLLB setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800211 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100212 str tmp1, .saved_pllbr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100213
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100214 mov tmp1, #AT91_PMC_PLLCOUNT
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800215 str tmp1, [pmc, #AT91_CKGR_PLLBR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100216
Andrew Victoreaad2db2008-09-21 21:35:18 +0100217 /* Turn off the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800218 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100219 bic tmp1, tmp1, #AT91_PMC_MOSCEN
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800220 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100221
222 /* Wait for interrupt */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100223 mcr p15, 0, tmp1, c7, c0, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +0100224
225 /* Turn on the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800226 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100227 orr tmp1, tmp1, #AT91_PMC_MOSCEN
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800228 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100229
230 wait_moscrdy
231
232 /* Restore PLLB setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100233 ldr tmp1, .saved_pllbr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800234 str tmp1, [pmc, #AT91_CKGR_PLLBR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100235
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100236 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100237 bne 1f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100238 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100239 beq 2f
2401:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100241 wait_pllblock
Anders Larsen9823f1a2010-04-08 11:48:16 +01002422:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100243
244 /* Restore PLLA setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100245 ldr tmp1, .saved_pllar
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800246 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100247
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100248 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100249 bne 3f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100250 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100251 beq 4f
2523:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100253 wait_pllalock
Anders Larsen9823f1a2010-04-08 11:48:16 +01002544:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100255
256#ifdef SLOWDOWN_MASTER_CLOCK
257 /*
258 * First set PRES if it was not 0,
259 * than set CSS and MDIV fields.
260 *
261 * See AT91RM9200 errata #27 and #28 for details.
262 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100263 ldr tmp1, .saved_mckr
264 tst tmp1, #AT91_PMC_PRES
Andrew Victoreaad2db2008-09-21 21:35:18 +0100265 beq 2f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100266 and tmp1, tmp1, #AT91_PMC_PRES
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800267 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100268
269 wait_mckrdy
270#endif
271
272 /*
273 * Restore master clock setting
274 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +01002752: ldr tmp1, .saved_mckr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800276 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100277
278 wait_mckrdy
279
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100280 /*
281 * at91rm9200 Memory controller
282 * Do nothing - self-refresh is automatically disabled.
283 */
284 cmp memctrl, #AT91_MEMCTRL_MC
285 beq ram_restored
286
287 /*
288 * DDRSDR Memory controller
289 */
290 cmp memctrl, #AT91_MEMCTRL_DDRSDR
291 bne sdr_en_restore
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100292 /* Restore LPR on AT91 with DDRAM */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100293 ldr tmp1, .saved_sam9_lpr
294 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100295
296 /* if we use the second ram controller */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100297 cmp ramc1, #0
298 ldrne tmp2, .saved_sam9_lpr1
299 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100300
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100301 b ram_restored
302
303 /*
304 * SDRAMC Memory controller
305 */
306sdr_en_restore:
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100307 /* Restore LPR on AT91 with SDRAM */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100308 ldr tmp1, .saved_sam9_lpr
309 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100310
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100311ram_restored:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100312 /* Restore registers, and return */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100313 ldmfd sp!, {r4 - r12, pc}
Andrew Victoreaad2db2008-09-21 21:35:18 +0100314
315
316.saved_mckr:
317 .word 0
318
319.saved_pllar:
320 .word 0
321
322.saved_pllbr:
323 .word 0
324
325.saved_sam9_lpr:
326 .word 0
327
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100328.saved_sam9_lpr1:
329 .word 0
330
Andrew Victoreaad2db2008-09-21 21:35:18 +0100331ENTRY(at91_slow_clock_sz)
332 .word .-at91_slow_clock