xref: /linux/arch/arm/mach-at91/pm_suspend.S (revision e58e871becec2d3b04ed91c0c16fe8deac9c9dfa)
1/*
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#include <linux/linkage.h>
15#include <linux/clk/at91_pmc.h>
16#include "pm.h"
17#include "generated/at91_pm_data-offsets.h"
18
19#define	SRAMC_SELF_FRESH_ACTIVE		0x01
20#define	SRAMC_SELF_FRESH_EXIT		0x00
21
22pmc	.req	r0
23tmp1	.req	r4
24tmp2	.req	r5
25
26/*
27 * Wait until master clock is ready (after switching master clock source)
28 */
29	.macro wait_mckrdy
301:	ldr	tmp1, [pmc, #AT91_PMC_SR]
31	tst	tmp1, #AT91_PMC_MCKRDY
32	beq	1b
33	.endm
34
35/*
36 * Wait until master oscillator has stabilized.
37 */
38	.macro wait_moscrdy
391:	ldr	tmp1, [pmc, #AT91_PMC_SR]
40	tst	tmp1, #AT91_PMC_MOSCS
41	beq	1b
42	.endm
43
44/*
45 * Wait until PLLA has locked.
46 */
47	.macro wait_pllalock
481:	ldr	tmp1, [pmc, #AT91_PMC_SR]
49	tst	tmp1, #AT91_PMC_LOCKA
50	beq	1b
51	.endm
52
53/*
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
71	.text
72
73	.arm
74
75/*
76 * void at91_suspend_sram_fn(struct at91_pm_data*)
77 * @input param:
78 * 	@r0: base address of struct at91_pm_data
79 */
80/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
81	.align 3
82ENTRY(at91_pm_suspend_in_sram)
83	/* Save registers on stack */
84	stmfd	sp!, {r4 - r12, lr}
85
86	/* Drain write buffer */
87	mov	tmp1, #0
88	mcr	p15, 0, tmp1, c7, c10, 4
89
90	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
100
101	/* Active the self-refresh mode */
102	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
103	bl	at91_sramc_self_refresh
104
105	ldr	r0, .pm_mode
106	tst	r0, #AT91_PM_SLOW_CLOCK
107	beq	skip_disable_main_clock
108
109	ldr	pmc, .pmc_base
110
111	/* Save Master clock setting */
112	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
113	str	tmp1, .saved_mckr
114
115	/*
116	 * Set the Master clock source to slow clock
117	 */
118	bic	tmp1, tmp1, #AT91_PMC_CSS
119	str	tmp1, [pmc, #AT91_PMC_MCKR]
120
121	wait_mckrdy
122
123	/* Save PLLA setting and disable it */
124	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
125	str	tmp1, .saved_pllar
126
127	mov	tmp1, #AT91_PMC_PLLCOUNT
128	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
129	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
130
131	/* Turn off the main oscillator */
132	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
133	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
134	orr	tmp1, tmp1, #AT91_PMC_KEY
135	str	tmp1, [pmc, #AT91_CKGR_MOR]
136
137skip_disable_main_clock:
138	ldr	pmc, .pmc_base
139
140	/* Wait for interrupt */
141	at91_cpu_idle
142
143	ldr	r0, .pm_mode
144	tst	r0, #AT91_PM_SLOW_CLOCK
145	beq	skip_enable_main_clock
146
147	ldr	pmc, .pmc_base
148
149	/* Turn on the main oscillator */
150	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
151	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
152	orr	tmp1, tmp1, #AT91_PMC_KEY
153	str	tmp1, [pmc, #AT91_CKGR_MOR]
154
155	wait_moscrdy
156
157	/* Restore PLLA setting */
158	ldr	tmp1, .saved_pllar
159	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
160
161	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
162	bne	3f
163	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
164	beq	4f
1653:
166	wait_pllalock
1674:
168
169	/*
170	 * Restore master clock setting
171	 */
172	ldr	tmp1, .saved_mckr
173	str	tmp1, [pmc, #AT91_PMC_MCKR]
174
175	wait_mckrdy
176
177skip_enable_main_clock:
178	/* 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}
184ENDPROC(at91_pm_suspend_in_sram)
185
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
204	/*
205	 * at91rm9200 Memory controller
206	 */
207
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
217	str	r3, [r2, #AT91_MC_SDRAMC_SRR]
218	b	exit_sramc_sf
219
220ddrc_sf:
221	cmp	r1, #AT91_MEMCTRL_DDRSDR
222	bne	sdramc_sf
223
224	/*
225	 * DDR Memory controller
226	 */
227	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:
272	/* Restore MDR in case of LPDDR1 */
273	ldr	r3, .saved_sam9_mdr
274	str	r3, [r2, #AT91_DDRSDRC_MDR]
275	/* Restore LPR on AT91 with DDRAM */
276	ldr	r3, .saved_sam9_lpr
277	str	r3, [r2, #AT91_DDRSDRC_LPR]
278
279	/* 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]
286
287	b	exit_sramc_sf
288
289	/*
290	 * SDRAMC Memory controller
291	 */
292sdramc_sf:
293	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
294	beq	sdramc_exit_sf
295
296	/* 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]
302
303sdramc_exit_sf:
304	ldr	r3, .saved_sam9_lpr
305	str	r3, [r2, #AT91_SDRAMC_LPR]
306
307exit_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
319.pm_mode:
320	.word 0
321.saved_mckr:
322	.word 0
323.saved_pllar:
324	.word 0
325.saved_sam9_lpr:
326	.word 0
327.saved_sam9_lpr1:
328	.word 0
329.saved_sam9_mdr:
330	.word 0
331.saved_sam9_mdr1:
332	.word 0
333
334ENTRY(at91_pm_suspend_in_sram_sz)
335	.word .-at91_pm_suspend_in_sram
336