xref: /optee_os/core/drivers/pm/sam/pm_suspend.S (revision 9ba9163746e3fba86a46ab7e35ac8e5b87ff4b27)
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#ifdef CFG_SAMA7G5
14#include <drivers/sam/sama7-ddr.h>
15#else
16#include <drivers/sam/at91_ddr.h>
17#endif
18#include <generated/pm-defines.h>
19
20#include "at91_pm.h"
21
22#define	SRAMC_SELF_FRESH_ACTIVE		0x01
23#define	SRAMC_SELF_FRESH_EXIT		0x00
24
25pmc	.req	r0
26tmp1	.req	r4
27tmp2	.req	r5
28tmp3	.req	r6
29
30/*
31 * Wait until master clock is ready (after switching master clock source)
32 * @r_mckid:	register holding master clock identifier
33 *
34 * Side effects: overwrites tmp1
35 */
36.macro wait_mckrdy r_mckid
37#ifdef CFG_SAMA7G5
38	cmp	\r_mckid, #0
39	beq	1f
402:	ldr	tmp1, [pmc, #AT91_PMC_SR]
41	tst	tmp1, #AT91_PMC_MCKXRDY
42	beq	2b
43	b	3f
44#endif
451:	ldr	tmp1, [pmc, #AT91_PMC_SR]
46	tst	tmp1, #AT91_PMC_MCKRDY
47	beq	1b
483:
49.endm
50
51/*
52 * Wait until master oscillator has stabilized.
53 */
54.macro wait_moscrdy
551:	ldr	tmp1, [pmc, #AT91_PMC_SR]
56	tst	tmp1, #AT91_PMC_MOSCS
57	beq	1b
58.endm
59
60/*
61 * Wait for main oscillator selection is done
62 */
63.macro wait_moscsels
641:	ldr	tmp1, [pmc, #AT91_PMC_SR]
65	tst	tmp1, #AT91_PMC_MOSCSELS
66	beq	1b
67.endm
68
69/*
70 * Put the processor to enter the idle state
71 */
72.macro at91_cpu_idle
73
74	mov	tmp1, #AT91_PMC_PCK
75	str	tmp1, [pmc, #AT91_PMC_SCDR]
76
77	dsb
78
79	wfi		@ Wait For Interrupt
80
81.endm
82
83.section .text.psci.suspend
84
85.arm
86
87#ifdef CFG_SAMA7G5
88/*
89 * Enable self-refresh
90 *
91 * Side effects: overwrites tmp1, tmp2, tmp3
92 */
93.macro at91_sramc_self_refresh_ena
94	dsb
95
96	ldr	tmp2, .sramc_base
97
98	/* Disable all AXI ports. */
99	ldr	tmp1, [tmp2, #UDDRC_PCTRL_0]
100	bic	tmp1, tmp1, #0x1
101	str	tmp1, [tmp2, #UDDRC_PCTRL_0]
102
103	ldr	tmp1, [tmp2, #UDDRC_PCTRL_1]
104	bic	tmp1, tmp1, #0x1
105	str	tmp1, [tmp2, #UDDRC_PCTRL_1]
106
107	ldr	tmp1, [tmp2, #UDDRC_PCTRL_2]
108	bic	tmp1, tmp1, #0x1
109	str	tmp1, [tmp2, #UDDRC_PCTRL_2]
110
111	ldr	tmp1, [tmp2, #UDDRC_PCTRL_3]
112	bic	tmp1, tmp1, #0x1
113	str	tmp1, [tmp2, #UDDRC_PCTRL_3]
114
115	ldr	tmp1, [tmp2, #UDDRC_PCTRL_4]
116	bic	tmp1, tmp1, #0x1
117	str	tmp1, [tmp2, #UDDRC_PCTRL_4]
118
119sr_ena_1:
120	/* Wait for all ports to disable. */
121	ldr	tmp1, [tmp2, #UDDRC_PSTAT]
122	ldr	tmp3, =UDDRC_PSTAT_ALL_PORTS
123	tst	tmp1, tmp3
124	bne	sr_ena_1
125
126	/* Switch to self-refresh. */
127	ldr	tmp1, [tmp2, #UDDRC_PWRCTL]
128	orr	tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW
129	str	tmp1, [tmp2, #UDDRC_PWRCTL]
130
131sr_ena_2:
132	/* Wait for self-refresh enter. */
133	ldr	tmp1, [tmp2, #UDDRC_STAT]
134	bic	tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
135	cmp	tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
136	bne	sr_ena_2
137
138	ldr	tmp2, .sramc_phy_base
139
140	/* Disable DX DLLs for non-backup modes. */
141	ldr	tmp1, .pm_mode
142	cmp	tmp1, #AT91_PM_BACKUP
143	beq	sr_ena_3
144
145	/* Do not soft reset the AC DLL. */
146	ldr	tmp1, [tmp2, #DDR3PHY_ACDLLCR]
147	bic	tmp1, tmp1, #DDR3PHY_ACDLLCR_DLLSRST
148	str	tmp1, [tmp2, #DDR3PHY_ACDLLCR]
149
150	/* Disable DX DLLs. */
151	ldr	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
152	orr	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
153	str	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
154
155	ldr	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
156	orr	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
157	str	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
158
159sr_ena_3:
160	/* Power down DDR PHY data receivers. */
161	ldr	tmp1, [tmp2, #DDR3PHY_DXCCR]
162	orr	tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
163	str	tmp1, [tmp2, #DDR3PHY_DXCCR]
164
165	/* Power down ADDR/CMD IO. */
166	ldr	tmp1, [tmp2, #DDR3PHY_ACIOCR]
167	orr	tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
168	orr	tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
169	orr	tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
170	str	tmp1, [tmp2, #DDR3PHY_ACIOCR]
171
172	/* Power down ODT. */
173	ldr	tmp1, [tmp2, #DDR3PHY_DSGCR]
174	orr	tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
175	str	tmp1, [tmp2, #DDR3PHY_DSGCR]
176.endm
177
178/*
179 * Disable self-refresh
180 *
181 * Side effects: overwrites tmp1, tmp2
182 */
183.macro at91_sramc_self_refresh_dis
184	ldr	tmp2, .sramc_phy_base
185
186	/* Power up DDR PHY data receivers. */
187	ldr	tmp1, [tmp2, #DDR3PHY_DXCCR]
188	bic	tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
189	str	tmp1, [tmp2, #DDR3PHY_DXCCR]
190
191	/* Power up the output of CK and CS pins. */
192	ldr	tmp1, [tmp2, #DDR3PHY_ACIOCR]
193	bic	tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
194	bic	tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
195	bic	tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
196	str	tmp1, [tmp2, #DDR3PHY_ACIOCR]
197
198	/* Power up ODT. */
199	ldr	tmp1, [tmp2, #DDR3PHY_DSGCR]
200	bic	tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
201	str	tmp1, [tmp2, #DDR3PHY_DSGCR]
202
203	/* Enable DX DLLs. */
204	ldr	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
205	bic	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
206	str	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
207
208	ldr	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
209	bic	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
210	str	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
211
212	ldr	tmp2, .sramc_base
213
214	/* Enable quasi-dynamic programming. */
215	mov	tmp1, #0
216	str	tmp1, [tmp2, #UDDRC_SWCTRL]
217
218	/* De-assert SDRAM initialization. */
219	ldr	tmp1, [tmp2, #UDDRC_DFIMISC]
220	bic	tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
221	str	tmp1, [tmp2, #UDDRC_DFIMISC]
222
223	/* Quasi-dynamic programming done. */
224	mov	tmp1, #UDDRC_SWCTRL_SW_DONE
225	str	tmp1, [tmp2, #UDDRC_SWCTRL]
226
227sr_dis_1:
228	ldr	tmp1, [tmp2, #UDDRC_SWSTAT]
229	tst	tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
230	beq	sr_dis_1
231
232	ldr	tmp2, .sramc_phy_base
233
234	/* DLL soft-reset + DLL lock wait + ITM reset */
235	mov	tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
236			DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
237	str	tmp1, [tmp2, #DDR3PHY_PIR]
238
239sr_dis_4:
240	/* Wait for it. */
241	ldr	tmp1, [tmp2, #DDR3PHY_PGSR]
242	tst	tmp1, #DDR3PHY_PGSR_IDONE
243	beq	sr_dis_4
244
245	ldr	tmp2, .sramc_base
246
247	/* Enable quasi-dynamic programming. */
248	mov	tmp1, #0
249	str	tmp1, [tmp2, #UDDRC_SWCTRL]
250
251	/* Assert PHY init complete enable signal. */
252	ldr	tmp1, [tmp2, #UDDRC_DFIMISC]
253	orr	tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
254	str	tmp1, [tmp2, #UDDRC_DFIMISC]
255
256	/* Programming is done. Set sw_done. */
257	mov	tmp1, #UDDRC_SWCTRL_SW_DONE
258	str	tmp1, [tmp2, #UDDRC_SWCTRL]
259
260sr_dis_5:
261	/* Wait for it. */
262	ldr	tmp1, [tmp2, #UDDRC_SWSTAT]
263	tst	tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
264	beq	sr_dis_5
265
266	/* Trigger self-refresh exit. */
267	ldr	tmp1, [tmp2, #UDDRC_PWRCTL]
268	bic	tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW
269	str	tmp1, [tmp2, #UDDRC_PWRCTL]
270
271sr_dis_6:
272	/* Wait for self-refresh exit done. */
273	ldr	tmp1, [tmp2, #UDDRC_STAT]
274	bic	tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
275	cmp	tmp1, #UDDRC_STAT_OPMODE_NORMAL
276	bne	sr_dis_6
277
278	/* Enable all AXI ports. */
279	ldr	tmp1, [tmp2, #UDDRC_PCTRL_0]
280	orr	tmp1, tmp1, #0x1
281	str	tmp1, [tmp2, #UDDRC_PCTRL_0]
282
283	ldr	tmp1, [tmp2, #UDDRC_PCTRL_1]
284	orr	tmp1, tmp1, #0x1
285	str	tmp1, [tmp2, #UDDRC_PCTRL_1]
286
287	ldr	tmp1, [tmp2, #UDDRC_PCTRL_2]
288	orr	tmp1, tmp1, #0x1
289	str	tmp1, [tmp2, #UDDRC_PCTRL_2]
290
291	ldr	tmp1, [tmp2, #UDDRC_PCTRL_3]
292	orr	tmp1, tmp1, #0x1
293	str	tmp1, [tmp2, #UDDRC_PCTRL_3]
294
295	ldr	tmp1, [tmp2, #UDDRC_PCTRL_4]
296	orr	tmp1, tmp1, #0x1
297	str	tmp1, [tmp2, #UDDRC_PCTRL_4]
298
299	dsb
300.endm
301#endif
302
303#define SUSPEND_FUNC(__name) \
304__name:
305
306#define SUSPEND_END_FUNC(__name) \
307	.size __name, .-__name
308
309.macro check_fit_in_sram since
310	.if (. - \since) > 0x10000
311		.error "Suspend assembly code exceeds dedicated SRAM size"
312	.endif
313.endm
314
315/*
316 * void at91_suspend_sram_fn(struct at91_pm_data*)
317 * @input param:
318 * 	@r0: base address of struct at91_pm_data
319 */
320.align 3
321.global at91_pm_suspend_in_sram
322SUSPEND_FUNC(at91_pm_suspend_in_sram)
323	/* Save registers on stack */
324	stmfd	sp!, {r4 - r12, lr}
325
326	/* Drain write buffer */
327	mov	tmp1, #0
328	mcr	p15, 0, tmp1, c7, c10, 4
329
330	ldr	tmp1, [r0, #PM_DATA_PMC]
331	str	tmp1, .pmc_base
332	ldr	tmp1, [r0, #PM_DATA_RAMC0]
333	str	tmp1, .sramc_base
334	ldr	tmp1, [r0, #PM_DATA_RAMC_PHY]
335	str	tmp1, .sramc_phy_base
336	ldr	tmp1, [r0, #PM_DATA_MODE]
337	str	tmp1, .pm_mode
338	/* Both ldrne below are here to preload their address in the TLB */
339	ldr	tmp1, [r0, #PM_DATA_SHDWC]
340	str	tmp1, .shdwc
341	cmp	tmp1, #0
342	ldrne	tmp2, [tmp1, #0]
343	ldr	tmp1, [r0, #PM_DATA_SFRBU]
344	str	tmp1, .sfrbu
345	cmp	tmp1, #0
346	ldrne	tmp2, [tmp1, #0x10]
347
348	/* Active the self-refresh mode */
349#ifdef CFG_SAMA5D2
350	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
351	bl	at91_sramc_self_refresh
352#endif
353#ifdef CFG_SAMA7G5
354	at91_sramc_self_refresh_ena
355#endif
356
357	ldr	r0, .pm_mode
358	cmp	r0, #AT91_PM_STANDBY
359	beq	standby
360	cmp	r0, #AT91_PM_BACKUP
361	beq	backup_mode
362
363	bl	at91_ulp_mode
364	b	exit_suspend
365
366standby:
367	/* Wait for interrupt */
368	ldr	pmc, .pmc_base
369	at91_cpu_idle
370	b	exit_suspend
371
372backup_mode:
373	bl	at91_backup_mode
374	b	exit_suspend
375
376exit_suspend:
377	/* Exit the self-refresh mode */
378#ifdef CFG_SAMA5D2
379	mov	r0, #SRAMC_SELF_FRESH_EXIT
380	bl	at91_sramc_self_refresh
381#endif
382#ifdef CFG_SAMA7G5
383	at91_sramc_self_refresh_dis
384#endif
385
386	/* Restore registers, and return */
387	ldmfd	sp!, {r4 - r12, pc}
388SUSPEND_END_FUNC(at91_pm_suspend_in_sram)
389
390SUSPEND_FUNC(at91_backup_mode)
391	/* Switch the master clock source to slow clock. */
392	ldr	pmc, .pmc_base
393	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
394	bic	tmp1, tmp1, #AT91_PMC_CSS
395	str	tmp1, [pmc, #AT91_PMC_MCKR]
396
397	mov	tmp3, #0
398	wait_mckrdy tmp3
399
400	/*BUMEN*/
401	ldr	r0, .sfrbu
402	mov	tmp1, #0x1
403	str	tmp1, [r0, #0x10]
404
405	/* Shutdown */
406	ldr	r0, .shdwc
407	mov	tmp1, #0xA5000000
408	add	tmp1, tmp1, #0x1
409#ifdef CFG_SAMA7G5
410	/* LPM Pad Enable: The LPM pad is set high */
411	orr	tmp1, tmp1, #0x200000
412#endif
413	str	tmp1, [r0, #0]
414SUSPEND_END_FUNC(at91_backup_mode)
415
416/*
417 * Set LPM
418 * @ena: 0 - disable LPM
419 *	 1 - enable LPM
420 *
421 * Side effects: overwrites tmp1, tmp3
422 */
423.macro at91_set_lpm ena
424#ifdef CFG_SAMA7G5
425	mov	tmp1, #\ena
426	cmp	tmp1, #1
427	movne	tmp3, #0x400000 /* LPM Pad Disable: The LPM pad is set low */
428	moveq	tmp3, #0x200000 /* LPM Pad Enable: The LPM pad is set high */
429	add	tmp3, #0xA5000000
430	ldr	tmp1, .shdwc
431	cmp	tmp1, #0
432	strne	tmp3, [tmp1]
433#endif
434.endm
435
436.macro at91_pm_ulp0_mode
437	ldr	pmc, .pmc_base
438	ldr	tmp2, .pm_mode
439
440	/* Check if ULP0 fast variant has been requested. */
441	cmp	tmp2, #AT91_PM_ULP0_FAST
442	bne	0f
443
444	/* Set highest prescaler for power saving */
445	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
446	bic	tmp1, tmp1, #AT91_PMC_PRES
447	orr	tmp1, tmp1, #AT91_PMC_PRES_64
448	str	tmp1, [pmc, #AT91_PMC_MCKR]
449
450	mov	tmp3, #0
451	wait_mckrdy tmp3
452	b	1f
453
4540:
455	/* Turn off the crystal oscillator */
456	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
457	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
458	orr	tmp1, tmp1, #AT91_PMC_KEY
459	str	tmp1, [pmc, #AT91_CKGR_MOR]
460
461	/* Save RC oscillator state */
462	ldr	tmp1, [pmc, #AT91_PMC_SR]
463	str	tmp1, .saved_osc_status
464	tst	tmp1, #AT91_PMC_MOSCRCS
465	bne	7f
466
467	/* Turn off RC oscillator */
468	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
469	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
470	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
471	orr	tmp1, tmp1, #AT91_PMC_KEY
472	str	tmp1, [pmc, #AT91_CKGR_MOR]
473
474	/* Wait main RC disabled done */
4752:	ldr	tmp1, [pmc, #AT91_PMC_SR]
476	tst	tmp1, #AT91_PMC_MOSCRCS
477	bne	2b
478
479	/* Enable LPM. */
4807:	at91_set_lpm 1
481
482	/* Wait for interrupt */
4831:	at91_cpu_idle
484
485	/* Check if ULP0 fast variant has been requested. */
486	cmp	tmp2, #AT91_PM_ULP0_FAST
487	bne	8f
488
489	/* Set lowest prescaler for fast resume. */
490	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
491	bic	tmp1, tmp1, #AT91_PMC_PRES
492	str	tmp1, [pmc, #AT91_PMC_MCKR]
493
494	mov	tmp3, #0
495	wait_mckrdy tmp3
496	b	6f
497
4988:	at91_set_lpm 0
499
5005:	/* Restore RC oscillator state */
501	ldr	tmp1, .saved_osc_status
502	tst	tmp1, #AT91_PMC_MOSCRCS
503	beq	4f
504
505	/* Turn on RC oscillator */
506	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
507	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
508	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
509	orr	tmp1, tmp1, #AT91_PMC_KEY
510	str	tmp1, [pmc, #AT91_CKGR_MOR]
511
512	/* Wait main RC stabilization */
5133:	ldr	tmp1, [pmc, #AT91_PMC_SR]
514	tst	tmp1, #AT91_PMC_MOSCRCS
515	beq	3b
516
517	/* Turn on the crystal oscillator */
5184:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
519	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
520	orr	tmp1, tmp1, #AT91_PMC_KEY
521	str	tmp1, [pmc, #AT91_CKGR_MOR]
522
523	wait_moscrdy
5246:
525.endm
526
527/**
528 * Note: This procedure only applies on the platform which uses
529 * the external crystal oscillator as a main clock source.
530 */
531.macro at91_pm_ulp1_mode
532	ldr	pmc, .pmc_base
533
534	/* Save RC oscillator state and check if it is enabled. */
535	ldr	tmp1, [pmc, #AT91_PMC_SR]
536	str	tmp1, .saved_osc_status
537	tst	tmp1, #AT91_PMC_MOSCRCS
538	bne	2f
539
540	/* Enable RC oscillator */
541	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
542	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
543	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
544	orr	tmp1, tmp1, #AT91_PMC_KEY
545	str	tmp1, [pmc, #AT91_CKGR_MOR]
546
547	/* Wait main RC stabilization */
5481:	ldr	tmp1, [pmc, #AT91_PMC_SR]
549	tst	tmp1, #AT91_PMC_MOSCRCS
550	beq	1b
551
552	/* Switch the main clock source to 12-MHz RC oscillator */
5532:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
554	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
555	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
556	orr	tmp1, tmp1, #AT91_PMC_KEY
557	str	tmp1, [pmc, #AT91_CKGR_MOR]
558
559	wait_moscsels
560
561	/* Disable the crystal oscillator */
562	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
563	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
564	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
565	orr	tmp1, tmp1, #AT91_PMC_KEY
566	str	tmp1, [pmc, #AT91_CKGR_MOR]
567
568	/* Switch the master clock source to main clock */
569	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
570	bic	tmp1, tmp1, #AT91_PMC_CSS
571	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
572	str	tmp1, [pmc, #AT91_PMC_MCKR]
573
574	mov	tmp3, #0
575	wait_mckrdy tmp3
576
577	/* Enable LPM */
578	at91_set_lpm 1
579
580	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
581	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
582	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
583	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
584	orr	tmp1, tmp1, #AT91_PMC_KEY
585	str	tmp1, [pmc, #AT91_CKGR_MOR]
586
587	/* Quirk for SAM9X60's PMC */
588	nop
589	nop
590
591	mov	tmp3, #0
592	wait_mckrdy tmp3
593
594	/* Disable LPM. */
595	at91_set_lpm 0
596
597	/* Enable the crystal oscillator */
598	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
599	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
600	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
601	orr	tmp1, tmp1, #AT91_PMC_KEY
602	str	tmp1, [pmc, #AT91_CKGR_MOR]
603
604	wait_moscrdy
605
606	/* Switch the master clock source to slow clock */
607	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
608	bic	tmp1, tmp1, #AT91_PMC_CSS
609	str	tmp1, [pmc, #AT91_PMC_MCKR]
610
611	mov	tmp3, #0
612	wait_mckrdy tmp3
613
614	/* Switch main clock source to crystal oscillator */
615	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
616	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
617	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
618	orr	tmp1, tmp1, #AT91_PMC_KEY
619	str	tmp1, [pmc, #AT91_CKGR_MOR]
620
621	wait_moscsels
622
623	/* Switch the master clock source to main clock */
624	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
625	bic	tmp1, tmp1, #AT91_PMC_CSS
626	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
627	str	tmp1, [pmc, #AT91_PMC_MCKR]
628
629	wait_mckrdy tmp3
630
631	/* Restore RC oscillator state */
632	ldr	tmp1, .saved_osc_status
633	tst	tmp1, #AT91_PMC_MOSCRCS
634	bne	3f
635
636	/* Disable RC oscillator */
637	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
638	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
639	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
640	orr	tmp1, tmp1, #AT91_PMC_KEY
641	str	tmp1, [pmc, #AT91_CKGR_MOR]
642
643	/* Wait RC oscillator disable done */
6444:	ldr	tmp1, [pmc, #AT91_PMC_SR]
645	tst	tmp1, #AT91_PMC_MOSCRCS
646	bne	4b
647
6483:
649.endm
650
651/*
652 * Save PLLA setting and disable it
653 *
654 * Side effects: overwrites tmp1, tmp2
655 */
656.macro at91_plla_disable
657#ifdef CFG_SAMA7G5
658	/* Save PLLA settings */
659	ldr	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
660	bic	tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
661	str	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
662
663	/* save div */
664	mov	tmp1, #0
665	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
666	bic	tmp2, tmp2, #0xffffff00
667	orr	tmp1, tmp1, tmp2
668
669	/* save mul */
670	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL1]
671	bic	tmp2, tmp2, #0xffffff
672	orr	tmp1, tmp1, tmp2
673	str	tmp1, .saved_pllar
674
675	/* step 2 */
676	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
677	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
678	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
679	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
680
681	/* step 3 */
682	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
683	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
684	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
685	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
686
687	/* step 4 */
688	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
689	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
690	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
691	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
692
693	/* step 5 */
694	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
695	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
696	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
697
698	/* step 6 */
699	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
700	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
701	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
702	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
703#else
704	/* Save PLLA setting and disable it */
705	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
706	str	tmp1, .saved_pllar
707
708	/* Disable PLLA. */
709	mov	tmp1, #AT91_PMC_PLLCOUNT
710	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
711	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
712#endif
7132:
714.endm
715
716/*
717 * Enable PLLA with the saved setting
718 *
719 * Side effects: overwrites tmp1, tmp2
720 */
721.macro at91_plla_enable
722#ifdef CFG_SAMA7G5
723	/* step 1 */
724	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
725	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
726	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
727	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
728
729	/* step 2 */
730	ldr	tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
731	str	tmp1, [pmc, #AT91_PMC_PLL_ACR]
732
733	/* step 3 */
734	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
735	ldr	tmp2, .saved_pllar
736	bic	tmp2, tmp2, #0xffffff
737	orr	tmp1, tmp1, tmp2
738	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
739
740	/* step 4 */
741	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
742	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
743	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
744	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
745
746	/* step 5 */
747	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
748	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK
749	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
750	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
751	bic	tmp1, tmp1, #0xff
752	ldr	tmp2, .saved_pllar
753	bic	tmp2, tmp2, #0xffffff00
754	orr	tmp1, tmp1, tmp2
755	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
756
757	/* step 6 */
758	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
759	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
760	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
761	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
762
763	/* step 7 */
7643:	ldr	tmp1, [pmc, #AT91_PMC_PLL_ISR0]
765	tst	tmp1, #0x1
766	beq	3b
767#else
768	ldr	tmp2, .saved_pllar
769
770	/* Restore PLLA setting */
771	str	tmp2, [pmc, #AT91_CKGR_PLLAR]
772
773	/* Enable PLLA. */
774	tst	tmp2, #(AT91_PMC_MUL &  0xff0000)
775	bne	1f
776	tst	tmp2, #(AT91_PMC_MUL & ~0xff0000)
777	beq	2f
778
7791:	ldr	tmp1, [pmc, #AT91_PMC_SR]
780	tst	tmp1, #AT91_PMC_LOCKA
781	beq	1b
7822:
783#endif
784.endm
785
786#ifdef CFG_SAMA7G5
787/*
788 * at91_mckx_ps_enable:	save MCK1..4 settings and switch it to main clock
789 *
790 * Side effects: overwrites tmp1, tmp2, tmp3
791 */
792.macro at91_mckx_ps_enable
793	ldr	pmc, .pmc_base
794
795	/* There are 4 MCKs we need to handle: MCK1..4 */
796	mov	tmp1, #1
797e_loop:
798	/* Write MCK ID to retrieve the settings */
799	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
800	ldr	tmp2, [pmc, #AT91_PMC_MCR_V2]
801
802	cmp	tmp1, #1
803	streq	tmp2, .saved_mck1
804	cmp	tmp1, #2
805	streq	tmp2, .saved_mck2
806	cmp	tmp1, #3
807	streq	tmp2, .saved_mck3
808	cmp	tmp1, #4
809	streq	tmp2, .saved_mck4
810
811	/* Use CSS=MD_SLOW_CLK and DIV=64. */
812	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK
813	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK
814	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK
815	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64
816	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CMD
817	str	tmp2, [pmc, #AT91_PMC_MCR_V2]
818
819	mov	tmp2, tmp1
820	wait_mckrdy tmp1
821	mov	tmp1, tmp2
822
823	add	tmp1, tmp1, #1
824	cmp	tmp1, #5
825	bne	e_loop
826.endm
827
828/*
829 * at91_mckx_ps_restore: restore MCK1..4 settings
830 *
831 * Side effects: overwrites tmp1, tmp2, tmp3
832 */
833.macro at91_mckx_ps_restore
834	ldr	pmc, .pmc_base
835
836	/* There are 4 MCKs we need to handle: MCK1..4 */
837	mov	tmp1, #1
838	ldr	tmp2, .saved_mck1
839r_loop:
840	cmp	tmp1, #2
841	ldreq	tmp2, .saved_mck2
842	cmp	tmp1, #3
843	ldreq	tmp2, .saved_mck3
844	cmp	tmp1, #4
845	ldreq	tmp2, .saved_mck4
846
847	/* Write MCK ID to retrieve the settings */
848	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
849	ldr	tmp3, [pmc, #AT91_PMC_MCR_V2]
850
851	/* We need to restore CSS and DIV. */
852	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK
853	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK
854	orr	tmp3, tmp3, tmp2
855	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK
856	orr	tmp3, tmp3, tmp1
857	orr	tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
858	str	tmp3, [pmc, #AT91_PMC_MCR_V2]
859
860	mov	tmp2, tmp1
861	wait_mckrdy tmp1
862	mov	tmp1, tmp2
863
864	add	tmp1, tmp1, #1
865	cmp	tmp1, #5
866	bne	r_loop
867.endm
868#endif
869
870SUSPEND_FUNC(at91_ulp_mode)
871#ifdef CFG_SAMA7G5
872	at91_mckx_ps_enable
873#endif
874
875	ldr	pmc, .pmc_base
876	ldr	tmp3, .pm_mode
877
878	/* Save Master clock setting */
879	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
880	str	tmp1, .saved_mckr
881
882	/*
883	 * Set master clock source to:
884	 * - MAINCK if using ULP0 fast variant
885	 * - slow clock, otherwise
886	 */
887	bic	tmp1, tmp1, #AT91_PMC_CSS
888	cmp	tmp3, #AT91_PM_ULP0_FAST
889	bne	save_mck
890	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
891save_mck:
892	str	tmp1, [pmc, #AT91_PMC_MCKR]
893
894	mov	tmp3, #0
895	wait_mckrdy tmp3
896
897	at91_plla_disable
898
899	ldr	tmp3, .pm_mode
900	cmp	tmp3, #AT91_PM_ULP1
901	beq	ulp1_mode
902
903	at91_pm_ulp0_mode
904	b	ulp_exit
905
906ulp1_mode:
907	at91_pm_ulp1_mode
908	b	ulp_exit
909
910ulp_exit:
911	ldr	pmc, .pmc_base
912
913	at91_plla_enable
914
915	/*
916	 * Restore master clock setting
917	 */
918	ldr	tmp2, .saved_mckr
919	str	tmp2, [pmc, #AT91_PMC_MCKR]
920
921	mov	tmp3, #0
922	wait_mckrdy tmp3
923
924#ifdef CFG_SAMA7G5
925	at91_mckx_ps_restore
926#endif
927
928	mov	pc, lr
929SUSPEND_END_FUNC(at91_ulp_mode)
930
931#ifdef CFG_SAMA5D2
932/*
933 * void at91_sramc_self_refresh(unsigned int is_active)
934 *
935 * @input param:
936 *	@r0: 1 - active self-refresh mode
937 *	     0 - exit self-refresh mode
938 * register usage:
939 *	@r2: base address of the sram controller
940 */
941
942SUSPEND_FUNC(at91_sramc_self_refresh)
943	ldr	r2, .sramc_base
944
945	/*
946	 * DDR Memory controller
947	 */
948	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
949	beq	ddrc_exit_sf
950
951	/* LPDDR1 --> force DDR2 mode during self-refresh */
952	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
953	str	r3, .saved_sam9_mdr
954	bic	r3, r3, #~AT91_DDRSDRC_MD
955	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
956	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
957	biceq	r3, r3, #AT91_DDRSDRC_MD
958	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
959	streq	r3, [r2, #AT91_DDRSDRC_MDR]
960
961	/* Active DDRC self-refresh mode */
962	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
963	str	r3, .saved_sam9_lpr
964	bic	r3, r3, #AT91_DDRSDRC_LPCB
965	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
966	str	r3, [r2, #AT91_DDRSDRC_LPR]
967
968	b	exit_sramc_sf
969
970ddrc_exit_sf:
971	/* Restore MDR in case of LPDDR1 */
972	ldr	r3, .saved_sam9_mdr
973	str	r3, [r2, #AT91_DDRSDRC_MDR]
974	/* Restore LPR on AT91 with DDRAM */
975	ldr	r3, .saved_sam9_lpr
976	str	r3, [r2, #AT91_DDRSDRC_LPR]
977
978exit_sramc_sf:
979	mov	pc, lr
980SUSPEND_END_FUNC(at91_sramc_self_refresh)
981#endif
982
983.pmc_base:
984	.word 0
985.sramc_base:
986	.word 0
987.sramc_phy_base:
988	.word 0
989.shdwc:
990	.word 0
991.sfrbu:
992	.word 0
993.pm_mode:
994	.word 0
995.saved_mckr:
996	.word 0
997.saved_pllar:
998	.word 0
999.saved_sam9_lpr:
1000	.word 0
1001.saved_sam9_mdr:
1002	.word 0
1003.saved_osc_status:
1004	.word 0
1005#ifdef CFG_SAMA7G5
1006.saved_mck1:
1007	.word 0
1008.saved_mck2:
1009	.word 0
1010.saved_mck3:
1011	.word 0
1012.saved_mck4:
1013	.word 0
1014#endif
1015
1016.global at91_pm_suspend_in_sram_sz
1017at91_pm_suspend_in_sram_sz:
1018	.word .-at91_pm_suspend_in_sram
1019
1020check_fit_in_sram at91_pm_suspend_in_sram
1021