blob: 96781daa671a33f15d8939da690eeeed3d44f9f4 [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:
Alexandre Belloni8c9290a2017-03-28 12:26:18 +02007 * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee>
Andrew Victoreaad2db2008-09-21 21:35:18 +01008 *
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"
Alexandre Belloni65cc1a52017-01-31 18:12:57 +010017#include "generated/at91_pm_data-offsets.h"
Andrew Victoreaad2db2008-09-21 21:35:18 +010018
Wenyou Yang0ab285c2015-03-09 11:48:26 +080019#define SRAMC_SELF_FRESH_ACTIVE 0x01
20#define SRAMC_SELF_FRESH_EXIT 0x00
21
Jean-Christophe PLAGNIOL-VILLARD8ff12ad32012-02-22 17:50:54 +010022pmc .req r0
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010023tmp1 .req r4
24tmp2 .req r5
Andrew Victoreaad2db2008-09-21 21:35:18 +010025
26/*
27 * Wait until master clock is ready (after switching master clock source)
28 */
29 .macro wait_mckrdy
Sylvain Rochetad4a38d2015-02-05 14:00:37 +0800301: ldr tmp1, [pmc, #AT91_PMC_SR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010031 tst tmp1, #AT91_PMC_MCKRDY
Andrew Victoreaad2db2008-09-21 21:35:18 +010032 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010033 .endm
34
35/*
36 * Wait until master oscillator has stabilized.
37 */
38 .macro wait_moscrdy
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_MOSCS
Andrew Victoreaad2db2008-09-21 21:35:18 +010041 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010042 .endm
43
44/*
45 * Wait until PLLA has locked.
46 */
47 .macro wait_pllalock
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_LOCKA
Andrew Victoreaad2db2008-09-21 21:35:18 +010050 beq 1b
Andrew Victoreaad2db2008-09-21 21:35:18 +010051 .endm
52
Wenyou Yang20567652015-03-09 11:53:46 +080053/*
54 * Put the processor to enter the idle state
55 */
56 .macro at91_cpu_idle
57
58#if defined(CONFIG_CPU_V7)
59 mov tmp1, #AT91_PMC_PCK
60 str tmp1, [pmc, #AT91_PMC_SCDR]
61
62 dsb
63
64 wfi @ Wait For Interrupt
65#else
66 mcr p15, 0, tmp1, c7, c0, 4
67#endif
68
69 .endm
70
Andrew Victoreaad2db2008-09-21 21:35:18 +010071 .text
72
Wenyou Yange7b848d2015-03-11 10:08:12 +080073 .arm
74
Wenyou Yang5726a8b2015-03-09 11:51:09 +080075/*
Alexandre Belloni65cc1a52017-01-31 18:12:57 +010076 * void at91_suspend_sram_fn(struct at91_pm_data*)
Wenyou Yang5726a8b2015-03-09 11:51:09 +080077 * @input param:
Alexandre Belloni65cc1a52017-01-31 18:12:57 +010078 * @r0: base address of struct at91_pm_data
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010079 */
Patrick Doyle5fcf8d12015-10-16 12:39:05 +020080/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
81 .align 3
Wenyou Yang5726a8b2015-03-09 11:51:09 +080082ENTRY(at91_pm_suspend_in_sram)
Andrew Victoreaad2db2008-09-21 21:35:18 +010083 /* Save registers on stack */
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +010084 stmfd sp!, {r4 - r12, lr}
Andrew Victoreaad2db2008-09-21 21:35:18 +010085
Andrew Victoreaad2db2008-09-21 21:35:18 +010086 /* Drain write buffer */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +010087 mov tmp1, #0
88 mcr p15, 0, tmp1, c7, c10, 4
Andrew Victoreaad2db2008-09-21 21:35:18 +010089
Alexandre Belloni65cc1a52017-01-31 18:12:57 +010090 ldr tmp1, [r0, #PM_DATA_PMC]
91 str tmp1, .pmc_base
92 ldr tmp1, [r0, #PM_DATA_RAMC0]
93 str tmp1, .sramc_base
94 ldr tmp1, [r0, #PM_DATA_RAMC1]
95 str tmp1, .sramc1_base
96 ldr tmp1, [r0, #PM_DATA_MEMCTRL]
97 str tmp1, .memtype
98 ldr tmp1, [r0, #PM_DATA_MODE]
99 str tmp1, .pm_mode
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100100
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800101 /* Active the self-refresh mode */
102 mov r0, #SRAMC_SELF_FRESH_ACTIVE
103 bl at91_sramc_self_refresh
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100104
Wenyou Yang23be4be2015-03-09 11:49:46 +0800105 ldr r0, .pm_mode
106 tst r0, #AT91_PM_SLOW_CLOCK
107 beq skip_disable_main_clock
108
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800109 ldr pmc, .pmc_base
Andrew Victoreaad2db2008-09-21 21:35:18 +0100110
Andrew Victoreaad2db2008-09-21 21:35:18 +0100111 /* Save Master clock setting */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800112 ldr tmp1, [pmc, #AT91_PMC_MCKR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100113 str tmp1, .saved_mckr
Andrew Victoreaad2db2008-09-21 21:35:18 +0100114
115 /*
116 * Set the Master clock source to slow clock
117 */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100118 bic tmp1, tmp1, #AT91_PMC_CSS
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800119 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100120
121 wait_mckrdy
122
Andrew Victoreaad2db2008-09-21 21:35:18 +0100123 /* Save PLLA setting and disable it */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800124 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100125 str tmp1, .saved_pllar
Andrew Victoreaad2db2008-09-21 21:35:18 +0100126
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100127 mov tmp1, #AT91_PMC_PLLCOUNT
128 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800129 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100130
Andrew Victoreaad2db2008-09-21 21:35:18 +0100131 /* Turn off the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800132 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100133 bic tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800134 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800135 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100136
Wenyou Yang23be4be2015-03-09 11:49:46 +0800137skip_disable_main_clock:
138 ldr pmc, .pmc_base
139
Andrew Victoreaad2db2008-09-21 21:35:18 +0100140 /* Wait for interrupt */
Wenyou Yang20567652015-03-09 11:53:46 +0800141 at91_cpu_idle
Andrew Victoreaad2db2008-09-21 21:35:18 +0100142
Wenyou Yang23be4be2015-03-09 11:49:46 +0800143 ldr r0, .pm_mode
144 tst r0, #AT91_PM_SLOW_CLOCK
145 beq skip_enable_main_clock
146
147 ldr pmc, .pmc_base
148
Andrew Victoreaad2db2008-09-21 21:35:18 +0100149 /* Turn on the main oscillator */
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800150 ldr tmp1, [pmc, #AT91_CKGR_MOR]
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100151 orr tmp1, tmp1, #AT91_PMC_MOSCEN
Patrice Vilchez59574572015-02-12 10:52:13 +0800152 orr tmp1, tmp1, #AT91_PMC_KEY
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800153 str tmp1, [pmc, #AT91_CKGR_MOR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100154
155 wait_moscrdy
156
Andrew Victoreaad2db2008-09-21 21:35:18 +0100157 /* Restore PLLA setting */
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100158 ldr tmp1, .saved_pllar
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800159 str tmp1, [pmc, #AT91_CKGR_PLLAR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100160
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100161 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100162 bne 3f
Jean-Christophe PLAGNIOL-VILLARD0dcfed12012-02-22 17:50:53 +0100163 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
Anders Larsen9823f1a2010-04-08 11:48:16 +0100164 beq 4f
1653:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100166 wait_pllalock
Anders Larsen9823f1a2010-04-08 11:48:16 +01001674:
Andrew Victoreaad2db2008-09-21 21:35:18 +0100168
Andrew Victoreaad2db2008-09-21 21:35:18 +0100169 /*
170 * Restore master clock setting
171 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800172 ldr tmp1, .saved_mckr
Jean-Christophe PLAGNIOL-VILLARDb5514952011-11-25 09:59:46 +0800173 str tmp1, [pmc, #AT91_PMC_MCKR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100174
175 wait_mckrdy
176
Wenyou Yang23be4be2015-03-09 11:49:46 +0800177skip_enable_main_clock:
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800178 /* Exit the self-refresh mode */
179 mov r0, #SRAMC_SELF_FRESH_EXIT
180 bl at91_sramc_self_refresh
181
182 /* Restore registers, and return */
183 ldmfd sp!, {r4 - r12, pc}
Wenyou Yang5726a8b2015-03-09 11:51:09 +0800184ENDPROC(at91_pm_suspend_in_sram)
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800185
186/*
187 * void at91_sramc_self_refresh(unsigned int is_active)
188 *
189 * @input param:
190 * @r0: 1 - active self-refresh mode
191 * 0 - exit self-refresh mode
192 * register usage:
193 * @r1: memory type
194 * @r2: base address of the sram controller
195 */
196
197ENTRY(at91_sramc_self_refresh)
198 ldr r1, .memtype
199 ldr r2, .sramc_base
200
201 cmp r1, #AT91_MEMCTRL_MC
202 bne ddrc_sf
203
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100204 /*
205 * at91rm9200 Memory controller
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100206 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800207
208 /*
209 * For exiting the self-refresh mode, do nothing,
210 * automatically exit the self-refresh mode.
211 */
212 tst r0, #SRAMC_SELF_FRESH_ACTIVE
213 beq exit_sramc_sf
214
215 /* Active SDRAM self-refresh mode */
216 mov r3, #1
Alexandre Bellonid7d45f22015-03-16 15:14:50 +0100217 str r3, [r2, #AT91_MC_SDRAMC_SRR]
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800218 b exit_sramc_sf
219
220ddrc_sf:
221 cmp r1, #AT91_MEMCTRL_DDRSDR
222 bne sdramc_sf
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100223
224 /*
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800225 * DDR Memory controller
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100226 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800227 tst r0, #SRAMC_SELF_FRESH_ACTIVE
228 beq ddrc_exit_sf
229
230 /* LPDDR1 --> force DDR2 mode during self-refresh */
231 ldr r3, [r2, #AT91_DDRSDRC_MDR]
232 str r3, .saved_sam9_mdr
233 bic r3, r3, #~AT91_DDRSDRC_MD
234 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
235 ldreq r3, [r2, #AT91_DDRSDRC_MDR]
236 biceq r3, r3, #AT91_DDRSDRC_MD
237 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
238 streq r3, [r2, #AT91_DDRSDRC_MDR]
239
240 /* Active DDRC self-refresh mode */
241 ldr r3, [r2, #AT91_DDRSDRC_LPR]
242 str r3, .saved_sam9_lpr
243 bic r3, r3, #AT91_DDRSDRC_LPCB
244 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
245 str r3, [r2, #AT91_DDRSDRC_LPR]
246
247 /* If using the 2nd ddr controller */
248 ldr r2, .sramc1_base
249 cmp r2, #0
250 beq no_2nd_ddrc
251
252 ldr r3, [r2, #AT91_DDRSDRC_MDR]
253 str r3, .saved_sam9_mdr1
254 bic r3, r3, #~AT91_DDRSDRC_MD
255 cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
256 ldreq r3, [r2, #AT91_DDRSDRC_MDR]
257 biceq r3, r3, #AT91_DDRSDRC_MD
258 orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
259 streq r3, [r2, #AT91_DDRSDRC_MDR]
260
261 /* Active DDRC self-refresh mode */
262 ldr r3, [r2, #AT91_DDRSDRC_LPR]
263 str r3, .saved_sam9_lpr1
264 bic r3, r3, #AT91_DDRSDRC_LPCB
265 orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
266 str r3, [r2, #AT91_DDRSDRC_LPR]
267
268no_2nd_ddrc:
269 b exit_sramc_sf
270
271ddrc_exit_sf:
Peter Rosin02f513a2015-02-05 14:02:09 +0800272 /* Restore MDR in case of LPDDR1 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800273 ldr r3, .saved_sam9_mdr
274 str r3, [r2, #AT91_DDRSDRC_MDR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100275 /* Restore LPR on AT91 with DDRAM */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800276 ldr r3, .saved_sam9_lpr
277 str r3, [r2, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100278
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800279 /* If using the 2nd ddr controller */
280 ldr r2, .sramc1_base
281 cmp r2, #0
282 ldrne r3, .saved_sam9_mdr1
283 strne r3, [r2, #AT91_DDRSDRC_MDR]
284 ldrne r3, .saved_sam9_lpr1
285 strne r3, [r2, #AT91_DDRSDRC_LPR]
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100286
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800287 b exit_sramc_sf
Jean-Christophe PLAGNIOL-VILLARDfb7e1972012-02-22 17:50:55 +0100288
289 /*
290 * SDRAMC Memory controller
291 */
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800292sdramc_sf:
293 tst r0, #SRAMC_SELF_FRESH_ACTIVE
294 beq sdramc_exit_sf
Andrew Victoreaad2db2008-09-21 21:35:18 +0100295
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800296 /* Active SDRAMC self-refresh mode */
297 ldr r3, [r2, #AT91_SDRAMC_LPR]
298 str r3, .saved_sam9_lpr
299 bic r3, r3, #AT91_SDRAMC_LPCB
300 orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
301 str r3, [r2, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100302
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800303sdramc_exit_sf:
304 ldr r3, .saved_sam9_lpr
305 str r3, [r2, #AT91_SDRAMC_LPR]
Andrew Victoreaad2db2008-09-21 21:35:18 +0100306
Wenyou Yang0ab285c2015-03-09 11:48:26 +0800307exit_sramc_sf:
308 mov pc, lr
309ENDPROC(at91_sramc_self_refresh)
310
311.pmc_base:
312 .word 0
313.sramc_base:
314 .word 0
315.sramc1_base:
316 .word 0
317.memtype:
318 .word 0
Wenyou Yang23be4be2015-03-09 11:49:46 +0800319.pm_mode:
320 .word 0
Andrew Victoreaad2db2008-09-21 21:35:18 +0100321.saved_mckr:
322 .word 0
Andrew Victoreaad2db2008-09-21 21:35:18 +0100323.saved_pllar:
324 .word 0
Andrew Victoreaad2db2008-09-21 21:35:18 +0100325.saved_sam9_lpr:
326 .word 0
Nicolas Ferre7dca3342010-06-21 14:59:27 +0100327.saved_sam9_lpr1:
328 .word 0
Peter Rosin02f513a2015-02-05 14:02:09 +0800329.saved_sam9_mdr:
330 .word 0
Peter Rosin02f513a2015-02-05 14:02:09 +0800331.saved_sam9_mdr1:
332 .word 0
333
Wenyou Yang5726a8b2015-03-09 11:51:09 +0800334ENTRY(at91_pm_suspend_in_sram_sz)
335 .word .-at91_pm_suspend_in_sram