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