xref: /optee_os/core/drivers/pm/sam/pm_suspend.S (revision 17022665de39e1982807a58fd9e41d8037128dcc)
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
2/*
3 * This file was imported from Linux arch/arm/mach-at91/pm_suspend.S and
4 * relicensed with dual GPL-2.0/BSD-2-Clause with Microchip agreement.
5 *
6 * Copyright (c) 2021, Microchip
7 */
8
9#include <arm.h>
10#include <arm32_macros.S>
11#include <asm.S>
12#include <at91_pmc.h>
13#include <drivers/sam/at91_ddr.h>
14#include <generated/pm-defines.h>
15
16#include "at91_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
24tmp3	.req	r6
25
26/*
27 * Wait until master clock is ready (after switching master clock source)
28 * @r_mckid:	register holding master clock identifier
29 *
30 * Side effects: overwrites tmp1
31 */
32.macro wait_mckrdy r_mckid
33#ifdef CFG_SAMA7G5
34	cmp	\r_mckid, #0
35	beq	1f
362:	ldr	tmp1, [pmc, #AT91_PMC_SR]
37	tst	tmp1, #AT91_PMC_MCKXRDY
38	beq	2b
39	b	3f
40#endif
411:	ldr	tmp1, [pmc, #AT91_PMC_SR]
42	tst	tmp1, #AT91_PMC_MCKRDY
43	beq	1b
443:
45.endm
46
47/*
48 * Wait until master oscillator has stabilized.
49 */
50.macro wait_moscrdy
511:	ldr	tmp1, [pmc, #AT91_PMC_SR]
52	tst	tmp1, #AT91_PMC_MOSCS
53	beq	1b
54.endm
55
56/*
57 * Wait for main oscillator selection is done
58 */
59.macro wait_moscsels
601:	ldr	tmp1, [pmc, #AT91_PMC_SR]
61	tst	tmp1, #AT91_PMC_MOSCSELS
62	beq	1b
63.endm
64
65/*
66 * Put the processor to enter the idle state
67 */
68.macro at91_cpu_idle
69
70	mov	tmp1, #AT91_PMC_PCK
71	str	tmp1, [pmc, #AT91_PMC_SCDR]
72
73	dsb
74
75	wfi		@ Wait For Interrupt
76
77.endm
78
79.section .text.psci.suspend
80
81.arm
82
83
84#define SUSPEND_FUNC(__name) \
85__name:
86
87#define SUSPEND_END_FUNC(__name) \
88	.size __name, .-__name
89
90.macro check_fit_in_sram since
91	.if (. - \since) > 0x10000
92		.error "Suspend assembly code exceeds dedicated SRAM size"
93	.endif
94.endm
95
96/*
97 * void at91_suspend_sram_fn(struct at91_pm_data*)
98 * @input param:
99 * 	@r0: base address of struct at91_pm_data
100 */
101.align 3
102.global at91_pm_suspend_in_sram
103SUSPEND_FUNC(at91_pm_suspend_in_sram)
104	/* Save registers on stack */
105	stmfd	sp!, {r4 - r12, lr}
106
107	/* Drain write buffer */
108	mov	tmp1, #0
109	mcr	p15, 0, tmp1, c7, c10, 4
110
111	ldr	tmp1, [r0, #PM_DATA_PMC]
112	str	tmp1, .pmc_base
113	ldr	tmp1, [r0, #PM_DATA_RAMC0]
114	str	tmp1, .sramc_base
115	ldr	tmp1, [r0, #PM_DATA_MODE]
116	str	tmp1, .pm_mode
117	/* Both ldrne below are here to preload their address in the TLB */
118	ldr	tmp1, [r0, #PM_DATA_SHDWC]
119	str	tmp1, .shdwc
120	cmp	tmp1, #0
121	ldrne	tmp2, [tmp1, #0]
122	ldr	tmp1, [r0, #PM_DATA_SFRBU]
123	str	tmp1, .sfrbu
124	cmp	tmp1, #0
125	ldrne	tmp2, [tmp1, #0x10]
126
127	/* Active the self-refresh mode */
128	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
129	bl	at91_sramc_self_refresh
130
131	ldr	r0, .pm_mode
132	cmp	r0, #AT91_PM_STANDBY
133	beq	standby
134	cmp	r0, #AT91_PM_BACKUP
135	beq	backup_mode
136
137	bl	at91_ulp_mode
138	b	exit_suspend
139
140standby:
141	/* Wait for interrupt */
142	ldr	pmc, .pmc_base
143	at91_cpu_idle
144	b	exit_suspend
145
146backup_mode:
147	bl	at91_backup_mode
148	b	exit_suspend
149
150exit_suspend:
151	/* Exit the self-refresh mode */
152	mov	r0, #SRAMC_SELF_FRESH_EXIT
153	bl	at91_sramc_self_refresh
154
155	/* Restore registers, and return */
156	ldmfd	sp!, {r4 - r12, pc}
157SUSPEND_END_FUNC(at91_pm_suspend_in_sram)
158
159SUSPEND_FUNC(at91_backup_mode)
160	/* Switch the master clock source to slow clock. */
161	ldr	pmc, .pmc_base
162	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
163	bic	tmp1, tmp1, #AT91_PMC_CSS
164	str	tmp1, [pmc, #AT91_PMC_MCKR]
165
166	mov	tmp3, #0
167	wait_mckrdy tmp3
168
169	/*BUMEN*/
170	ldr	r0, .sfrbu
171	mov	tmp1, #0x1
172	str	tmp1, [r0, #0x10]
173
174	/* Shutdown */
175	ldr	r0, .shdwc
176	mov	tmp1, #0xA5000000
177	add	tmp1, tmp1, #0x1
178#ifdef CFG_SAMA7G5
179	/* LPM Pad Enable: The LPM pad is set high */
180	orr	tmp1, tmp1, #0x200000
181#endif
182	str	tmp1, [r0, #0]
183SUSPEND_END_FUNC(at91_backup_mode)
184
185/*
186 * Set LPM
187 * @ena: 0 - disable LPM
188 *	 1 - enable LPM
189 *
190 * Side effects: overwrites tmp1, tmp3
191 */
192.macro at91_set_lpm ena
193#ifdef CFG_SAMA7G5
194	mov	tmp1, #\ena
195	cmp	tmp1, #1
196	movne	tmp3, #0x400000 /* LPM Pad Disable: The LPM pad is set low */
197	moveq	tmp3, #0x200000 /* LPM Pad Enable: The LPM pad is set high */
198	add	tmp3, #0xA5000000
199	ldr	tmp1, .shdwc
200	cmp	tmp1, #0
201	strne	tmp3, [tmp1]
202#endif
203.endm
204
205.macro at91_pm_ulp0_mode
206	ldr	pmc, .pmc_base
207	ldr	tmp2, .pm_mode
208
209	/* Check if ULP0 fast variant has been requested. */
210	cmp	tmp2, #AT91_PM_ULP0_FAST
211	bne	0f
212
213	/* Set highest prescaler for power saving */
214	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
215	bic	tmp1, tmp1, #AT91_PMC_PRES
216	orr	tmp1, tmp1, #AT91_PMC_PRES_64
217	str	tmp1, [pmc, #AT91_PMC_MCKR]
218
219	mov	tmp3, #0
220	wait_mckrdy tmp3
221	b	1f
222
2230:
224	/* Turn off the crystal oscillator */
225	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
226	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
227	orr	tmp1, tmp1, #AT91_PMC_KEY
228	str	tmp1, [pmc, #AT91_CKGR_MOR]
229
230	/* Save RC oscillator state */
231	ldr	tmp1, [pmc, #AT91_PMC_SR]
232	str	tmp1, .saved_osc_status
233	tst	tmp1, #AT91_PMC_MOSCRCS
234	bne	7f
235
236	/* Turn off RC oscillator */
237	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
238	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
239	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
240	orr	tmp1, tmp1, #AT91_PMC_KEY
241	str	tmp1, [pmc, #AT91_CKGR_MOR]
242
243	/* Wait main RC disabled done */
2442:	ldr	tmp1, [pmc, #AT91_PMC_SR]
245	tst	tmp1, #AT91_PMC_MOSCRCS
246	bne	2b
247
248	/* Enable LPM. */
2497:	at91_set_lpm 1
250
251	/* Wait for interrupt */
2521:	at91_cpu_idle
253
254	/* Check if ULP0 fast variant has been requested. */
255	cmp	tmp2, #AT91_PM_ULP0_FAST
256	bne	8f
257
258	/* Set lowest prescaler for fast resume. */
259	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
260	bic	tmp1, tmp1, #AT91_PMC_PRES
261	str	tmp1, [pmc, #AT91_PMC_MCKR]
262
263	mov	tmp3, #0
264	wait_mckrdy tmp3
265	b	6f
266
2678:	at91_set_lpm 0
268
2695:	/* Restore RC oscillator state */
270	ldr	tmp1, .saved_osc_status
271	tst	tmp1, #AT91_PMC_MOSCRCS
272	beq	4f
273
274	/* Turn on RC oscillator */
275	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
276	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
277	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
278	orr	tmp1, tmp1, #AT91_PMC_KEY
279	str	tmp1, [pmc, #AT91_CKGR_MOR]
280
281	/* Wait main RC stabilization */
2823:	ldr	tmp1, [pmc, #AT91_PMC_SR]
283	tst	tmp1, #AT91_PMC_MOSCRCS
284	beq	3b
285
286	/* Turn on the crystal oscillator */
2874:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
288	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
289	orr	tmp1, tmp1, #AT91_PMC_KEY
290	str	tmp1, [pmc, #AT91_CKGR_MOR]
291
292	wait_moscrdy
2936:
294.endm
295
296/**
297 * Note: This procedure only applies on the platform which uses
298 * the external crystal oscillator as a main clock source.
299 */
300.macro at91_pm_ulp1_mode
301	ldr	pmc, .pmc_base
302
303	/* Save RC oscillator state and check if it is enabled. */
304	ldr	tmp1, [pmc, #AT91_PMC_SR]
305	str	tmp1, .saved_osc_status
306	tst	tmp1, #AT91_PMC_MOSCRCS
307	bne	2f
308
309	/* Enable RC oscillator */
310	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
311	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
312	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
313	orr	tmp1, tmp1, #AT91_PMC_KEY
314	str	tmp1, [pmc, #AT91_CKGR_MOR]
315
316	/* Wait main RC stabilization */
3171:	ldr	tmp1, [pmc, #AT91_PMC_SR]
318	tst	tmp1, #AT91_PMC_MOSCRCS
319	beq	1b
320
321	/* Switch the main clock source to 12-MHz RC oscillator */
3222:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
323	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
324	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
325	orr	tmp1, tmp1, #AT91_PMC_KEY
326	str	tmp1, [pmc, #AT91_CKGR_MOR]
327
328	wait_moscsels
329
330	/* Disable the crystal oscillator */
331	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
332	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
333	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
334	orr	tmp1, tmp1, #AT91_PMC_KEY
335	str	tmp1, [pmc, #AT91_CKGR_MOR]
336
337	/* Switch the master clock source to main clock */
338	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
339	bic	tmp1, tmp1, #AT91_PMC_CSS
340	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
341	str	tmp1, [pmc, #AT91_PMC_MCKR]
342
343	mov	tmp3, #0
344	wait_mckrdy tmp3
345
346	/* Enable LPM */
347	at91_set_lpm 1
348
349	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
350	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
351	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
352	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
353	orr	tmp1, tmp1, #AT91_PMC_KEY
354	str	tmp1, [pmc, #AT91_CKGR_MOR]
355
356	/* Quirk for SAM9X60's PMC */
357	nop
358	nop
359
360	mov	tmp3, #0
361	wait_mckrdy tmp3
362
363	/* Disable LPM. */
364	at91_set_lpm 0
365
366	/* Enable the crystal oscillator */
367	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
368	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
369	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
370	orr	tmp1, tmp1, #AT91_PMC_KEY
371	str	tmp1, [pmc, #AT91_CKGR_MOR]
372
373	wait_moscrdy
374
375	/* Switch the master clock source to slow clock */
376	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
377	bic	tmp1, tmp1, #AT91_PMC_CSS
378	str	tmp1, [pmc, #AT91_PMC_MCKR]
379
380	mov	tmp3, #0
381	wait_mckrdy tmp3
382
383	/* Switch main clock source to crystal oscillator */
384	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
385	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
386	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
387	orr	tmp1, tmp1, #AT91_PMC_KEY
388	str	tmp1, [pmc, #AT91_CKGR_MOR]
389
390	wait_moscsels
391
392	/* Switch the master clock source to main clock */
393	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
394	bic	tmp1, tmp1, #AT91_PMC_CSS
395	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
396	str	tmp1, [pmc, #AT91_PMC_MCKR]
397
398	wait_mckrdy tmp3
399
400	/* Restore RC oscillator state */
401	ldr	tmp1, .saved_osc_status
402	tst	tmp1, #AT91_PMC_MOSCRCS
403	bne	3f
404
405	/* Disable RC oscillator */
406	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
407	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
408	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
409	orr	tmp1, tmp1, #AT91_PMC_KEY
410	str	tmp1, [pmc, #AT91_CKGR_MOR]
411
412	/* Wait RC oscillator disable done */
4134:	ldr	tmp1, [pmc, #AT91_PMC_SR]
414	tst	tmp1, #AT91_PMC_MOSCRCS
415	bne	4b
416
4173:
418.endm
419
420/*
421 * Save PLLA setting and disable it
422 *
423 * Side effects: overwrites tmp1, tmp2
424 */
425.macro at91_plla_disable
426#ifdef CFG_SAMA7G5
427	/* Save PLLA settings */
428	ldr	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
429	bic	tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
430	str	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
431
432	/* save div */
433	mov	tmp1, #0
434	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
435	bic	tmp2, tmp2, #0xffffff00
436	orr	tmp1, tmp1, tmp2
437
438	/* save mul */
439	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL1]
440	bic	tmp2, tmp2, #0xffffff
441	orr	tmp1, tmp1, tmp2
442	str	tmp1, .saved_pllar
443
444	/* step 2 */
445	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
446	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
447	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
448	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
449
450	/* step 3 */
451	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
452	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
453	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
454	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
455
456	/* step 4 */
457	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
458	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
459	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
460	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
461
462	/* step 5 */
463	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
464	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
465	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
466
467	/* step 6 */
468	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
469	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
470	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
471	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
472#else
473	/* Save PLLA setting and disable it */
474	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
475	str	tmp1, .saved_pllar
476
477	/* Disable PLLA. */
478	mov	tmp1, #AT91_PMC_PLLCOUNT
479	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
480	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
481#endif
4822:
483.endm
484
485/*
486 * Enable PLLA with the saved setting
487 *
488 * Side effects: overwrites tmp1, tmp2
489 */
490.macro at91_plla_enable
491#ifdef CFG_SAMA7G5
492	/* step 1 */
493	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
494	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
495	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
496	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
497
498	/* step 2 */
499	ldr	tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
500	str	tmp1, [pmc, #AT91_PMC_PLL_ACR]
501
502	/* step 3 */
503	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
504	ldr	tmp2, .saved_pllar
505	bic	tmp2, tmp2, #0xffffff
506	orr	tmp1, tmp1, tmp2
507	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
508
509	/* step 4 */
510	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
511	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
512	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
513	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
514
515	/* step 5 */
516	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
517	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK
518	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
519	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
520	bic	tmp1, tmp1, #0xff
521	ldr	tmp2, .saved_pllar
522	bic	tmp2, tmp2, #0xffffff00
523	orr	tmp1, tmp1, tmp2
524	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
525
526	/* step 6 */
527	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
528	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
529	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
530	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
531
532	/* step 7 */
5333:	ldr	tmp1, [pmc, #AT91_PMC_PLL_ISR0]
534	tst	tmp1, #0x1
535	beq	3b
536#else
537	ldr	tmp2, .saved_pllar
538
539	/* Restore PLLA setting */
540	str	tmp2, [pmc, #AT91_CKGR_PLLAR]
541
542	/* Enable PLLA. */
543	tst	tmp2, #(AT91_PMC_MUL &  0xff0000)
544	bne	1f
545	tst	tmp2, #(AT91_PMC_MUL & ~0xff0000)
546	beq	2f
547
5481:	ldr	tmp1, [pmc, #AT91_PMC_SR]
549	tst	tmp1, #AT91_PMC_LOCKA
550	beq	1b
5512:
552#endif
553.endm
554
555#ifdef CFG_SAMA7G5
556/*
557 * at91_mckx_ps_enable:	save MCK1..4 settings and switch it to main clock
558 *
559 * Side effects: overwrites tmp1, tmp2, tmp3
560 */
561.macro at91_mckx_ps_enable
562	ldr	pmc, .pmc_base
563
564	/* There are 4 MCKs we need to handle: MCK1..4 */
565	mov	tmp1, #1
566e_loop:
567	/* Write MCK ID to retrieve the settings */
568	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
569	ldr	tmp2, [pmc, #AT91_PMC_MCR_V2]
570
571	cmp	tmp1, #1
572	streq	tmp2, .saved_mck1
573	cmp	tmp1, #2
574	streq	tmp2, .saved_mck2
575	cmp	tmp1, #3
576	streq	tmp2, .saved_mck3
577	cmp	tmp1, #4
578	streq	tmp2, .saved_mck4
579
580	/* Use CSS=MD_SLOW_CLK and DIV=64. */
581	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK
582	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK
583	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK
584	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64
585	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CMD
586	str	tmp2, [pmc, #AT91_PMC_MCR_V2]
587
588	mov	tmp2, tmp1
589	wait_mckrdy tmp1
590	mov	tmp1, tmp2
591
592	add	tmp1, tmp1, #1
593	cmp	tmp1, #5
594	bne	e_loop
595.endm
596
597/*
598 * at91_mckx_ps_restore: restore MCK1..4 settings
599 *
600 * Side effects: overwrites tmp1, tmp2, tmp3
601 */
602.macro at91_mckx_ps_restore
603	ldr	pmc, .pmc_base
604
605	/* There are 4 MCKs we need to handle: MCK1..4 */
606	mov	tmp1, #1
607	ldr	tmp2, .saved_mck1
608r_loop:
609	cmp	tmp1, #2
610	ldreq	tmp2, .saved_mck2
611	cmp	tmp1, #3
612	ldreq	tmp2, .saved_mck3
613	cmp	tmp1, #4
614	ldreq	tmp2, .saved_mck4
615
616	/* Write MCK ID to retrieve the settings */
617	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
618	ldr	tmp3, [pmc, #AT91_PMC_MCR_V2]
619
620	/* We need to restore CSS and DIV. */
621	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK
622	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK
623	orr	tmp3, tmp3, tmp2
624	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK
625	orr	tmp3, tmp3, tmp1
626	orr	tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
627	str	tmp3, [pmc, #AT91_PMC_MCR_V2]
628
629	mov	tmp2, tmp1
630	wait_mckrdy tmp1
631	mov	tmp1, tmp2
632
633	add	tmp1, tmp1, #1
634	cmp	tmp1, #5
635	bne	r_loop
636.endm
637#endif
638
639SUSPEND_FUNC(at91_ulp_mode)
640#ifdef CFG_SAMA7G5
641	at91_mckx_ps_enable
642#endif
643
644	ldr	pmc, .pmc_base
645	ldr	tmp3, .pm_mode
646
647	/* Save Master clock setting */
648	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
649	str	tmp1, .saved_mckr
650
651	/*
652	 * Set master clock source to:
653	 * - MAINCK if using ULP0 fast variant
654	 * - slow clock, otherwise
655	 */
656	bic	tmp1, tmp1, #AT91_PMC_CSS
657	cmp	tmp3, #AT91_PM_ULP0_FAST
658	bne	save_mck
659	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
660save_mck:
661	str	tmp1, [pmc, #AT91_PMC_MCKR]
662
663	mov	tmp3, #0
664	wait_mckrdy tmp3
665
666	at91_plla_disable
667
668	ldr	tmp3, .pm_mode
669	cmp	tmp3, #AT91_PM_ULP1
670	beq	ulp1_mode
671
672	at91_pm_ulp0_mode
673	b	ulp_exit
674
675ulp1_mode:
676	at91_pm_ulp1_mode
677	b	ulp_exit
678
679ulp_exit:
680	ldr	pmc, .pmc_base
681
682	at91_plla_enable
683
684	/*
685	 * Restore master clock setting
686	 */
687	ldr	tmp2, .saved_mckr
688	str	tmp2, [pmc, #AT91_PMC_MCKR]
689
690	mov	tmp3, #0
691	wait_mckrdy tmp3
692
693#ifdef CFG_SAMA7G5
694	at91_mckx_ps_restore
695#endif
696
697	mov	pc, lr
698SUSPEND_END_FUNC(at91_ulp_mode)
699
700/*
701 * void at91_sramc_self_refresh(unsigned int is_active)
702 *
703 * @input param:
704 *	@r0: 1 - active self-refresh mode
705 *	     0 - exit self-refresh mode
706 * register usage:
707 *	@r2: base address of the sram controller
708 */
709
710SUSPEND_FUNC(at91_sramc_self_refresh)
711	ldr	r2, .sramc_base
712
713	/*
714	 * DDR Memory controller
715	 */
716	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
717	beq	ddrc_exit_sf
718
719	/* LPDDR1 --> force DDR2 mode during self-refresh */
720	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
721	str	r3, .saved_sam9_mdr
722	bic	r3, r3, #~AT91_DDRSDRC_MD
723	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
724	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
725	biceq	r3, r3, #AT91_DDRSDRC_MD
726	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
727	streq	r3, [r2, #AT91_DDRSDRC_MDR]
728
729	/* Active DDRC self-refresh mode */
730	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
731	str	r3, .saved_sam9_lpr
732	bic	r3, r3, #AT91_DDRSDRC_LPCB
733	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
734	str	r3, [r2, #AT91_DDRSDRC_LPR]
735
736	b	exit_sramc_sf
737
738ddrc_exit_sf:
739	/* Restore MDR in case of LPDDR1 */
740	ldr	r3, .saved_sam9_mdr
741	str	r3, [r2, #AT91_DDRSDRC_MDR]
742	/* Restore LPR on AT91 with DDRAM */
743	ldr	r3, .saved_sam9_lpr
744	str	r3, [r2, #AT91_DDRSDRC_LPR]
745
746exit_sramc_sf:
747	mov	pc, lr
748SUSPEND_END_FUNC(at91_sramc_self_refresh)
749
750.pmc_base:
751	.word 0
752.sramc_base:
753	.word 0
754.shdwc:
755	.word 0
756.sfrbu:
757	.word 0
758.pm_mode:
759	.word 0
760.saved_mckr:
761	.word 0
762.saved_pllar:
763	.word 0
764.saved_sam9_lpr:
765	.word 0
766.saved_sam9_mdr:
767	.word 0
768.saved_osc_status:
769	.word 0
770#ifdef CFG_SAMA7G5
771.saved_mck1:
772	.word 0
773.saved_mck2:
774	.word 0
775.saved_mck3:
776	.word 0
777.saved_mck4:
778	.word 0
779#endif
780
781.global at91_pm_suspend_in_sram_sz
782at91_pm_suspend_in_sram_sz:
783	.word .-at91_pm_suspend_in_sram
784
785check_fit_in_sram at91_pm_suspend_in_sram
786