• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
18#define	SRAMC_SELF_FRESH_ACTIVE		0x01
19#define	SRAMC_SELF_FRESH_EXIT		0x00
20
21pmc	.req	r0
22tmp1	.req	r4
23tmp2	.req	r5
24
25/*
26 * Wait until master clock is ready (after switching master clock source)
27 */
28	.macro wait_mckrdy
291:	ldr	tmp1, [pmc, #AT91_PMC_SR]
30	tst	tmp1, #AT91_PMC_MCKRDY
31	beq	1b
32	.endm
33
34/*
35 * Wait until master oscillator has stabilized.
36 */
37	.macro wait_moscrdy
381:	ldr	tmp1, [pmc, #AT91_PMC_SR]
39	tst	tmp1, #AT91_PMC_MOSCS
40	beq	1b
41	.endm
42
43/*
44 * Wait until PLLA has locked.
45 */
46	.macro wait_pllalock
471:	ldr	tmp1, [pmc, #AT91_PMC_SR]
48	tst	tmp1, #AT91_PMC_LOCKA
49	beq	1b
50	.endm
51
52/*
53 * Put the processor to enter the idle state
54 */
55	.macro at91_cpu_idle
56
57#if defined(CONFIG_CPU_V7)
58	mov	tmp1, #AT91_PMC_PCK
59	str	tmp1, [pmc, #AT91_PMC_SCDR]
60
61	dsb
62
63	wfi		@ Wait For Interrupt
64#else
65	mcr	p15, 0, tmp1, c7, c0, 4
66#endif
67
68	.endm
69
70	.text
71
72	.arm
73
74/*
75 * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
76 *			void __iomem *ramc1, int memctrl)
77 * @input param:
78 * 	@r0: base address of AT91_PMC
79 *  	@r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
80 *	@r2: base address of second SDRAM Controller or 0 if not present
81 *	@r3: pm information
82 */
83/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
84	.align 3
85ENTRY(at91_pm_suspend_in_sram)
86	/* Save registers on stack */
87	stmfd	sp!, {r4 - r12, lr}
88
89	/* Drain write buffer */
90	mov	tmp1, #0
91	mcr	p15, 0, tmp1, c7, c10, 4
92
93	str	r0, .pmc_base
94	str	r1, .sramc_base
95	str	r2, .sramc1_base
96
97	and	r0, r3, #AT91_PM_MEMTYPE_MASK
98	str	r0, .memtype
99
100	lsr	r0, r3, #AT91_PM_MODE_OFFSET
101	and	r0, r0, #AT91_PM_MODE_MASK
102	str	r0, .pm_mode
103
104	/* Active the self-refresh mode */
105	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
106	bl	at91_sramc_self_refresh
107
108	ldr	r0, .pm_mode
109	tst	r0, #AT91_PM_SLOW_CLOCK
110	beq	skip_disable_main_clock
111
112	ldr	pmc, .pmc_base
113
114	/* Save Master clock setting */
115	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
116	str	tmp1, .saved_mckr
117
118	/*
119	 * Set the Master clock source to slow clock
120	 */
121	bic	tmp1, tmp1, #AT91_PMC_CSS
122	str	tmp1, [pmc, #AT91_PMC_MCKR]
123
124	wait_mckrdy
125
126	/* Save PLLA setting and disable it */
127	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
128	str	tmp1, .saved_pllar
129
130	mov	tmp1, #AT91_PMC_PLLCOUNT
131	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
132	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
133
134	/* Turn off the main oscillator */
135	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
136	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
137	orr	tmp1, tmp1, #AT91_PMC_KEY
138	str	tmp1, [pmc, #AT91_CKGR_MOR]
139
140skip_disable_main_clock:
141	ldr	pmc, .pmc_base
142
143	/* Wait for interrupt */
144	at91_cpu_idle
145
146	ldr	r0, .pm_mode
147	tst	r0, #AT91_PM_SLOW_CLOCK
148	beq	skip_enable_main_clock
149
150	ldr	pmc, .pmc_base
151
152	/* Turn on the main oscillator */
153	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
154	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
155	orr	tmp1, tmp1, #AT91_PMC_KEY
156	str	tmp1, [pmc, #AT91_CKGR_MOR]
157
158	wait_moscrdy
159
160	/* Restore PLLA setting */
161	ldr	tmp1, .saved_pllar
162	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
163
164	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
165	bne	3f
166	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
167	beq	4f
1683:
169	wait_pllalock
1704:
171
172	/*
173	 * Restore master clock setting
174	 */
175	ldr	tmp1, .saved_mckr
176	str	tmp1, [pmc, #AT91_PMC_MCKR]
177
178	wait_mckrdy
179
180skip_enable_main_clock:
181	/* Exit the self-refresh mode */
182	mov	r0, #SRAMC_SELF_FRESH_EXIT
183	bl	at91_sramc_self_refresh
184
185	/* Restore registers, and return */
186	ldmfd	sp!, {r4 - r12, pc}
187ENDPROC(at91_pm_suspend_in_sram)
188
189/*
190 * void at91_sramc_self_refresh(unsigned int is_active)
191 *
192 * @input param:
193 *	@r0: 1 - active self-refresh mode
194 *	     0 - exit self-refresh mode
195 * register usage:
196 * 	@r1: memory type
197 *	@r2: base address of the sram controller
198 */
199
200ENTRY(at91_sramc_self_refresh)
201	ldr	r1, .memtype
202	ldr	r2, .sramc_base
203
204	cmp	r1, #AT91_MEMCTRL_MC
205	bne	ddrc_sf
206
207	/*
208	 * at91rm9200 Memory controller
209	 */
210
211	 /*
212	  * For exiting the self-refresh mode, do nothing,
213	  * automatically exit the self-refresh mode.
214	  */
215	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
216	beq	exit_sramc_sf
217
218	/* Active SDRAM self-refresh mode */
219	mov	r3, #1
220	str	r3, [r2, #AT91_MC_SDRAMC_SRR]
221	b	exit_sramc_sf
222
223ddrc_sf:
224	cmp	r1, #AT91_MEMCTRL_DDRSDR
225	bne	sdramc_sf
226
227	/*
228	 * DDR Memory controller
229	 */
230	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
231	beq	ddrc_exit_sf
232
233	/* LPDDR1 --> force DDR2 mode during self-refresh */
234	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
235	str	r3, .saved_sam9_mdr
236	bic	r3, r3, #~AT91_DDRSDRC_MD
237	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
238	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
239	biceq	r3, r3, #AT91_DDRSDRC_MD
240	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
241	streq	r3, [r2, #AT91_DDRSDRC_MDR]
242
243	/* Active DDRC self-refresh mode */
244	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
245	str	r3, .saved_sam9_lpr
246	bic	r3, r3, #AT91_DDRSDRC_LPCB
247	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
248	str	r3, [r2, #AT91_DDRSDRC_LPR]
249
250	/* If using the 2nd ddr controller */
251	ldr	r2, .sramc1_base
252	cmp	r2, #0
253	beq	no_2nd_ddrc
254
255	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
256	str	r3, .saved_sam9_mdr1
257	bic	r3, r3, #~AT91_DDRSDRC_MD
258	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
259	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
260	biceq	r3, r3, #AT91_DDRSDRC_MD
261	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
262	streq	r3, [r2, #AT91_DDRSDRC_MDR]
263
264	/* Active DDRC self-refresh mode */
265	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
266	str	r3, .saved_sam9_lpr1
267	bic	r3, r3, #AT91_DDRSDRC_LPCB
268	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
269	str	r3, [r2, #AT91_DDRSDRC_LPR]
270
271no_2nd_ddrc:
272	b	exit_sramc_sf
273
274ddrc_exit_sf:
275	/* Restore MDR in case of LPDDR1 */
276	ldr	r3, .saved_sam9_mdr
277	str	r3, [r2, #AT91_DDRSDRC_MDR]
278	/* Restore LPR on AT91 with DDRAM */
279	ldr	r3, .saved_sam9_lpr
280	str	r3, [r2, #AT91_DDRSDRC_LPR]
281
282	/* If using the 2nd ddr controller */
283	ldr	r2, .sramc1_base
284	cmp	r2, #0
285	ldrne	r3, .saved_sam9_mdr1
286	strne	r3, [r2, #AT91_DDRSDRC_MDR]
287	ldrne	r3, .saved_sam9_lpr1
288	strne	r3, [r2, #AT91_DDRSDRC_LPR]
289
290	b	exit_sramc_sf
291
292	/*
293	 * SDRAMC Memory controller
294	 */
295sdramc_sf:
296	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
297	beq	sdramc_exit_sf
298
299	/* Active SDRAMC self-refresh mode */
300	ldr	r3, [r2, #AT91_SDRAMC_LPR]
301	str	r3, .saved_sam9_lpr
302	bic	r3, r3, #AT91_SDRAMC_LPCB
303	orr	r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
304	str	r3, [r2, #AT91_SDRAMC_LPR]
305
306sdramc_exit_sf:
307	ldr	r3, .saved_sam9_lpr
308	str	r3, [r2, #AT91_SDRAMC_LPR]
309
310exit_sramc_sf:
311	mov	pc, lr
312ENDPROC(at91_sramc_self_refresh)
313
314.pmc_base:
315	.word 0
316.sramc_base:
317	.word 0
318.sramc1_base:
319	.word 0
320.memtype:
321	.word 0
322.pm_mode:
323	.word 0
324.saved_mckr:
325	.word 0
326.saved_pllar:
327	.word 0
328.saved_sam9_lpr:
329	.word 0
330.saved_sam9_lpr1:
331	.word 0
332.saved_sam9_mdr:
333	.word 0
334.saved_sam9_mdr1:
335	.word 0
336
337ENTRY(at91_pm_suspend_in_sram_sz)
338	.word .-at91_pm_suspend_in_sram
339