blob: a25defda3d226c98469c6150a001266aeec4c2fa [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 */
Andrew Victoreaad2db2008-09-21 21:35:18 +010014#include <linux/linkage.h>
Boris BREZILLON2edb90a2013-10-11 09:37:45 +020015#include <linux/clk/at91_pmc.h>
Wenyou Yang23be4be2015-03-09 11:49:46 +080016#include "pm.h"
Andrew Victoreaad2db2008-09-21 21:35:18 +010017
Wenyou Yang0ab285c2015-03-09 11:48:26 +080018#define SRAMC_SELF_FRESH_ACTIVE 0x01
19#define SRAMC_SELF_FRESH_EXIT 0x00
20
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +010021pmc .req r0
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010022tmp1 .req r4
23tmp2 .req r5
Andrew Victoreaad2db2008-09-21 21:35:18 +010024
25/*
26 * Wait until master clock is ready (after switching master clock source)
27 */
28 .macro wait_mckrdy
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800291: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010030 tst tmp1, #AT91_PMC_MCKRDY
Andrew Victoreaad2db2008-09-21 21:35:18 +010031 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010032 .endm
33
34/*
35 * Wait until master oscillator has stabilized.
36 */
37 .macro wait_moscrdy
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800381: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010039 tst tmp1, #AT91_PMC_MOSCS
Andrew Victoreaad2db2008-09-21 21:35:18 +010040 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010041 .endm
42
43/*
44 * Wait until PLLA has locked.
45 */
46 .macro wait_pllalock
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800471: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010048 tst tmp1, #AT91_PMC_LOCKA
Andrew Victoreaad2db2008-09-21 21:35:18 +010049 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010050 .endm
51
Wenyou Yang20567652015-03-09 11:53:46 +080052/*
53 * Put the processor to enter the idle state
54 */
55 .macro at91_cpu_idle
56
57#if defined(CONFIG_CPU_V7)
58 mov tmp1, #AT91_PMC_PCK
59 str tmp1, [pmc, #AT91_PMC_SCDR]
60
61 dsb
62
63 wfi @ Wait For Interrupt
64#else
65 mcr p15, 0, tmp1, c7, c0, 4
66#endif
67
68 .endm
69
Andrew Victoreaad2db2008-09-21 21:35:18 +010070 .text
71
Wenyou Yange7b848d2015-03-11 10:08:12 +080072 .arm
73
Wenyou Yang5726a8b2015-03-09 11:51:09 +080074/*
75 * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010076 * void __iomem *ramc1, int memctrl)
Wenyou Yang5726a8b2015-03-09 11:51:09 +080077 * @input param:
78 * @r0: base address of AT91_PMC
79 * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
80 * @r2: base address of second SDRAM Controller or 0 if not present
81 * @r3: pm information
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010082 */
Patrick Doyle5fcf8d12015-10-16 12:39:05 +020083/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
84 .align 3
Wenyou Yang5726a8b2015-03-09 11:51:09 +080085ENTRY(at91_pm_suspend_in_sram)
Andrew Victoreaad2db2008-09-21 21:35:18 +010086 /* Save registers on stack */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010087 stmfd sp!, {r4 - r12, lr}
Andrew Victoreaad2db2008-09-21 21:35:18 +010088
Andrew Victoreaad2db2008-09-21 21:35:18 +010089 /* Drain write buffer */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010090 mov tmp1, #0
91 mcr p15, 0, tmp1, c7, c10, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +010092
Wenyou Yang0ab285c2015-03-09 11:48:26 +080093 str r0, .pmc_base
94 str r1, .sramc_base
95 str r2, .sramc1_base
Wenyou Yang23be4be2015-03-09 11:49:46 +080096
97 and r0, r3, #AT91_PM_MEMTYPE_MASK
98 str r0, .memtype
99
100 lsr r0, r3, #AT91_PM_MODE_OFFSET
101 and r0, r0, #AT91_PM_MODE_MASK
102 str r0, .pm_mode
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100103
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800104 /* Active the self-refresh mode */
105 mov r0, #SRAMC_SELF_FRESH_ACTIVE
106 bl at91_sramc_self_refresh
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100107
Wenyou Yang23be4be2015-03-09 11:49:46 +0800108 ldr r0, .pm_mode
109 tst r0, #AT91_PM_SLOW_CLOCK
110 beq skip_disable_main_clock
111
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800112 ldr pmc, .pmc_base
Andrew Victoreaad2db2008-09-21 21:35:18 +0100113
Andrew Victoreaad2db2008-09-21 21:35:18 +0100114 /* Save Master clock setting */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800115 ldr tmp1, [pmc, #AT91_PMC_MCKR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100116 str tmp1, .saved_mckr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100117
118 /*
119 * Set the Master clock source to slow clock
120 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100121 bic tmp1, tmp1, #AT91_PMC_CSS
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800122 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100123
124 wait_mckrdy
125
Andrew Victoreaad2db2008-09-21 21:35:18 +0100126 /* Save PLLA setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800127 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100128 str tmp1, .saved_pllar
Andrew Victoreaad2db2008-09-21 21:35:18 +0100129
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100130 mov tmp1, #AT91_PMC_PLLCOUNT
131 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800132 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100133
Andrew Victoreaad2db2008-09-21 21:35:18 +0100134 /* Turn off the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800135 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100136 bic tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800137 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800138 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100139
Wenyou Yang23be4be2015-03-09 11:49:46 +0800140skip_disable_main_clock:
141 ldr pmc, .pmc_base
142
Andrew Victoreaad2db2008-09-21 21:35:18 +0100143 /* Wait for interrupt */
Wenyou Yang20567652015-03-09 11:53:46 +0800144 at91_cpu_idle
Andrew Victoreaad2db2008-09-21 21:35:18 +0100145
Wenyou Yang23be4be2015-03-09 11:49:46 +0800146 ldr r0, .pm_mode
147 tst r0, #AT91_PM_SLOW_CLOCK
148 beq skip_enable_main_clock
149
150 ldr pmc, .pmc_base
151
Andrew Victoreaad2db2008-09-21 21:35:18 +0100152 /* Turn on the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800153 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100154 orr tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800155 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800156 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100157
158 wait_moscrdy
159
Andrew Victoreaad2db2008-09-21 21:35:18 +0100160 /* Restore PLLA setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100161 ldr tmp1, .saved_pllar
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800162 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100163
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100164 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100165 bne 3f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100166 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100167 beq 4f
1683:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100169 wait_pllalock
Anders Larsen9823f1a2010-04-08 11:48:16 +01001704:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100171
Andrew Victoreaad2db2008-09-21 21:35:18 +0100172 /*
173 * Restore master clock setting
174 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800175 ldr tmp1, .saved_mckr
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
Wenyou Yang23be4be2015-03-09 11:49:46 +0800180skip_enable_main_clock:
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800181 /* Exit the self-refresh mode */
182 mov r0, #SRAMC_SELF_FRESH_EXIT
183 bl at91_sramc_self_refresh
184
185 /* Restore registers, and return */
186 ldmfd sp!, {r4 - r12, pc}
Wenyou Yang5726a8b2015-03-09 11:51:09 +0800187ENDPROC(at91_pm_suspend_in_sram)
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800188
189/*
190 * void at91_sramc_self_refresh(unsigned int is_active)
191 *
192 * @input param:
193 * @r0: 1 - active self-refresh mode
194 * 0 - exit self-refresh mode
195 * register usage:
196 * @r1: memory type
197 * @r2: base address of the sram controller
198 */
199
200ENTRY(at91_sramc_self_refresh)
201 ldr r1, .memtype
202 ldr r2, .sramc_base
203
204 cmp r1, #AT91_MEMCTRL_MC
205 bne ddrc_sf
206
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100207 /*
208 * at91rm9200 Memory controller
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100209 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800210
211 /*
212 * For exiting the self-refresh mode, do nothing,
213 * automatically exit the self-refresh mode.
214 */
215 tst r0, #SRAMC_SELF_FRESH_ACTIVE
216 beq exit_sramc_sf
217
218 /* Active SDRAM self-refresh mode */
219 mov r3, #1
Alexandre Bellonid7d45f22015-03-16 15:14:50 +0100220 str r3, [r2, #AT91_MC_SDRAMC_SRR]
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800221 b exit_sramc_sf
222
223ddrc_sf:
224 cmp r1, #AT91_MEMCTRL_DDRSDR
225 bne sdramc_sf
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100226
227 /*
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800228 * DDR Memory controller
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100229 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800230 tst r0, #SRAMC_SELF_FRESH_ACTIVE
231 beq ddrc_exit_sf
232
233 /* LPDDR1 --> force DDR2 mode during self-refresh */
234 ldr r3, [r2, #AT91_DDRSDRC_MDR]
235 str r3, .saved_sam9_mdr
236 bic r3, r3, #~AT91_DDRSDRC_MD
237 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
238 ldreq r3, [r2, #AT91_DDRSDRC_MDR]
239 biceq r3, r3, #AT91_DDRSDRC_MD
240 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
241 streq r3, [r2, #AT91_DDRSDRC_MDR]
242
243 /* Active DDRC self-refresh mode */
244 ldr r3, [r2, #AT91_DDRSDRC_LPR]
245 str r3, .saved_sam9_lpr
246 bic r3, r3, #AT91_DDRSDRC_LPCB
247 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
248 str r3, [r2, #AT91_DDRSDRC_LPR]
249
250 /* If using the 2nd ddr controller */
251 ldr r2, .sramc1_base
252 cmp r2, #0
253 beq no_2nd_ddrc
254
255 ldr r3, [r2, #AT91_DDRSDRC_MDR]
256 str r3, .saved_sam9_mdr1
257 bic r3, r3, #~AT91_DDRSDRC_MD
258 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
259 ldreq r3, [r2, #AT91_DDRSDRC_MDR]
260 biceq r3, r3, #AT91_DDRSDRC_MD
261 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
262 streq r3, [r2, #AT91_DDRSDRC_MDR]
263
264 /* Active DDRC self-refresh mode */
265 ldr r3, [r2, #AT91_DDRSDRC_LPR]
266 str r3, .saved_sam9_lpr1
267 bic r3, r3, #AT91_DDRSDRC_LPCB
268 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
269 str r3, [r2, #AT91_DDRSDRC_LPR]
270
271no_2nd_ddrc:
272 b exit_sramc_sf
273
274ddrc_exit_sf:
Peter Rosin02f513a2015-02-05 14:02:09 +0800275 /* Restore MDR in case of LPDDR1 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800276 ldr r3, .saved_sam9_mdr
277 str r3, [r2, #AT91_DDRSDRC_MDR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100278 /* Restore LPR on AT91 with DDRAM */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800279 ldr r3, .saved_sam9_lpr
280 str r3, [r2, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100281
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800282 /* If using the 2nd ddr controller */
283 ldr r2, .sramc1_base
284 cmp r2, #0
285 ldrne r3, .saved_sam9_mdr1
286 strne r3, [r2, #AT91_DDRSDRC_MDR]
287 ldrne r3, .saved_sam9_lpr1
288 strne r3, [r2, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100289
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800290 b exit_sramc_sf
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100291
292 /*
293 * SDRAMC Memory controller
294 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800295sdramc_sf:
296 tst r0, #SRAMC_SELF_FRESH_ACTIVE
297 beq sdramc_exit_sf
Andrew Victoreaad2db2008-09-21 21:35:18 +0100298
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800299 /* Active SDRAMC self-refresh mode */
300 ldr r3, [r2, #AT91_SDRAMC_LPR]
301 str r3, .saved_sam9_lpr
302 bic r3, r3, #AT91_SDRAMC_LPCB
303 orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
304 str r3, [r2, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100305
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800306sdramc_exit_sf:
307 ldr r3, .saved_sam9_lpr
308 str r3, [r2, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100309
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800310exit_sramc_sf:
311 mov pc, lr
312ENDPROC(at91_sramc_self_refresh)
313
314.pmc_base:
315 .word 0
316.sramc_base:
317 .word 0
318.sramc1_base:
319 .word 0
320.memtype:
321 .word 0
Wenyou Yang23be4be2015-03-09 11:49:46 +0800322.pm_mode:
323 .word 0
Andrew Victoreaad2db2008-09-21 21:35:18 +0100324.saved_mckr:
325 .word 0
Andrew Victoreaad2db2008-09-21 21:35:18 +0100326.saved_pllar:
327 .word 0
Andrew Victoreaad2db2008-09-21 21:35:18 +0100328.saved_sam9_lpr:
329 .word 0
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100330.saved_sam9_lpr1:
331 .word 0
Peter Rosin02f513a2015-02-05 14:02:09 +0800332.saved_sam9_mdr:
333 .word 0
Peter Rosin02f513a2015-02-05 14:02:09 +0800334.saved_sam9_mdr1:
335 .word 0
336
Wenyou Yang5726a8b2015-03-09 11:51:09 +0800337ENTRY(at91_pm_suspend_in_sram_sz)
338 .word .-at91_pm_suspend_in_sram