xref: /openbmc/linux/arch/arm/mach-at91/pm_suspend.S (revision 68198dca)
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	/* Both ldrne below are here to preload their address in the TLB */
101	ldr	tmp1, [r0, #PM_DATA_SHDWC]
102	str	tmp1, .shdwc
103	cmp	tmp1, #0
104	ldrne	tmp2, [tmp1, #0]
105	ldr	tmp1, [r0, #PM_DATA_SFRBU]
106	str	tmp1, .sfr
107	cmp	tmp1, #0
108	ldrne	tmp2, [tmp1, #0x10]
109
110	/* Active the self-refresh mode */
111	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
112	bl	at91_sramc_self_refresh
113
114	ldr	r0, .pm_mode
115	cmp	r0, #AT91_PM_SLOW_CLOCK
116	beq	slow_clock
117	cmp	r0, #AT91_PM_BACKUP
118	beq	backup_mode
119
120	/* Wait for interrupt */
121	ldr	pmc, .pmc_base
122	at91_cpu_idle
123	b	exit_suspend
124
125slow_clock:
126	bl	at91_slowck_mode
127	b	exit_suspend
128backup_mode:
129	bl	at91_backup_mode
130	b	exit_suspend
131
132exit_suspend:
133	/* Exit the self-refresh mode */
134	mov	r0, #SRAMC_SELF_FRESH_EXIT
135	bl	at91_sramc_self_refresh
136
137	/* Restore registers, and return */
138	ldmfd	sp!, {r4 - r12, pc}
139ENDPROC(at91_pm_suspend_in_sram)
140
141ENTRY(at91_backup_mode)
142	/*BUMEN*/
143	ldr	r0, .sfr
144	mov	tmp1, #0x1
145	str	tmp1, [r0, #0x10]
146
147	/* Shutdown */
148	ldr	r0, .shdwc
149	mov	tmp1, #0xA5000000
150	add	tmp1, tmp1, #0x1
151	str	tmp1, [r0, #0]
152ENDPROC(at91_backup_mode)
153
154ENTRY(at91_slowck_mode)
155	ldr	pmc, .pmc_base
156
157	/* Save Master clock setting */
158	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
159	str	tmp1, .saved_mckr
160
161	/*
162	 * Set the Master clock source to slow clock
163	 */
164	bic	tmp1, tmp1, #AT91_PMC_CSS
165	str	tmp1, [pmc, #AT91_PMC_MCKR]
166
167	wait_mckrdy
168
169	/* Save PLLA setting and disable it */
170	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
171	str	tmp1, .saved_pllar
172
173	mov	tmp1, #AT91_PMC_PLLCOUNT
174	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
175	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
176
177	/* Turn off the main oscillator */
178	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
179	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
180	orr	tmp1, tmp1, #AT91_PMC_KEY
181	str	tmp1, [pmc, #AT91_CKGR_MOR]
182
183	/* Wait for interrupt */
184	at91_cpu_idle
185
186	/* Turn on the main oscillator */
187	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
188	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
189	orr	tmp1, tmp1, #AT91_PMC_KEY
190	str	tmp1, [pmc, #AT91_CKGR_MOR]
191
192	wait_moscrdy
193
194	/* Restore PLLA setting */
195	ldr	tmp1, .saved_pllar
196	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
197
198	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
199	bne	3f
200	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
201	beq	4f
2023:
203	wait_pllalock
2044:
205
206	/*
207	 * Restore master clock setting
208	 */
209	ldr	tmp1, .saved_mckr
210	str	tmp1, [pmc, #AT91_PMC_MCKR]
211
212	wait_mckrdy
213
214	mov	pc, lr
215ENDPROC(at91_slowck_mode)
216
217/*
218 * void at91_sramc_self_refresh(unsigned int is_active)
219 *
220 * @input param:
221 *	@r0: 1 - active self-refresh mode
222 *	     0 - exit self-refresh mode
223 * register usage:
224 * 	@r1: memory type
225 *	@r2: base address of the sram controller
226 */
227
228ENTRY(at91_sramc_self_refresh)
229	ldr	r1, .memtype
230	ldr	r2, .sramc_base
231
232	cmp	r1, #AT91_MEMCTRL_MC
233	bne	ddrc_sf
234
235	/*
236	 * at91rm9200 Memory controller
237	 */
238
239	 /*
240	  * For exiting the self-refresh mode, do nothing,
241	  * automatically exit the self-refresh mode.
242	  */
243	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
244	beq	exit_sramc_sf
245
246	/* Active SDRAM self-refresh mode */
247	mov	r3, #1
248	str	r3, [r2, #AT91_MC_SDRAMC_SRR]
249	b	exit_sramc_sf
250
251ddrc_sf:
252	cmp	r1, #AT91_MEMCTRL_DDRSDR
253	bne	sdramc_sf
254
255	/*
256	 * DDR Memory controller
257	 */
258	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
259	beq	ddrc_exit_sf
260
261	/* LPDDR1 --> force DDR2 mode during self-refresh */
262	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
263	str	r3, .saved_sam9_mdr
264	bic	r3, r3, #~AT91_DDRSDRC_MD
265	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
266	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
267	biceq	r3, r3, #AT91_DDRSDRC_MD
268	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
269	streq	r3, [r2, #AT91_DDRSDRC_MDR]
270
271	/* Active DDRC self-refresh mode */
272	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
273	str	r3, .saved_sam9_lpr
274	bic	r3, r3, #AT91_DDRSDRC_LPCB
275	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
276	str	r3, [r2, #AT91_DDRSDRC_LPR]
277
278	/* If using the 2nd ddr controller */
279	ldr	r2, .sramc1_base
280	cmp	r2, #0
281	beq	no_2nd_ddrc
282
283	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
284	str	r3, .saved_sam9_mdr1
285	bic	r3, r3, #~AT91_DDRSDRC_MD
286	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
287	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
288	biceq	r3, r3, #AT91_DDRSDRC_MD
289	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
290	streq	r3, [r2, #AT91_DDRSDRC_MDR]
291
292	/* Active DDRC self-refresh mode */
293	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
294	str	r3, .saved_sam9_lpr1
295	bic	r3, r3, #AT91_DDRSDRC_LPCB
296	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
297	str	r3, [r2, #AT91_DDRSDRC_LPR]
298
299no_2nd_ddrc:
300	b	exit_sramc_sf
301
302ddrc_exit_sf:
303	/* Restore MDR in case of LPDDR1 */
304	ldr	r3, .saved_sam9_mdr
305	str	r3, [r2, #AT91_DDRSDRC_MDR]
306	/* Restore LPR on AT91 with DDRAM */
307	ldr	r3, .saved_sam9_lpr
308	str	r3, [r2, #AT91_DDRSDRC_LPR]
309
310	/* If using the 2nd ddr controller */
311	ldr	r2, .sramc1_base
312	cmp	r2, #0
313	ldrne	r3, .saved_sam9_mdr1
314	strne	r3, [r2, #AT91_DDRSDRC_MDR]
315	ldrne	r3, .saved_sam9_lpr1
316	strne	r3, [r2, #AT91_DDRSDRC_LPR]
317
318	b	exit_sramc_sf
319
320	/*
321	 * SDRAMC Memory controller
322	 */
323sdramc_sf:
324	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
325	beq	sdramc_exit_sf
326
327	/* Active SDRAMC self-refresh mode */
328	ldr	r3, [r2, #AT91_SDRAMC_LPR]
329	str	r3, .saved_sam9_lpr
330	bic	r3, r3, #AT91_SDRAMC_LPCB
331	orr	r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
332	str	r3, [r2, #AT91_SDRAMC_LPR]
333
334sdramc_exit_sf:
335	ldr	r3, .saved_sam9_lpr
336	str	r3, [r2, #AT91_SDRAMC_LPR]
337
338exit_sramc_sf:
339	mov	pc, lr
340ENDPROC(at91_sramc_self_refresh)
341
342.pmc_base:
343	.word 0
344.sramc_base:
345	.word 0
346.sramc1_base:
347	.word 0
348.shdwc:
349	.word 0
350.sfr:
351	.word 0
352.memtype:
353	.word 0
354.pm_mode:
355	.word 0
356.saved_mckr:
357	.word 0
358.saved_pllar:
359	.word 0
360.saved_sam9_lpr:
361	.word 0
362.saved_sam9_lpr1:
363	.word 0
364.saved_sam9_mdr:
365	.word 0
366.saved_sam9_mdr1:
367	.word 0
368
369ENTRY(at91_pm_suspend_in_sram_sz)
370	.word .-at91_pm_suspend_in_sram
371