xref: /openbmc/linux/arch/arm/mach-at91/pm_suspend.S (revision d7a3d85e)
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 <mach/at91_ramc.h>
17#include "pm.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_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
77 *			void __iomem *ramc1, int memctrl)
78 * @input param:
79 * 	@r0: base address of AT91_PMC
80 *  	@r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
81 *	@r2: base address of second SDRAM Controller or 0 if not present
82 *	@r3: pm information
83 */
84ENTRY(at91_pm_suspend_in_sram)
85	/* Save registers on stack */
86	stmfd	sp!, {r4 - r12, lr}
87
88	/* Drain write buffer */
89	mov	tmp1, #0
90	mcr	p15, 0, tmp1, c7, c10, 4
91
92	str	r0, .pmc_base
93	str	r1, .sramc_base
94	str	r2, .sramc1_base
95
96	and	r0, r3, #AT91_PM_MEMTYPE_MASK
97	str	r0, .memtype
98
99	lsr	r0, r3, #AT91_PM_MODE_OFFSET
100	and	r0, r0, #AT91_PM_MODE_MASK
101	str	r0, .pm_mode
102
103	/* Active the self-refresh mode */
104	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
105	bl	at91_sramc_self_refresh
106
107	ldr	r0, .pm_mode
108	tst	r0, #AT91_PM_SLOW_CLOCK
109	beq	skip_disable_main_clock
110
111	ldr	pmc, .pmc_base
112
113	/* Save Master clock setting */
114	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
115	str	tmp1, .saved_mckr
116
117	/*
118	 * Set the Master clock source to slow clock
119	 */
120	bic	tmp1, tmp1, #AT91_PMC_CSS
121	str	tmp1, [pmc, #AT91_PMC_MCKR]
122
123	wait_mckrdy
124
125	/* Save PLLA setting and disable it */
126	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
127	str	tmp1, .saved_pllar
128
129	mov	tmp1, #AT91_PMC_PLLCOUNT
130	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
131	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
132
133	/* Turn off the main oscillator */
134	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
135	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
136	orr	tmp1, tmp1, #AT91_PMC_KEY
137	str	tmp1, [pmc, #AT91_CKGR_MOR]
138
139skip_disable_main_clock:
140	ldr	pmc, .pmc_base
141
142	/* Wait for interrupt */
143	at91_cpu_idle
144
145	ldr	r0, .pm_mode
146	tst	r0, #AT91_PM_SLOW_CLOCK
147	beq	skip_enable_main_clock
148
149	ldr	pmc, .pmc_base
150
151	/* Turn on the main oscillator */
152	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
153	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
154	orr	tmp1, tmp1, #AT91_PMC_KEY
155	str	tmp1, [pmc, #AT91_CKGR_MOR]
156
157	wait_moscrdy
158
159	/* Restore PLLA setting */
160	ldr	tmp1, .saved_pllar
161	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
162
163	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
164	bne	3f
165	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
166	beq	4f
1673:
168	wait_pllalock
1694:
170
171	/*
172	 * Restore master clock setting
173	 */
174	ldr	tmp1, .saved_mckr
175	str	tmp1, [pmc, #AT91_PMC_MCKR]
176
177	wait_mckrdy
178
179skip_enable_main_clock:
180	/* Exit the self-refresh mode */
181	mov	r0, #SRAMC_SELF_FRESH_EXIT
182	bl	at91_sramc_self_refresh
183
184	/* Restore registers, and return */
185	ldmfd	sp!, {r4 - r12, pc}
186ENDPROC(at91_pm_suspend_in_sram)
187
188/*
189 * void at91_sramc_self_refresh(unsigned int is_active)
190 *
191 * @input param:
192 *	@r0: 1 - active self-refresh mode
193 *	     0 - exit self-refresh mode
194 * register usage:
195 * 	@r1: memory type
196 *	@r2: base address of the sram controller
197 */
198
199ENTRY(at91_sramc_self_refresh)
200	ldr	r1, .memtype
201	ldr	r2, .sramc_base
202
203	cmp	r1, #AT91_MEMCTRL_MC
204	bne	ddrc_sf
205
206	/*
207	 * at91rm9200 Memory controller
208	 */
209
210	 /*
211	  * For exiting the self-refresh mode, do nothing,
212	  * automatically exit the self-refresh mode.
213	  */
214	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
215	beq	exit_sramc_sf
216
217	/* Active SDRAM self-refresh mode */
218	mov	r3, #1
219	str	r3, [r2, #AT91RM9200_SDRAMC_SRR]
220	b	exit_sramc_sf
221
222ddrc_sf:
223	cmp	r1, #AT91_MEMCTRL_DDRSDR
224	bne	sdramc_sf
225
226	/*
227	 * DDR Memory controller
228	 */
229	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
230	beq	ddrc_exit_sf
231
232	/* LPDDR1 --> force DDR2 mode during self-refresh */
233	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
234	str	r3, .saved_sam9_mdr
235	bic	r3, r3, #~AT91_DDRSDRC_MD
236	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
237	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
238	biceq	r3, r3, #AT91_DDRSDRC_MD
239	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
240	streq	r3, [r2, #AT91_DDRSDRC_MDR]
241
242	/* Active DDRC self-refresh mode */
243	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
244	str	r3, .saved_sam9_lpr
245	bic	r3, r3, #AT91_DDRSDRC_LPCB
246	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
247	str	r3, [r2, #AT91_DDRSDRC_LPR]
248
249	/* If using the 2nd ddr controller */
250	ldr	r2, .sramc1_base
251	cmp	r2, #0
252	beq	no_2nd_ddrc
253
254	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
255	str	r3, .saved_sam9_mdr1
256	bic	r3, r3, #~AT91_DDRSDRC_MD
257	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
258	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
259	biceq	r3, r3, #AT91_DDRSDRC_MD
260	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
261	streq	r3, [r2, #AT91_DDRSDRC_MDR]
262
263	/* Active DDRC self-refresh mode */
264	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
265	str	r3, .saved_sam9_lpr1
266	bic	r3, r3, #AT91_DDRSDRC_LPCB
267	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
268	str	r3, [r2, #AT91_DDRSDRC_LPR]
269
270no_2nd_ddrc:
271	b	exit_sramc_sf
272
273ddrc_exit_sf:
274	/* Restore MDR in case of LPDDR1 */
275	ldr	r3, .saved_sam9_mdr
276	str	r3, [r2, #AT91_DDRSDRC_MDR]
277	/* Restore LPR on AT91 with DDRAM */
278	ldr	r3, .saved_sam9_lpr
279	str	r3, [r2, #AT91_DDRSDRC_LPR]
280
281	/* If using the 2nd ddr controller */
282	ldr	r2, .sramc1_base
283	cmp	r2, #0
284	ldrne	r3, .saved_sam9_mdr1
285	strne	r3, [r2, #AT91_DDRSDRC_MDR]
286	ldrne	r3, .saved_sam9_lpr1
287	strne	r3, [r2, #AT91_DDRSDRC_LPR]
288
289	b	exit_sramc_sf
290
291	/*
292	 * SDRAMC Memory controller
293	 */
294sdramc_sf:
295	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
296	beq	sdramc_exit_sf
297
298	/* Active SDRAMC self-refresh mode */
299	ldr	r3, [r2, #AT91_SDRAMC_LPR]
300	str	r3, .saved_sam9_lpr
301	bic	r3, r3, #AT91_SDRAMC_LPCB
302	orr	r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
303	str	r3, [r2, #AT91_SDRAMC_LPR]
304
305sdramc_exit_sf:
306	ldr	r3, .saved_sam9_lpr
307	str	r3, [r2, #AT91_SDRAMC_LPR]
308
309exit_sramc_sf:
310	mov	pc, lr
311ENDPROC(at91_sramc_self_refresh)
312
313.pmc_base:
314	.word 0
315.sramc_base:
316	.word 0
317.sramc1_base:
318	.word 0
319.memtype:
320	.word 0
321.pm_mode:
322	.word 0
323.saved_mckr:
324	.word 0
325.saved_pllar:
326	.word 0
327.saved_sam9_lpr:
328	.word 0
329.saved_sam9_lpr1:
330	.word 0
331.saved_sam9_mdr:
332	.word 0
333.saved_sam9_mdr1:
334	.word 0
335
336ENTRY(at91_pm_suspend_in_sram_sz)
337	.word .-at91_pm_suspend_in_sram
338