blob: 931f0e302c035ecc33a138ec0bd61dc910321c66 [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>
Boris BREZILLON2edb90a2013-10-11 09:37:45 +020016#include <linux/clk/at91_pmc.h>
Andrew Victoreaad2db2008-09-21 21:35:18 +010017#include <mach/hardware.h>
Jean-Christophe PLAGNIOL-VILLARDf363c402012-02-13 12:58:53 +080018#include <mach/at91_ramc.h>
Andrew Victoreaad2db2008-09-21 21:35:18 +010019
Andrew Victoreaad2db2008-09-21 21:35:18 +010020/*
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
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +010028pmc .req r0
29sdramc .req r1
30ramc1 .req r2
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010031memctrl .req r3
32tmp1 .req r4
33tmp2 .req r5
Andrew Victoreaad2db2008-09-21 21:35:18 +010034
35/*
36 * Wait until master clock is ready (after switching master clock source)
37 */
38 .macro wait_mckrdy
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800391: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010040 tst tmp1, #AT91_PMC_MCKRDY
Andrew Victoreaad2db2008-09-21 21:35:18 +010041 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010042 .endm
43
44/*
45 * Wait until master oscillator has stabilized.
46 */
47 .macro wait_moscrdy
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800481: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010049 tst tmp1, #AT91_PMC_MOSCS
Andrew Victoreaad2db2008-09-21 21:35:18 +010050 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010051 .endm
52
53/*
54 * Wait until PLLA has locked.
55 */
56 .macro wait_pllalock
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800571: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010058 tst tmp1, #AT91_PMC_LOCKA
Andrew Victoreaad2db2008-09-21 21:35:18 +010059 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010060 .endm
61
62/*
63 * Wait until PLLB has locked.
64 */
65 .macro wait_pllblock
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800661: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010067 tst tmp1, #AT91_PMC_LOCKB
Andrew Victoreaad2db2008-09-21 21:35:18 +010068 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010069 .endm
70
71 .text
72
Wenyou Yange7b848d2015-03-11 10:08:12 +080073 .arm
74
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010075/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
76 * void __iomem *ramc1, int memctrl)
77 */
Andrew Victoreaad2db2008-09-21 21:35:18 +010078ENTRY(at91_slow_clock)
79 /* Save registers on stack */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010080 stmfd sp!, {r4 - r12, lr}
Andrew Victoreaad2db2008-09-21 21:35:18 +010081
82 /*
83 * Register usage:
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +010084 * R0 = Base address of AT91_PMC
85 * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
86 * R2 = Base address of second RAM Controller or 0 if not present
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010087 * R3 = Memory controller
Andrew Victoreaad2db2008-09-21 21:35:18 +010088 * R4 = temporary register
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010089 * R5 = temporary register
Andrew Victoreaad2db2008-09-21 21:35:18 +010090 */
Andrew Victoreaad2db2008-09-21 21:35:18 +010091
92 /* Drain write buffer */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010093 mov tmp1, #0
94 mcr p15, 0, tmp1, c7, c10, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +010095
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010096 cmp memctrl, #AT91_MEMCTRL_MC
97 bne ddr_sr_enable
98
99 /*
100 * at91rm9200 Memory controller
101 */
Andrew Victoreaad2db2008-09-21 21:35:18 +0100102 /* Put SDRAM in self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100103 mov tmp1, #1
Jean-Christophe PLAGNIOL-VILLARD1a269ad2011-11-16 02:58:31 +0800104 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100105 b sdr_sr_done
106
107 /*
108 * DDRSDR Memory controller
109 */
110ddr_sr_enable:
111 cmp memctrl, #AT91_MEMCTRL_DDRSDR
112 bne sdr_sr_enable
Andrew Victoreaad2db2008-09-21 21:35:18 +0100113
Peter Rosin02f513a2015-02-05 14:02:09 +0800114 /* LPDDR1 --> force DDR2 mode during self-refresh */
115 ldr tmp1, [sdramc, #AT91_DDRSDRC_MDR]
116 str tmp1, .saved_sam9_mdr
117 bic tmp1, tmp1, #~AT91_DDRSDRC_MD
118 cmp tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR
119 ldreq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
120 biceq tmp1, tmp1, #AT91_DDRSDRC_MD
121 orreq tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2
122 streq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
123
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100124 /* prepare for DDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100125 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
126 str tmp1, .saved_sam9_lpr
127 bic tmp1, #AT91_DDRSDRC_LPCB
128 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100129
130 /* figure out if we use the second ram controller */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100131 cmp ramc1, #0
Peter Rosin02f513a2015-02-05 14:02:09 +0800132 beq ddr_no_2nd_ctrl
133
134 ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR]
135 str tmp2, .saved_sam9_mdr1
136 bic tmp2, tmp2, #~AT91_DDRSDRC_MD
137 cmp tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR
138 ldreq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
139 biceq tmp2, tmp2, #AT91_DDRSDRC_MD
140 orreq tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2
141 streq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
142
143 ldr tmp2, [ramc1, #AT91_DDRSDRC_LPR]
144 str tmp2, .saved_sam9_lpr1
145 bic tmp2, #AT91_DDRSDRC_LPCB
146 orr tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100147
148 /* Enable DDRAM self-refresh mode */
Peter Rosin02f513a2015-02-05 14:02:09 +0800149 str tmp2, [ramc1, #AT91_DDRSDRC_LPR]
150ddr_no_2nd_ctrl:
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100151 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100152
153 b sdr_sr_done
154
155 /*
156 * SDRAMC Memory controller
157 */
158sdr_sr_enable:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100159 /* Enable SDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100160 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
161 str tmp1, .saved_sam9_lpr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100162
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100163 bic tmp1, #AT91_SDRAMC_LPCB
164 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
165 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100166
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100167sdr_sr_done:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100168 /* Save Master clock setting */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800169 ldr tmp1, [pmc, #AT91_PMC_MCKR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100170 str tmp1, .saved_mckr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100171
172 /*
173 * Set the Master clock source to slow clock
174 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100175 bic tmp1, tmp1, #AT91_PMC_CSS
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800176 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100177
178 wait_mckrdy
179
180#ifdef SLOWDOWN_MASTER_CLOCK
181 /*
182 * Set the Master Clock PRES and MDIV fields.
183 *
184 * See AT91RM9200 errata #27 and #28 for details.
185 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100186 mov tmp1, #0
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800187 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100188
189 wait_mckrdy
190#endif
191
192 /* Save PLLA setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800193 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100194 str tmp1, .saved_pllar
Andrew Victoreaad2db2008-09-21 21:35:18 +0100195
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100196 mov tmp1, #AT91_PMC_PLLCOUNT
197 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800198 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100199
Andrew Victoreaad2db2008-09-21 21:35:18 +0100200 /* Save PLLB setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800201 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100202 str tmp1, .saved_pllbr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100203
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100204 mov tmp1, #AT91_PMC_PLLCOUNT
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800205 str tmp1, [pmc, #AT91_CKGR_PLLBR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100206
Andrew Victoreaad2db2008-09-21 21:35:18 +0100207 /* Turn off the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800208 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100209 bic tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800210 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800211 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100212
213 /* Wait for interrupt */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100214 mcr p15, 0, tmp1, c7, c0, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +0100215
216 /* Turn on the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800217 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100218 orr tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800219 orr tmp1, tmp1, #AT91_PMC_KEY
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_moscrdy
223
224 /* Restore PLLB setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100225 ldr tmp1, .saved_pllbr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800226 str tmp1, [pmc, #AT91_CKGR_PLLBR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100227
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100228 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100229 bne 1f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100230 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100231 beq 2f
2321:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100233 wait_pllblock
Anders Larsen9823f1a2010-04-08 11:48:16 +01002342:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100235
236 /* Restore PLLA setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100237 ldr tmp1, .saved_pllar
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800238 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100239
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100240 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100241 bne 3f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100242 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100243 beq 4f
2443:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100245 wait_pllalock
Anders Larsen9823f1a2010-04-08 11:48:16 +01002464:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100247
248#ifdef SLOWDOWN_MASTER_CLOCK
249 /*
250 * First set PRES if it was not 0,
251 * than set CSS and MDIV fields.
252 *
253 * See AT91RM9200 errata #27 and #28 for details.
254 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100255 ldr tmp1, .saved_mckr
256 tst tmp1, #AT91_PMC_PRES
Andrew Victoreaad2db2008-09-21 21:35:18 +0100257 beq 2f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100258 and tmp1, tmp1, #AT91_PMC_PRES
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800259 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100260
261 wait_mckrdy
262#endif
263
264 /*
265 * Restore master clock setting
266 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +01002672: ldr tmp1, .saved_mckr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800268 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100269
270 wait_mckrdy
271
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100272 /*
273 * at91rm9200 Memory controller
274 * Do nothing - self-refresh is automatically disabled.
275 */
276 cmp memctrl, #AT91_MEMCTRL_MC
277 beq ram_restored
278
279 /*
280 * DDRSDR Memory controller
281 */
282 cmp memctrl, #AT91_MEMCTRL_DDRSDR
283 bne sdr_en_restore
Peter Rosin02f513a2015-02-05 14:02:09 +0800284 /* Restore MDR in case of LPDDR1 */
285 ldr tmp1, .saved_sam9_mdr
286 str tmp1, [sdramc, #AT91_DDRSDRC_MDR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100287 /* Restore LPR on AT91 with DDRAM */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100288 ldr tmp1, .saved_sam9_lpr
289 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100290
291 /* if we use the second ram controller */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100292 cmp ramc1, #0
Peter Rosin02f513a2015-02-05 14:02:09 +0800293 ldrne tmp2, .saved_sam9_mdr1
294 strne tmp2, [ramc1, #AT91_DDRSDRC_MDR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100295 ldrne tmp2, .saved_sam9_lpr1
296 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100297
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100298 b ram_restored
299
300 /*
301 * SDRAMC Memory controller
302 */
303sdr_en_restore:
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100304 /* Restore LPR on AT91 with SDRAM */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100305 ldr tmp1, .saved_sam9_lpr
306 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100307
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100308ram_restored:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100309 /* Restore registers, and return */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100310 ldmfd sp!, {r4 - r12, pc}
Andrew Victoreaad2db2008-09-21 21:35:18 +0100311
312
313.saved_mckr:
314 .word 0
315
316.saved_pllar:
317 .word 0
318
319.saved_pllbr:
320 .word 0
321
322.saved_sam9_lpr:
323 .word 0
324
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100325.saved_sam9_lpr1:
326 .word 0
327
Peter Rosin02f513a2015-02-05 14:02:09 +0800328.saved_sam9_mdr:
329 .word 0
330
331.saved_sam9_mdr1:
332 .word 0
333
Andrew Victoreaad2db2008-09-21 21:35:18 +0100334ENTRY(at91_slow_clock_sz)
335 .word .-at91_slow_clock