xref: /optee_os/core/drivers/pm/sam/pm_suspend.S (revision 735a1eff7b78a551da285a7a259391237f948f16)
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	str	tmp1, [r0, #0]
179SUSPEND_END_FUNC(at91_backup_mode)
180
181.macro at91_pm_ulp0_mode
182	ldr	pmc, .pmc_base
183	ldr	tmp2, .pm_mode
184
185	/* Check if ULP0 fast variant has been requested. */
186	cmp	tmp2, #AT91_PM_ULP0_FAST
187	bne	0f
188
189	/* Set highest prescaler for power saving */
190	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
191	bic	tmp1, tmp1, #AT91_PMC_PRES
192	orr	tmp1, tmp1, #AT91_PMC_PRES_64
193	str	tmp1, [pmc, #AT91_PMC_MCKR]
194
195	mov	tmp3, #0
196	wait_mckrdy tmp3
197	b	1f
198
1990:
200	/* Turn off the crystal oscillator */
201	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
202	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
203	orr	tmp1, tmp1, #AT91_PMC_KEY
204	str	tmp1, [pmc, #AT91_CKGR_MOR]
205
206	/* Save RC oscillator state */
207	ldr	tmp1, [pmc, #AT91_PMC_SR]
208	str	tmp1, .saved_osc_status
209	tst	tmp1, #AT91_PMC_MOSCRCS
210	bne	1f
211
212	/* Turn off RC oscillator */
213	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
214	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
215	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
216	orr	tmp1, tmp1, #AT91_PMC_KEY
217	str	tmp1, [pmc, #AT91_CKGR_MOR]
218
219	/* Wait main RC disabled done */
2202:	ldr	tmp1, [pmc, #AT91_PMC_SR]
221	tst	tmp1, #AT91_PMC_MOSCRCS
222	bne	2b
223
224	/* Wait for interrupt */
2251:	at91_cpu_idle
226
227	/* Check if ULP0 fast variant has been requested. */
228	cmp	tmp2, #AT91_PM_ULP0_FAST
229	bne	5f
230
231	/* Set lowest prescaler for fast resume. */
232	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
233	bic	tmp1, tmp1, #AT91_PMC_PRES
234	str	tmp1, [pmc, #AT91_PMC_MCKR]
235
236	mov	tmp3, #0
237	wait_mckrdy tmp3
238	b	6f
239
2405:	/* Restore RC oscillator state */
241	ldr	tmp1, .saved_osc_status
242	tst	tmp1, #AT91_PMC_MOSCRCS
243	beq	4f
244
245	/* Turn on RC oscillator */
246	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
247	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
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 main RC stabilization */
2533:	ldr	tmp1, [pmc, #AT91_PMC_SR]
254	tst	tmp1, #AT91_PMC_MOSCRCS
255	beq	3b
256
257	/* Turn on the crystal oscillator */
2584:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
259	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
260	orr	tmp1, tmp1, #AT91_PMC_KEY
261	str	tmp1, [pmc, #AT91_CKGR_MOR]
262
263	wait_moscrdy
2646:
265.endm
266
267/**
268 * Note: This procedure only applies on the platform which uses
269 * the external crystal oscillator as a main clock source.
270 */
271.macro at91_pm_ulp1_mode
272	ldr	pmc, .pmc_base
273
274	/* Save RC oscillator state and check if it is enabled. */
275	ldr	tmp1, [pmc, #AT91_PMC_SR]
276	str	tmp1, .saved_osc_status
277	tst	tmp1, #AT91_PMC_MOSCRCS
278	bne	2f
279
280	/* Enable RC oscillator */
281	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
282	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
283	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
284	orr	tmp1, tmp1, #AT91_PMC_KEY
285	str	tmp1, [pmc, #AT91_CKGR_MOR]
286
287	/* Wait main RC stabilization */
2881:	ldr	tmp1, [pmc, #AT91_PMC_SR]
289	tst	tmp1, #AT91_PMC_MOSCRCS
290	beq	1b
291
292	/* Switch the main clock source to 12-MHz RC oscillator */
2932:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
294	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
295	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
296	orr	tmp1, tmp1, #AT91_PMC_KEY
297	str	tmp1, [pmc, #AT91_CKGR_MOR]
298
299	wait_moscsels
300
301	/* Disable the crystal oscillator */
302	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
303	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
304	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
305	orr	tmp1, tmp1, #AT91_PMC_KEY
306	str	tmp1, [pmc, #AT91_CKGR_MOR]
307
308	/* Switch the master clock source to main clock */
309	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
310	bic	tmp1, tmp1, #AT91_PMC_CSS
311	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
312	str	tmp1, [pmc, #AT91_PMC_MCKR]
313
314	mov	tmp3, #0
315	wait_mckrdy tmp3
316
317	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
318	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
319	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
320	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
321	orr	tmp1, tmp1, #AT91_PMC_KEY
322	str	tmp1, [pmc, #AT91_CKGR_MOR]
323
324	/* Quirk for SAM9X60's PMC */
325	nop
326	nop
327
328	wait_mckrdy tmp3
329
330	/* Enable the crystal oscillator */
331	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
332	orr	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	wait_moscrdy
338
339	/* Switch the master clock source to slow clock */
340	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
341	bic	tmp1, tmp1, #AT91_PMC_CSS
342	str	tmp1, [pmc, #AT91_PMC_MCKR]
343
344	wait_mckrdy tmp3
345
346	/* Switch main clock source to crystal oscillator */
347	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
348	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
349	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
350	orr	tmp1, tmp1, #AT91_PMC_KEY
351	str	tmp1, [pmc, #AT91_CKGR_MOR]
352
353	wait_moscsels
354
355	/* Switch the master clock source to main clock */
356	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
357	bic	tmp1, tmp1, #AT91_PMC_CSS
358	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
359	str	tmp1, [pmc, #AT91_PMC_MCKR]
360
361	wait_mckrdy tmp3
362
363	/* Restore RC oscillator state */
364	ldr	tmp1, .saved_osc_status
365	tst	tmp1, #AT91_PMC_MOSCRCS
366	bne	3f
367
368	/* Disable RC oscillator */
369	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
370	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
371	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
372	orr	tmp1, tmp1, #AT91_PMC_KEY
373	str	tmp1, [pmc, #AT91_CKGR_MOR]
374
375	/* Wait RC oscillator disable done */
3764:	ldr	tmp1, [pmc, #AT91_PMC_SR]
377	tst	tmp1, #AT91_PMC_MOSCRCS
378	bne	4b
379
3803:
381.endm
382
383/*
384 * Save PLLA setting and disable it
385 *
386 * Side effects: overwrites tmp1, tmp2
387 */
388.macro at91_plla_disable
389#ifdef CFG_SAMA7G5
390	/* Save PLLA settings */
391	ldr	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
392	bic	tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
393	str	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
394
395	/* save div */
396	mov	tmp1, #0
397	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
398	bic	tmp2, tmp2, #0xffffff00
399	orr	tmp1, tmp1, tmp2
400
401	/* save mul */
402	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL1]
403	bic	tmp2, tmp2, #0xffffff
404	orr	tmp1, tmp1, tmp2
405	str	tmp1, .saved_pllar
406
407	/* step 2 */
408	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
409	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
410	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
411	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
412
413	/* step 3 */
414	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
415	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
416	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
417	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
418
419	/* step 4 */
420	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
421	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
422	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
423	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
424
425	/* step 5 */
426	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
427	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
428	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
429
430	/* step 6 */
431	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
432	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
433	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
434	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
435#else
436	/* Save PLLA setting and disable it */
437	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
438	str	tmp1, .saved_pllar
439
440	/* Disable PLLA. */
441	mov	tmp1, #AT91_PMC_PLLCOUNT
442	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
443	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
444#endif
4452:
446.endm
447
448/*
449 * Enable PLLA with the saved setting
450 *
451 * Side effects: overwrites tmp1, tmp2
452 */
453.macro at91_plla_enable
454#ifdef CFG_SAMA7G5
455	/* step 1 */
456	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
457	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
458	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
459	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
460
461	/* step 2 */
462	ldr	tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
463	str	tmp1, [pmc, #AT91_PMC_PLL_ACR]
464
465	/* step 3 */
466	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
467	ldr	tmp2, .saved_pllar
468	bic	tmp2, tmp2, #0xffffff
469	orr	tmp1, tmp1, tmp2
470	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
471
472	/* step 4 */
473	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
474	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
475	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
476	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
477
478	/* step 5 */
479	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
480	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK
481	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
482	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
483	bic	tmp1, tmp1, #0xff
484	ldr	tmp2, .saved_pllar
485	bic	tmp2, tmp2, #0xffffff00
486	orr	tmp1, tmp1, tmp2
487	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
488
489	/* step 6 */
490	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
491	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
492	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
493	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
494
495	/* step 7 */
4963:	ldr	tmp1, [pmc, #AT91_PMC_PLL_ISR0]
497	tst	tmp1, #0x1
498	beq	3b
499#else
500	ldr	tmp2, .saved_pllar
501
502	/* Restore PLLA setting */
503	str	tmp2, [pmc, #AT91_CKGR_PLLAR]
504
505	/* Enable PLLA. */
506	tst	tmp2, #(AT91_PMC_MUL &  0xff0000)
507	bne	1f
508	tst	tmp2, #(AT91_PMC_MUL & ~0xff0000)
509	beq	2f
510
5111:	ldr	tmp1, [pmc, #AT91_PMC_SR]
512	tst	tmp1, #AT91_PMC_LOCKA
513	beq	1b
5142:
515#endif
516.endm
517
518#ifdef CFG_SAMA7G5
519/*
520 * at91_mckx_ps_enable:	save MCK1..4 settings and switch it to main clock
521 *
522 * Side effects: overwrites tmp1, tmp2, tmp3
523 */
524.macro at91_mckx_ps_enable
525	ldr	pmc, .pmc_base
526
527	/* There are 4 MCKs we need to handle: MCK1..4 */
528	mov	tmp1, #1
529e_loop:
530	/* Write MCK ID to retrieve the settings */
531	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
532	ldr	tmp2, [pmc, #AT91_PMC_MCR_V2]
533
534	cmp	tmp1, #1
535	streq	tmp2, .saved_mck1
536	cmp	tmp1, #2
537	streq	tmp2, .saved_mck2
538	cmp	tmp1, #3
539	streq	tmp2, .saved_mck3
540	cmp	tmp1, #4
541	streq	tmp2, .saved_mck4
542
543	/* Use CSS=MD_SLOW_CLK and DIV=64. */
544	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK
545	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK
546	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK
547	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64
548	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CMD
549	str	tmp2, [pmc, #AT91_PMC_MCR_V2]
550
551	mov	tmp2, tmp1
552	wait_mckrdy tmp1
553	mov	tmp1, tmp2
554
555	add	tmp1, tmp1, #1
556	cmp	tmp1, #5
557	bne	e_loop
558.endm
559
560/*
561 * at91_mckx_ps_restore: restore MCK1..4 settings
562 *
563 * Side effects: overwrites tmp1, tmp2, tmp3
564 */
565.macro at91_mckx_ps_restore
566	ldr	pmc, .pmc_base
567
568	/* There are 4 MCKs we need to handle: MCK1..4 */
569	mov	tmp1, #1
570	ldr	tmp2, .saved_mck1
571r_loop:
572	cmp	tmp1, #2
573	ldreq	tmp2, .saved_mck2
574	cmp	tmp1, #3
575	ldreq	tmp2, .saved_mck3
576	cmp	tmp1, #4
577	ldreq	tmp2, .saved_mck4
578
579	/* Write MCK ID to retrieve the settings */
580	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
581	ldr	tmp3, [pmc, #AT91_PMC_MCR_V2]
582
583	/* We need to restore CSS and DIV. */
584	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK
585	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK
586	orr	tmp3, tmp3, tmp2
587	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK
588	orr	tmp3, tmp3, tmp1
589	orr	tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
590	str	tmp3, [pmc, #AT91_PMC_MCR_V2]
591
592	mov	tmp2, tmp1
593	wait_mckrdy tmp1
594	mov	tmp1, tmp2
595
596	add	tmp1, tmp1, #1
597	cmp	tmp1, #5
598	bne	r_loop
599.endm
600#endif
601
602SUSPEND_FUNC(at91_ulp_mode)
603#ifdef CFG_SAMA7G5
604	at91_mckx_ps_enable
605#endif
606
607	ldr	pmc, .pmc_base
608	ldr	tmp3, .pm_mode
609
610	/* Save Master clock setting */
611	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
612	str	tmp1, .saved_mckr
613
614	/*
615	 * Set master clock source to:
616	 * - MAINCK if using ULP0 fast variant
617	 * - slow clock, otherwise
618	 */
619	bic	tmp1, tmp1, #AT91_PMC_CSS
620	cmp	tmp3, #AT91_PM_ULP0_FAST
621	bne	save_mck
622	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
623save_mck:
624	str	tmp1, [pmc, #AT91_PMC_MCKR]
625
626	mov	tmp3, #0
627	wait_mckrdy tmp3
628
629	at91_plla_disable
630
631	ldr	tmp3, .pm_mode
632	cmp	tmp3, #AT91_PM_ULP1
633	beq	ulp1_mode
634
635	at91_pm_ulp0_mode
636	b	ulp_exit
637
638ulp1_mode:
639	at91_pm_ulp1_mode
640	b	ulp_exit
641
642ulp_exit:
643	ldr	pmc, .pmc_base
644
645	at91_plla_enable
646
647	/*
648	 * Restore master clock setting
649	 */
650	ldr	tmp2, .saved_mckr
651	str	tmp2, [pmc, #AT91_PMC_MCKR]
652
653	mov	tmp3, #0
654	wait_mckrdy tmp3
655
656#ifdef CFG_SAMA7G5
657	at91_mckx_ps_restore
658#endif
659
660	mov	pc, lr
661SUSPEND_END_FUNC(at91_ulp_mode)
662
663/*
664 * void at91_sramc_self_refresh(unsigned int is_active)
665 *
666 * @input param:
667 *	@r0: 1 - active self-refresh mode
668 *	     0 - exit self-refresh mode
669 * register usage:
670 *	@r2: base address of the sram controller
671 */
672
673SUSPEND_FUNC(at91_sramc_self_refresh)
674	ldr	r2, .sramc_base
675
676	/*
677	 * DDR Memory controller
678	 */
679	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
680	beq	ddrc_exit_sf
681
682	/* LPDDR1 --> force DDR2 mode during self-refresh */
683	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
684	str	r3, .saved_sam9_mdr
685	bic	r3, r3, #~AT91_DDRSDRC_MD
686	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
687	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
688	biceq	r3, r3, #AT91_DDRSDRC_MD
689	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
690	streq	r3, [r2, #AT91_DDRSDRC_MDR]
691
692	/* Active DDRC self-refresh mode */
693	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
694	str	r3, .saved_sam9_lpr
695	bic	r3, r3, #AT91_DDRSDRC_LPCB
696	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
697	str	r3, [r2, #AT91_DDRSDRC_LPR]
698
699	b	exit_sramc_sf
700
701ddrc_exit_sf:
702	/* Restore MDR in case of LPDDR1 */
703	ldr	r3, .saved_sam9_mdr
704	str	r3, [r2, #AT91_DDRSDRC_MDR]
705	/* Restore LPR on AT91 with DDRAM */
706	ldr	r3, .saved_sam9_lpr
707	str	r3, [r2, #AT91_DDRSDRC_LPR]
708
709exit_sramc_sf:
710	mov	pc, lr
711SUSPEND_END_FUNC(at91_sramc_self_refresh)
712
713.pmc_base:
714	.word 0
715.sramc_base:
716	.word 0
717.shdwc:
718	.word 0
719.sfrbu:
720	.word 0
721.pm_mode:
722	.word 0
723.saved_mckr:
724	.word 0
725.saved_pllar:
726	.word 0
727.saved_sam9_lpr:
728	.word 0
729.saved_sam9_mdr:
730	.word 0
731.saved_osc_status:
732	.word 0
733#ifdef CFG_SAMA7G5
734.saved_mck1:
735	.word 0
736.saved_mck2:
737	.word 0
738.saved_mck3:
739	.word 0
740.saved_mck4:
741	.word 0
742#endif
743
744.global at91_pm_suspend_in_sram_sz
745at91_pm_suspend_in_sram_sz:
746	.word .-at91_pm_suspend_in_sram
747
748check_fit_in_sram at91_pm_suspend_in_sram
749