xref: /optee_os/core/drivers/pm/sam/pm_suspend.S (revision 9f34db38245c9b3a4e6e7e63eb78a75e23ab2da3)
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	write_tlbiall
331	isb
332
333	/*
334	 * ldrne below are here to preload their address in the TLB as access
335	 * to RAM may be limited while in self-refresh.
336	 */
337	ldr	tmp1, [r0, #PM_DATA_PMC]
338	str	tmp1, .pmc_base
339	cmp	tmp1, #0
340	ldrne	tmp2, [tmp1, #0]
341
342	ldr	tmp1, [r0, #PM_DATA_RAMC0]
343	str	tmp1, .sramc_base
344	cmp	tmp1, #0
345	ldrne	tmp2, [tmp1, #0]
346
347	ldr	tmp1, [r0, #PM_DATA_RAMC_PHY]
348	str	tmp1, .sramc_phy_base
349	cmp	tmp1, #0
350	ldrne	tmp2, [tmp1, #0]
351
352	ldr	tmp1, [r0, #PM_DATA_MODE]
353	str	tmp1, .pm_mode
354	/* Both ldrne below are here to preload their address in the TLB */
355	ldr	tmp1, [r0, #PM_DATA_SHDWC]
356	str	tmp1, .shdwc
357	cmp	tmp1, #0
358	ldrne	tmp2, [tmp1, #0]
359	ldr	tmp1, [r0, #PM_DATA_SFRBU]
360	str	tmp1, .sfrbu
361	cmp	tmp1, #0
362	ldrne	tmp2, [tmp1, #0x10]
363
364	/* Active the self-refresh mode */
365#ifdef CFG_SAMA5D2
366	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
367	bl	at91_sramc_self_refresh
368#endif
369#ifdef CFG_SAMA7G5
370	at91_sramc_self_refresh_ena
371#endif
372
373	ldr	r0, .pm_mode
374	cmp	r0, #AT91_PM_STANDBY
375	beq	standby
376	cmp	r0, #AT91_PM_BACKUP
377	beq	backup_mode
378
379	bl	at91_ulp_mode
380	b	exit_suspend
381
382standby:
383	/* Wait for interrupt */
384	ldr	pmc, .pmc_base
385	at91_cpu_idle
386	b	exit_suspend
387
388backup_mode:
389	bl	at91_backup_mode
390	b	exit_suspend
391
392exit_suspend:
393	/* Exit the self-refresh mode */
394#ifdef CFG_SAMA5D2
395	mov	r0, #SRAMC_SELF_FRESH_EXIT
396	bl	at91_sramc_self_refresh
397#endif
398#ifdef CFG_SAMA7G5
399	at91_sramc_self_refresh_dis
400#endif
401
402	/* Restore registers, and return */
403	ldmfd	sp!, {r4 - r12, pc}
404SUSPEND_END_FUNC(at91_pm_suspend_in_sram)
405
406SUSPEND_FUNC(at91_backup_mode)
407	/* Switch the master clock source to slow clock. */
408	ldr	pmc, .pmc_base
409	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
410	bic	tmp1, tmp1, #AT91_PMC_CSS
411	str	tmp1, [pmc, #AT91_PMC_MCKR]
412
413	mov	tmp3, #0
414	wait_mckrdy tmp3
415
416	/*BUMEN*/
417	ldr	r0, .sfrbu
418	mov	tmp1, #0x1
419	str	tmp1, [r0, #0x10]
420
421	/* Shutdown */
422	ldr	r0, .shdwc
423	mov	tmp1, #0xA5000000
424	add	tmp1, tmp1, #0x1
425#ifdef CFG_SAMA7G5
426	/* LPM Pad Enable: The LPM pad is set high */
427	orr	tmp1, tmp1, #0x200000
428#endif
429	str	tmp1, [r0, #0]
430SUSPEND_END_FUNC(at91_backup_mode)
431
432/*
433 * Set LPM
434 * @ena: 0 - disable LPM
435 *	 1 - enable LPM
436 *
437 * Side effects: overwrites tmp1, tmp3
438 */
439.macro at91_set_lpm ena
440#ifdef CFG_SAMA7G5
441	mov	tmp1, #\ena
442	cmp	tmp1, #1
443	movne	tmp3, #0x400000 /* LPM Pad Disable: The LPM pad is set low */
444	moveq	tmp3, #0x200000 /* LPM Pad Enable: The LPM pad is set high */
445	add	tmp3, #0xA5000000
446	ldr	tmp1, .shdwc
447	cmp	tmp1, #0
448	strne	tmp3, [tmp1]
449#endif
450.endm
451
452.macro at91_pm_ulp0_mode
453	ldr	pmc, .pmc_base
454	ldr	tmp2, .pm_mode
455
456	/* Check if ULP0 fast variant has been requested. */
457	cmp	tmp2, #AT91_PM_ULP0_FAST
458	bne	0f
459
460	/* Set highest prescaler for power saving */
461	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
462	bic	tmp1, tmp1, #AT91_PMC_PRES
463	orr	tmp1, tmp1, #AT91_PMC_PRES_64
464	str	tmp1, [pmc, #AT91_PMC_MCKR]
465
466	mov	tmp3, #0
467	wait_mckrdy tmp3
468	b	1f
469
4700:
471	/* Turn off the crystal oscillator */
472	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
473	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
474	orr	tmp1, tmp1, #AT91_PMC_KEY
475	str	tmp1, [pmc, #AT91_CKGR_MOR]
476
477	/* Save RC oscillator state */
478	ldr	tmp1, [pmc, #AT91_PMC_SR]
479	str	tmp1, .saved_osc_status
480	tst	tmp1, #AT91_PMC_MOSCRCS
481	bne	7f
482
483	/* Turn off RC oscillator */
484	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
485	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
486	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
487	orr	tmp1, tmp1, #AT91_PMC_KEY
488	str	tmp1, [pmc, #AT91_CKGR_MOR]
489
490	/* Wait main RC disabled done */
4912:	ldr	tmp1, [pmc, #AT91_PMC_SR]
492	tst	tmp1, #AT91_PMC_MOSCRCS
493	bne	2b
494
495	/* Enable LPM. */
4967:	at91_set_lpm 1
497
498	/* Wait for interrupt */
4991:	at91_cpu_idle
500
501	/* Check if ULP0 fast variant has been requested. */
502	cmp	tmp2, #AT91_PM_ULP0_FAST
503	bne	8f
504
505	/* Set lowest prescaler for fast resume. */
506	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
507	bic	tmp1, tmp1, #AT91_PMC_PRES
508	str	tmp1, [pmc, #AT91_PMC_MCKR]
509
510	mov	tmp3, #0
511	wait_mckrdy tmp3
512	b	6f
513
5148:	at91_set_lpm 0
515
5165:	/* Restore RC oscillator state */
517	ldr	tmp1, .saved_osc_status
518	tst	tmp1, #AT91_PMC_MOSCRCS
519	beq	4f
520
521	/* Turn on RC oscillator */
522	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
523	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
524	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
525	orr	tmp1, tmp1, #AT91_PMC_KEY
526	str	tmp1, [pmc, #AT91_CKGR_MOR]
527
528	/* Wait main RC stabilization */
5293:	ldr	tmp1, [pmc, #AT91_PMC_SR]
530	tst	tmp1, #AT91_PMC_MOSCRCS
531	beq	3b
532
533	/* Turn on the crystal oscillator */
5344:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
535	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
536	orr	tmp1, tmp1, #AT91_PMC_KEY
537	str	tmp1, [pmc, #AT91_CKGR_MOR]
538
539	wait_moscrdy
5406:
541.endm
542
543/**
544 * Note: This procedure only applies on the platform which uses
545 * the external crystal oscillator as a main clock source.
546 */
547.macro at91_pm_ulp1_mode
548	ldr	pmc, .pmc_base
549
550	/* Save RC oscillator state and check if it is enabled. */
551	ldr	tmp1, [pmc, #AT91_PMC_SR]
552	str	tmp1, .saved_osc_status
553	tst	tmp1, #AT91_PMC_MOSCRCS
554	bne	2f
555
556	/* Enable RC oscillator */
557	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
558	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
559	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
560	orr	tmp1, tmp1, #AT91_PMC_KEY
561	str	tmp1, [pmc, #AT91_CKGR_MOR]
562
563	/* Wait main RC stabilization */
5641:	ldr	tmp1, [pmc, #AT91_PMC_SR]
565	tst	tmp1, #AT91_PMC_MOSCRCS
566	beq	1b
567
568	/* Switch the main clock source to 12-MHz RC oscillator */
5692:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
570	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
571	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
572	orr	tmp1, tmp1, #AT91_PMC_KEY
573	str	tmp1, [pmc, #AT91_CKGR_MOR]
574
575	wait_moscsels
576
577	/* Disable the crystal oscillator */
578	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
579	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
580	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
581	orr	tmp1, tmp1, #AT91_PMC_KEY
582	str	tmp1, [pmc, #AT91_CKGR_MOR]
583
584	/* Switch the master clock source to main clock */
585	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
586	bic	tmp1, tmp1, #AT91_PMC_CSS
587	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
588	str	tmp1, [pmc, #AT91_PMC_MCKR]
589
590	mov	tmp3, #0
591	wait_mckrdy tmp3
592
593	/* Enable LPM */
594	at91_set_lpm 1
595
596	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
597	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
598	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
599	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
600	orr	tmp1, tmp1, #AT91_PMC_KEY
601	str	tmp1, [pmc, #AT91_CKGR_MOR]
602
603	/* Quirk for SAM9X60's PMC */
604	nop
605	nop
606
607	mov	tmp3, #0
608	wait_mckrdy tmp3
609
610	/* Disable LPM. */
611	at91_set_lpm 0
612
613	/* Enable the crystal oscillator */
614	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
615	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
616	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
617	orr	tmp1, tmp1, #AT91_PMC_KEY
618	str	tmp1, [pmc, #AT91_CKGR_MOR]
619
620	wait_moscrdy
621
622	/* Switch the master clock source to slow clock */
623	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
624	bic	tmp1, tmp1, #AT91_PMC_CSS
625	str	tmp1, [pmc, #AT91_PMC_MCKR]
626
627	mov	tmp3, #0
628	wait_mckrdy tmp3
629
630	/* Switch main clock source to crystal oscillator */
631	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
632	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
633	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
634	orr	tmp1, tmp1, #AT91_PMC_KEY
635	str	tmp1, [pmc, #AT91_CKGR_MOR]
636
637	wait_moscsels
638
639	/* Switch the master clock source to main clock */
640	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
641	bic	tmp1, tmp1, #AT91_PMC_CSS
642	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
643	str	tmp1, [pmc, #AT91_PMC_MCKR]
644
645	wait_mckrdy tmp3
646
647	/* Restore RC oscillator state */
648	ldr	tmp1, .saved_osc_status
649	tst	tmp1, #AT91_PMC_MOSCRCS
650	bne	3f
651
652	/* Disable RC oscillator */
653	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
654	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
655	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
656	orr	tmp1, tmp1, #AT91_PMC_KEY
657	str	tmp1, [pmc, #AT91_CKGR_MOR]
658
659	/* Wait RC oscillator disable done */
6604:	ldr	tmp1, [pmc, #AT91_PMC_SR]
661	tst	tmp1, #AT91_PMC_MOSCRCS
662	bne	4b
663
6643:
665.endm
666
667/*
668 * Save PLLA setting and disable it
669 *
670 * Side effects: overwrites tmp1, tmp2
671 */
672.macro at91_plla_disable
673#ifdef CFG_SAMA7G5
674	/* Save PLLA settings */
675	ldr	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
676	bic	tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
677	str	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
678
679	/* save div */
680	mov	tmp1, #0
681	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
682	bic	tmp2, tmp2, #0xffffff00
683	orr	tmp1, tmp1, tmp2
684
685	/* save mul */
686	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL1]
687	bic	tmp2, tmp2, #0xffffff
688	orr	tmp1, tmp1, tmp2
689	str	tmp1, .saved_pllar
690
691	/* step 2 */
692	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
693	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
694	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
695	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
696
697	/* step 3 */
698	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
699	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
700	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
701	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
702
703	/* step 4 */
704	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
705	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
706	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
707	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
708
709	/* step 5 */
710	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
711	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
712	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
713
714	/* step 6 */
715	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
716	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
717	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
718	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
719#else
720	/* Save PLLA setting and disable it */
721	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
722	str	tmp1, .saved_pllar
723
724	/* Disable PLLA. */
725	mov	tmp1, #AT91_PMC_PLLCOUNT
726	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
727	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
728#endif
7292:
730.endm
731
732/*
733 * Enable PLLA with the saved setting
734 *
735 * Side effects: overwrites tmp1, tmp2
736 */
737.macro at91_plla_enable
738#ifdef CFG_SAMA7G5
739	/* step 1 */
740	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
741	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
742	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
743	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
744
745	/* step 2 */
746	ldr	tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
747	str	tmp1, [pmc, #AT91_PMC_PLL_ACR]
748
749	/* step 3 */
750	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
751	ldr	tmp2, .saved_pllar
752	bic	tmp2, tmp2, #0xffffff
753	orr	tmp1, tmp1, tmp2
754	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
755
756	/* step 4 */
757	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
758	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
759	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
760	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
761
762	/* step 5 */
763	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
764	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK
765	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
766	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
767	bic	tmp1, tmp1, #0xff
768	ldr	tmp2, .saved_pllar
769	bic	tmp2, tmp2, #0xffffff00
770	orr	tmp1, tmp1, tmp2
771	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
772
773	/* step 6 */
774	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
775	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
776	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
777	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
778
779	/* step 7 */
7803:	ldr	tmp1, [pmc, #AT91_PMC_PLL_ISR0]
781	tst	tmp1, #0x1
782	beq	3b
783#else
784	ldr	tmp2, .saved_pllar
785
786	/* Restore PLLA setting */
787	str	tmp2, [pmc, #AT91_CKGR_PLLAR]
788
789	/* Enable PLLA. */
790	tst	tmp2, #(AT91_PMC_MUL &  0xff0000)
791	bne	1f
792	tst	tmp2, #(AT91_PMC_MUL & ~0xff0000)
793	beq	2f
794
7951:	ldr	tmp1, [pmc, #AT91_PMC_SR]
796	tst	tmp1, #AT91_PMC_LOCKA
797	beq	1b
7982:
799#endif
800.endm
801
802#ifdef CFG_SAMA7G5
803/*
804 * at91_mckx_ps_enable:	save MCK1..4 settings and switch it to main clock
805 *
806 * Side effects: overwrites tmp1, tmp2, tmp3
807 */
808.macro at91_mckx_ps_enable
809	ldr	pmc, .pmc_base
810
811	/* There are 4 MCKs we need to handle: MCK1..4 */
812	mov	tmp1, #1
813e_loop:
814	/* Write MCK ID to retrieve the settings */
815	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
816	ldr	tmp2, [pmc, #AT91_PMC_MCR_V2]
817
818	cmp	tmp1, #1
819	streq	tmp2, .saved_mck1
820	cmp	tmp1, #2
821	streq	tmp2, .saved_mck2
822	cmp	tmp1, #3
823	streq	tmp2, .saved_mck3
824	cmp	tmp1, #4
825	streq	tmp2, .saved_mck4
826
827	/* Use CSS=MD_SLOW_CLK and DIV=64. */
828	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK
829	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK
830	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK
831	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64
832	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CMD
833	str	tmp2, [pmc, #AT91_PMC_MCR_V2]
834
835	mov	tmp2, tmp1
836	wait_mckrdy tmp1
837	mov	tmp1, tmp2
838
839	add	tmp1, tmp1, #1
840	cmp	tmp1, #5
841	bne	e_loop
842.endm
843
844/*
845 * at91_mckx_ps_restore: restore MCK1..4 settings
846 *
847 * Side effects: overwrites tmp1, tmp2, tmp3
848 */
849.macro at91_mckx_ps_restore
850	ldr	pmc, .pmc_base
851
852	/* There are 4 MCKs we need to handle: MCK1..4 */
853	mov	tmp1, #1
854	ldr	tmp2, .saved_mck1
855r_loop:
856	cmp	tmp1, #2
857	ldreq	tmp2, .saved_mck2
858	cmp	tmp1, #3
859	ldreq	tmp2, .saved_mck3
860	cmp	tmp1, #4
861	ldreq	tmp2, .saved_mck4
862
863	/* Write MCK ID to retrieve the settings */
864	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
865	ldr	tmp3, [pmc, #AT91_PMC_MCR_V2]
866
867	/* We need to restore CSS and DIV. */
868	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK
869	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK
870	orr	tmp3, tmp3, tmp2
871	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK
872	orr	tmp3, tmp3, tmp1
873	orr	tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
874	str	tmp3, [pmc, #AT91_PMC_MCR_V2]
875
876	mov	tmp2, tmp1
877	wait_mckrdy tmp1
878	mov	tmp1, tmp2
879
880	add	tmp1, tmp1, #1
881	cmp	tmp1, #5
882	bne	r_loop
883.endm
884#endif
885
886SUSPEND_FUNC(at91_ulp_mode)
887#ifdef CFG_SAMA7G5
888	at91_mckx_ps_enable
889#endif
890
891	ldr	pmc, .pmc_base
892	ldr	tmp3, .pm_mode
893
894	/* Save Master clock setting */
895	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
896	str	tmp1, .saved_mckr
897
898	/*
899	 * Set master clock source to:
900	 * - MAINCK if using ULP0 fast variant
901	 * - slow clock, otherwise
902	 */
903	bic	tmp1, tmp1, #AT91_PMC_CSS
904	cmp	tmp3, #AT91_PM_ULP0_FAST
905	bne	save_mck
906	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
907save_mck:
908	str	tmp1, [pmc, #AT91_PMC_MCKR]
909
910	mov	tmp3, #0
911	wait_mckrdy tmp3
912
913	at91_plla_disable
914
915	ldr	tmp3, .pm_mode
916	cmp	tmp3, #AT91_PM_ULP1
917	beq	ulp1_mode
918
919	at91_pm_ulp0_mode
920	b	ulp_exit
921
922ulp1_mode:
923	at91_pm_ulp1_mode
924	b	ulp_exit
925
926ulp_exit:
927	ldr	pmc, .pmc_base
928
929	at91_plla_enable
930
931	/*
932	 * Restore master clock setting
933	 */
934	ldr	tmp2, .saved_mckr
935	str	tmp2, [pmc, #AT91_PMC_MCKR]
936
937	mov	tmp3, #0
938	wait_mckrdy tmp3
939
940#ifdef CFG_SAMA7G5
941	at91_mckx_ps_restore
942#endif
943
944	mov	pc, lr
945SUSPEND_END_FUNC(at91_ulp_mode)
946
947#ifdef CFG_SAMA5D2
948/*
949 * void at91_sramc_self_refresh(unsigned int is_active)
950 *
951 * @input param:
952 *	@r0: 1 - active self-refresh mode
953 *	     0 - exit self-refresh mode
954 * register usage:
955 *	@r2: base address of the sram controller
956 */
957
958SUSPEND_FUNC(at91_sramc_self_refresh)
959	ldr	r2, .sramc_base
960
961	/*
962	 * DDR Memory controller
963	 */
964	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
965	beq	ddrc_exit_sf
966
967	/* LPDDR1 --> force DDR2 mode during self-refresh */
968	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
969	str	r3, .saved_sam9_mdr
970	bic	r3, r3, #~AT91_DDRSDRC_MD
971	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
972	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
973	biceq	r3, r3, #AT91_DDRSDRC_MD
974	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
975	streq	r3, [r2, #AT91_DDRSDRC_MDR]
976
977	/* Active DDRC self-refresh mode */
978	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
979	str	r3, .saved_sam9_lpr
980	bic	r3, r3, #AT91_DDRSDRC_LPCB
981	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
982	str	r3, [r2, #AT91_DDRSDRC_LPR]
983
984	b	exit_sramc_sf
985
986ddrc_exit_sf:
987	/* Restore MDR in case of LPDDR1 */
988	ldr	r3, .saved_sam9_mdr
989	str	r3, [r2, #AT91_DDRSDRC_MDR]
990	/* Restore LPR on AT91 with DDRAM */
991	ldr	r3, .saved_sam9_lpr
992	str	r3, [r2, #AT91_DDRSDRC_LPR]
993
994exit_sramc_sf:
995	mov	pc, lr
996SUSPEND_END_FUNC(at91_sramc_self_refresh)
997#endif
998
999.pmc_base:
1000	.word 0
1001.sramc_base:
1002	.word 0
1003.sramc_phy_base:
1004	.word 0
1005.shdwc:
1006	.word 0
1007.sfrbu:
1008	.word 0
1009.pm_mode:
1010	.word 0
1011.saved_mckr:
1012	.word 0
1013.saved_pllar:
1014	.word 0
1015.saved_sam9_lpr:
1016	.word 0
1017.saved_sam9_mdr:
1018	.word 0
1019.saved_osc_status:
1020	.word 0
1021#ifdef CFG_SAMA7G5
1022.saved_mck1:
1023	.word 0
1024.saved_mck2:
1025	.word 0
1026.saved_mck3:
1027	.word 0
1028.saved_mck4:
1029	.word 0
1030#endif
1031
1032.global at91_pm_suspend_in_sram_sz
1033at91_pm_suspend_in_sram_sz:
1034	.word .-at91_pm_suspend_in_sram
1035
1036check_fit_in_sram at91_pm_suspend_in_sram
1037