• 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#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 for main oscillator selection is done
46 */
47	.macro wait_moscsels
481:	ldr	tmp1, [pmc, #AT91_PMC_SR]
49	tst	tmp1, #AT91_PMC_MOSCSELS
50	beq	1b
51	.endm
52
53/*
54 * Wait until PLLA has locked.
55 */
56	.macro wait_pllalock
571:	ldr	tmp1, [pmc, #AT91_PMC_SR]
58	tst	tmp1, #AT91_PMC_LOCKA
59	beq	1b
60	.endm
61
62/*
63 * Put the processor to enter the idle state
64 */
65	.macro at91_cpu_idle
66
67#if defined(CONFIG_CPU_V7)
68	mov	tmp1, #AT91_PMC_PCK
69	str	tmp1, [pmc, #AT91_PMC_SCDR]
70
71	dsb
72
73	wfi		@ Wait For Interrupt
74#else
75	mcr	p15, 0, tmp1, c7, c0, 4
76#endif
77
78	.endm
79
80	.text
81
82	.arm
83
84/*
85 * void at91_suspend_sram_fn(struct at91_pm_data*)
86 * @input param:
87 * 	@r0: base address of struct at91_pm_data
88 */
89/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
90	.align 3
91ENTRY(at91_pm_suspend_in_sram)
92	/* Save registers on stack */
93	stmfd	sp!, {r4 - r12, lr}
94
95	/* Drain write buffer */
96	mov	tmp1, #0
97	mcr	p15, 0, tmp1, c7, c10, 4
98
99	ldr	tmp1, [r0, #PM_DATA_PMC]
100	str	tmp1, .pmc_base
101	ldr	tmp1, [r0, #PM_DATA_RAMC0]
102	str	tmp1, .sramc_base
103	ldr	tmp1, [r0, #PM_DATA_RAMC1]
104	str	tmp1, .sramc1_base
105	ldr	tmp1, [r0, #PM_DATA_MEMCTRL]
106	str	tmp1, .memtype
107	ldr	tmp1, [r0, #PM_DATA_MODE]
108	str	tmp1, .pm_mode
109	/* Both ldrne below are here to preload their address in the TLB */
110	ldr	tmp1, [r0, #PM_DATA_SHDWC]
111	str	tmp1, .shdwc
112	cmp	tmp1, #0
113	ldrne	tmp2, [tmp1, #0]
114	ldr	tmp1, [r0, #PM_DATA_SFRBU]
115	str	tmp1, .sfr
116	cmp	tmp1, #0
117	ldrne	tmp2, [tmp1, #0x10]
118
119	/* Active the self-refresh mode */
120	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
121	bl	at91_sramc_self_refresh
122
123	ldr	r0, .pm_mode
124	cmp	r0, #AT91_PM_STANDBY
125	beq	standby
126	cmp	r0, #AT91_PM_BACKUP
127	beq	backup_mode
128
129	bl	at91_ulp_mode
130	b	exit_suspend
131
132standby:
133	/* Wait for interrupt */
134	ldr	pmc, .pmc_base
135	at91_cpu_idle
136	b	exit_suspend
137
138backup_mode:
139	bl	at91_backup_mode
140	b	exit_suspend
141
142exit_suspend:
143	/* Exit the self-refresh mode */
144	mov	r0, #SRAMC_SELF_FRESH_EXIT
145	bl	at91_sramc_self_refresh
146
147	/* Restore registers, and return */
148	ldmfd	sp!, {r4 - r12, pc}
149ENDPROC(at91_pm_suspend_in_sram)
150
151ENTRY(at91_backup_mode)
152	/*BUMEN*/
153	ldr	r0, .sfr
154	mov	tmp1, #0x1
155	str	tmp1, [r0, #0x10]
156
157	/* Shutdown */
158	ldr	r0, .shdwc
159	mov	tmp1, #0xA5000000
160	add	tmp1, tmp1, #0x1
161	str	tmp1, [r0, #0]
162ENDPROC(at91_backup_mode)
163
164.macro at91_pm_ulp0_mode
165	ldr	pmc, .pmc_base
166
167	/* Turn off the crystal oscillator */
168	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
169	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
170	orr	tmp1, tmp1, #AT91_PMC_KEY
171	str	tmp1, [pmc, #AT91_CKGR_MOR]
172
173	/* Wait for interrupt */
174	at91_cpu_idle
175
176	/* Turn on the crystal oscillator */
177	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
178	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
179	orr	tmp1, tmp1, #AT91_PMC_KEY
180	str	tmp1, [pmc, #AT91_CKGR_MOR]
181
182	wait_moscrdy
183.endm
184
185/**
186 * Note: This procedure only applies on the platform which uses
187 * the external crystal oscillator as a main clock source.
188 */
189.macro at91_pm_ulp1_mode
190	ldr	pmc, .pmc_base
191
192	/* Switch the main clock source to 12-MHz RC oscillator */
193	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
194	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
195	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
196	orr	tmp1, tmp1, #AT91_PMC_KEY
197	str	tmp1, [pmc, #AT91_CKGR_MOR]
198
199	wait_moscsels
200
201	/* Disable the crystal oscillator */
202	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
203	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
204	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
205	orr	tmp1, tmp1, #AT91_PMC_KEY
206	str	tmp1, [pmc, #AT91_CKGR_MOR]
207
208	/* Switch the master clock source to main clock */
209	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
210	bic	tmp1, tmp1, #AT91_PMC_CSS
211	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
212	str	tmp1, [pmc, #AT91_PMC_MCKR]
213
214	wait_mckrdy
215
216	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
217	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
218	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
219	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
220	orr	tmp1, tmp1, #AT91_PMC_KEY
221	str	tmp1, [pmc, #AT91_CKGR_MOR]
222
223	/* Quirk for SAM9X60's PMC */
224	nop
225	nop
226
227	wait_mckrdy
228
229	/* Enable the crystal oscillator */
230	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
231	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
232	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
233	orr	tmp1, tmp1, #AT91_PMC_KEY
234	str	tmp1, [pmc, #AT91_CKGR_MOR]
235
236	wait_moscrdy
237
238	/* Switch the master clock source to slow clock */
239	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
240	bic	tmp1, tmp1, #AT91_PMC_CSS
241	str	tmp1, [pmc, #AT91_PMC_MCKR]
242
243	wait_mckrdy
244
245	/* Switch main clock source to crystal oscillator */
246	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
247	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
248	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
249	orr	tmp1, tmp1, #AT91_PMC_KEY
250	str	tmp1, [pmc, #AT91_CKGR_MOR]
251
252	wait_moscsels
253
254	/* Switch the master clock source to main clock */
255	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
256	bic	tmp1, tmp1, #AT91_PMC_CSS
257	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
258	str	tmp1, [pmc, #AT91_PMC_MCKR]
259
260	wait_mckrdy
261.endm
262
263ENTRY(at91_ulp_mode)
264	ldr	pmc, .pmc_base
265
266	/* Save Master clock setting */
267	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
268	str	tmp1, .saved_mckr
269
270	/*
271	 * Set the Master clock source to slow clock
272	 */
273	bic	tmp1, tmp1, #AT91_PMC_CSS
274	str	tmp1, [pmc, #AT91_PMC_MCKR]
275
276	wait_mckrdy
277
278	/* Save PLLA setting and disable it */
279	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
280	str	tmp1, .saved_pllar
281
282	mov	tmp1, #AT91_PMC_PLLCOUNT
283	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
284	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
285
286	ldr	r0, .pm_mode
287	cmp	r0, #AT91_PM_ULP1
288	beq	ulp1_mode
289
290	at91_pm_ulp0_mode
291	b	ulp_exit
292
293ulp1_mode:
294	at91_pm_ulp1_mode
295	b	ulp_exit
296
297ulp_exit:
298	ldr	pmc, .pmc_base
299
300	/* Restore PLLA setting */
301	ldr	tmp1, .saved_pllar
302	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
303
304	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
305	bne	3f
306	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
307	beq	4f
3083:
309	wait_pllalock
3104:
311
312	/*
313	 * Restore master clock setting
314	 */
315	ldr	tmp1, .saved_mckr
316	str	tmp1, [pmc, #AT91_PMC_MCKR]
317
318	wait_mckrdy
319
320	mov	pc, lr
321ENDPROC(at91_ulp_mode)
322
323/*
324 * void at91_sramc_self_refresh(unsigned int is_active)
325 *
326 * @input param:
327 *	@r0: 1 - active self-refresh mode
328 *	     0 - exit self-refresh mode
329 * register usage:
330 * 	@r1: memory type
331 *	@r2: base address of the sram controller
332 */
333
334ENTRY(at91_sramc_self_refresh)
335	ldr	r1, .memtype
336	ldr	r2, .sramc_base
337
338	cmp	r1, #AT91_MEMCTRL_MC
339	bne	ddrc_sf
340
341	/*
342	 * at91rm9200 Memory controller
343	 */
344
345	 /*
346	  * For exiting the self-refresh mode, do nothing,
347	  * automatically exit the self-refresh mode.
348	  */
349	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
350	beq	exit_sramc_sf
351
352	/* Active SDRAM self-refresh mode */
353	mov	r3, #1
354	str	r3, [r2, #AT91_MC_SDRAMC_SRR]
355	b	exit_sramc_sf
356
357ddrc_sf:
358	cmp	r1, #AT91_MEMCTRL_DDRSDR
359	bne	sdramc_sf
360
361	/*
362	 * DDR Memory controller
363	 */
364	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
365	beq	ddrc_exit_sf
366
367	/* LPDDR1 --> force DDR2 mode during self-refresh */
368	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
369	str	r3, .saved_sam9_mdr
370	bic	r3, r3, #~AT91_DDRSDRC_MD
371	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
372	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
373	biceq	r3, r3, #AT91_DDRSDRC_MD
374	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
375	streq	r3, [r2, #AT91_DDRSDRC_MDR]
376
377	/* Active DDRC self-refresh mode */
378	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
379	str	r3, .saved_sam9_lpr
380	bic	r3, r3, #AT91_DDRSDRC_LPCB
381	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
382	str	r3, [r2, #AT91_DDRSDRC_LPR]
383
384	/* If using the 2nd ddr controller */
385	ldr	r2, .sramc1_base
386	cmp	r2, #0
387	beq	no_2nd_ddrc
388
389	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
390	str	r3, .saved_sam9_mdr1
391	bic	r3, r3, #~AT91_DDRSDRC_MD
392	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
393	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
394	biceq	r3, r3, #AT91_DDRSDRC_MD
395	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
396	streq	r3, [r2, #AT91_DDRSDRC_MDR]
397
398	/* Active DDRC self-refresh mode */
399	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
400	str	r3, .saved_sam9_lpr1
401	bic	r3, r3, #AT91_DDRSDRC_LPCB
402	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
403	str	r3, [r2, #AT91_DDRSDRC_LPR]
404
405no_2nd_ddrc:
406	b	exit_sramc_sf
407
408ddrc_exit_sf:
409	/* Restore MDR in case of LPDDR1 */
410	ldr	r3, .saved_sam9_mdr
411	str	r3, [r2, #AT91_DDRSDRC_MDR]
412	/* Restore LPR on AT91 with DDRAM */
413	ldr	r3, .saved_sam9_lpr
414	str	r3, [r2, #AT91_DDRSDRC_LPR]
415
416	/* If using the 2nd ddr controller */
417	ldr	r2, .sramc1_base
418	cmp	r2, #0
419	ldrne	r3, .saved_sam9_mdr1
420	strne	r3, [r2, #AT91_DDRSDRC_MDR]
421	ldrne	r3, .saved_sam9_lpr1
422	strne	r3, [r2, #AT91_DDRSDRC_LPR]
423
424	b	exit_sramc_sf
425
426	/*
427	 * SDRAMC Memory controller
428	 */
429sdramc_sf:
430	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
431	beq	sdramc_exit_sf
432
433	/* Active SDRAMC self-refresh mode */
434	ldr	r3, [r2, #AT91_SDRAMC_LPR]
435	str	r3, .saved_sam9_lpr
436	bic	r3, r3, #AT91_SDRAMC_LPCB
437	orr	r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
438	str	r3, [r2, #AT91_SDRAMC_LPR]
439
440sdramc_exit_sf:
441	ldr	r3, .saved_sam9_lpr
442	str	r3, [r2, #AT91_SDRAMC_LPR]
443
444exit_sramc_sf:
445	mov	pc, lr
446ENDPROC(at91_sramc_self_refresh)
447
448.pmc_base:
449	.word 0
450.sramc_base:
451	.word 0
452.sramc1_base:
453	.word 0
454.shdwc:
455	.word 0
456.sfr:
457	.word 0
458.memtype:
459	.word 0
460.pm_mode:
461	.word 0
462.saved_mckr:
463	.word 0
464.saved_pllar:
465	.word 0
466.saved_sam9_lpr:
467	.word 0
468.saved_sam9_lpr1:
469	.word 0
470.saved_sam9_mdr:
471	.word 0
472.saved_sam9_mdr1:
473	.word 0
474
475ENTRY(at91_pm_suspend_in_sram_sz)
476	.word .-at91_pm_suspend_in_sram
477