blob: 8ab80e579be0bb59998b9a93e343ac83143d9611 [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
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010073/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
74 * void __iomem *ramc1, int memctrl)
75 */
Andrew Victoreaad2db2008-09-21 21:35:18 +010076ENTRY(at91_slow_clock)
77 /* Save registers on stack */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010078 stmfd sp!, {r4 - r12, lr}
Andrew Victoreaad2db2008-09-21 21:35:18 +010079
80 /*
81 * Register usage:
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +010082 * 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
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010085 * R3 = Memory controller
Andrew Victoreaad2db2008-09-21 21:35:18 +010086 * R4 = temporary register
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010087 * R5 = temporary register
Andrew Victoreaad2db2008-09-21 21:35:18 +010088 */
Andrew Victoreaad2db2008-09-21 21:35:18 +010089
90 /* Drain write buffer */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010091 mov tmp1, #0
92 mcr p15, 0, tmp1, c7, c10, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +010093
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010094 cmp memctrl, #AT91_MEMCTRL_MC
95 bne ddr_sr_enable
96
97 /*
98 * at91rm9200 Memory controller
99 */
Andrew Victoreaad2db2008-09-21 21:35:18 +0100100 /* Put SDRAM in self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100101 mov tmp1, #1
Jean-Christophe PLAGNIOL-VILLARD1a269ad2011-11-16 02:58:31 +0800102 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100103 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
Andrew Victoreaad2db2008-09-21 21:35:18 +0100111
Peter Rosin02f513a2015-02-05 14:02:09 +0800112 /* LPDDR1 --> force DDR2 mode during self-refresh */
113 ldr tmp1, [sdramc, #AT91_DDRSDRC_MDR]
114 str tmp1, .saved_sam9_mdr
115 bic tmp1, tmp1, #~AT91_DDRSDRC_MD
116 cmp tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR
117 ldreq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
118 biceq tmp1, tmp1, #AT91_DDRSDRC_MD
119 orreq tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2
120 streq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
121
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100122 /* prepare for DDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100123 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
124 str tmp1, .saved_sam9_lpr
125 bic tmp1, #AT91_DDRSDRC_LPCB
126 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100127
128 /* figure out if we use the second ram controller */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100129 cmp ramc1, #0
Peter Rosin02f513a2015-02-05 14:02:09 +0800130 beq ddr_no_2nd_ctrl
131
132 ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR]
133 str tmp2, .saved_sam9_mdr1
134 bic tmp2, tmp2, #~AT91_DDRSDRC_MD
135 cmp tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR
136 ldreq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
137 biceq tmp2, tmp2, #AT91_DDRSDRC_MD
138 orreq tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2
139 streq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
140
141 ldr tmp2, [ramc1, #AT91_DDRSDRC_LPR]
142 str tmp2, .saved_sam9_lpr1
143 bic tmp2, #AT91_DDRSDRC_LPCB
144 orr tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100145
146 /* Enable DDRAM self-refresh mode */
Peter Rosin02f513a2015-02-05 14:02:09 +0800147 str tmp2, [ramc1, #AT91_DDRSDRC_LPR]
148ddr_no_2nd_ctrl:
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100149 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100150
151 b sdr_sr_done
152
153 /*
154 * SDRAMC Memory controller
155 */
156sdr_sr_enable:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100157 /* Enable SDRAM self-refresh mode */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100158 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
159 str tmp1, .saved_sam9_lpr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100160
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100161 bic tmp1, #AT91_SDRAMC_LPCB
162 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
163 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100164
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100165sdr_sr_done:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100166 /* Save Master clock setting */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800167 ldr tmp1, [pmc, #AT91_PMC_MCKR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100168 str tmp1, .saved_mckr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100169
170 /*
171 * Set the Master clock source to slow clock
172 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100173 bic tmp1, tmp1, #AT91_PMC_CSS
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800174 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100175
176 wait_mckrdy
177
178#ifdef SLOWDOWN_MASTER_CLOCK
179 /*
180 * Set the Master Clock PRES and MDIV fields.
181 *
182 * See AT91RM9200 errata #27 and #28 for details.
183 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100184 mov tmp1, #0
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800185 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100186
187 wait_mckrdy
188#endif
189
190 /* Save PLLA setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800191 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100192 str tmp1, .saved_pllar
Andrew Victoreaad2db2008-09-21 21:35:18 +0100193
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100194 mov tmp1, #AT91_PMC_PLLCOUNT
195 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800196 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100197
Andrew Victoreaad2db2008-09-21 21:35:18 +0100198 /* Save PLLB setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800199 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100200 str tmp1, .saved_pllbr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100201
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100202 mov tmp1, #AT91_PMC_PLLCOUNT
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800203 str tmp1, [pmc, #AT91_CKGR_PLLBR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100204
Andrew Victoreaad2db2008-09-21 21:35:18 +0100205 /* Turn off the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800206 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100207 bic tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800208 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800209 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100210
211 /* Wait for interrupt */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100212 mcr p15, 0, tmp1, c7, c0, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +0100213
214 /* Turn on the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800215 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100216 orr tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800217 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800218 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100219
220 wait_moscrdy
221
222 /* Restore PLLB setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100223 ldr tmp1, .saved_pllbr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800224 str tmp1, [pmc, #AT91_CKGR_PLLBR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100225
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100226 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100227 bne 1f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100228 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100229 beq 2f
2301:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100231 wait_pllblock
Anders Larsen9823f1a2010-04-08 11:48:16 +01002322:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100233
234 /* Restore PLLA setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100235 ldr tmp1, .saved_pllar
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800236 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100237
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100238 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100239 bne 3f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100240 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100241 beq 4f
2423:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100243 wait_pllalock
Anders Larsen9823f1a2010-04-08 11:48:16 +01002444:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100245
246#ifdef SLOWDOWN_MASTER_CLOCK
247 /*
248 * First set PRES if it was not 0,
249 * than set CSS and MDIV fields.
250 *
251 * See AT91RM9200 errata #27 and #28 for details.
252 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100253 ldr tmp1, .saved_mckr
254 tst tmp1, #AT91_PMC_PRES
Andrew Victoreaad2db2008-09-21 21:35:18 +0100255 beq 2f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100256 and tmp1, tmp1, #AT91_PMC_PRES
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800257 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100258
259 wait_mckrdy
260#endif
261
262 /*
263 * Restore master clock setting
264 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +01002652: ldr tmp1, .saved_mckr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800266 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100267
268 wait_mckrdy
269
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100270 /*
271 * at91rm9200 Memory controller
272 * Do nothing - self-refresh is automatically disabled.
273 */
274 cmp memctrl, #AT91_MEMCTRL_MC
275 beq ram_restored
276
277 /*
278 * DDRSDR Memory controller
279 */
280 cmp memctrl, #AT91_MEMCTRL_DDRSDR
281 bne sdr_en_restore
Peter Rosin02f513a2015-02-05 14:02:09 +0800282 /* Restore MDR in case of LPDDR1 */
283 ldr tmp1, .saved_sam9_mdr
284 str tmp1, [sdramc, #AT91_DDRSDRC_MDR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100285 /* Restore LPR on AT91 with DDRAM */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100286 ldr tmp1, .saved_sam9_lpr
287 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100288
289 /* if we use the second ram controller */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100290 cmp ramc1, #0
Peter Rosin02f513a2015-02-05 14:02:09 +0800291 ldrne tmp2, .saved_sam9_mdr1
292 strne tmp2, [ramc1, #AT91_DDRSDRC_MDR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100293 ldrne tmp2, .saved_sam9_lpr1
294 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100295
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100296 b ram_restored
297
298 /*
299 * SDRAMC Memory controller
300 */
301sdr_en_restore:
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100302 /* Restore LPR on AT91 with SDRAM */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100303 ldr tmp1, .saved_sam9_lpr
304 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100305
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100306ram_restored:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100307 /* Restore registers, and return */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100308 ldmfd sp!, {r4 - r12, pc}
Andrew Victoreaad2db2008-09-21 21:35:18 +0100309
310
311.saved_mckr:
312 .word 0
313
314.saved_pllar:
315 .word 0
316
317.saved_pllbr:
318 .word 0
319
320.saved_sam9_lpr:
321 .word 0
322
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100323.saved_sam9_lpr1:
324 .word 0
325
Peter Rosin02f513a2015-02-05 14:02:09 +0800326.saved_sam9_mdr:
327 .word 0
328
329.saved_sam9_mdr1:
330 .word 0
331
Andrew Victoreaad2db2008-09-21 21:35:18 +0100332ENTRY(at91_slow_clock_sz)
333 .word .-at91_slow_clock