xref: /optee_os/core/drivers/pm/sam/pm_suspend.S (revision c6c416f1bf4617feef23d592155ba7de69bceea9)
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
2/*
3 * Copyright (c) 2021, Microchip
4 */
5
6#include <arm.h>
7#include <arm32_macros.S>
8#include <asm.S>
9#include <at91_pmc.h>
10#include <drivers/sam/at91_ddr.h>
11#include <generated/pm-defines.h>
12
13#include "at91_pm.h"
14
15#define	SRAMC_SELF_FRESH_ACTIVE		0x01
16#define	SRAMC_SELF_FRESH_EXIT		0x00
17
18pmc	.req	r0
19tmp1	.req	r4
20tmp2	.req	r5
21tmp3	.req	r6
22
23/*
24 * Wait until master clock is ready (after switching master clock source)
25 */
26.macro wait_mckrdy
271:	ldr	tmp1, [pmc, #AT91_PMC_SR]
28	tst	tmp1, #AT91_PMC_MCKRDY
29	beq	1b
30.endm
31
32/*
33 * Wait until master oscillator has stabilized.
34 */
35.macro wait_moscrdy
361:	ldr	tmp1, [pmc, #AT91_PMC_SR]
37	tst	tmp1, #AT91_PMC_MOSCS
38	beq	1b
39.endm
40
41/*
42 * Wait for main oscillator selection is done
43 */
44.macro wait_moscsels
451:	ldr	tmp1, [pmc, #AT91_PMC_SR]
46	tst	tmp1, #AT91_PMC_MOSCSELS
47	beq	1b
48.endm
49
50/*
51 * Put the processor to enter the idle state
52 */
53.macro at91_cpu_idle
54
55	mov	tmp1, #AT91_PMC_PCK
56	str	tmp1, [pmc, #AT91_PMC_SCDR]
57
58	dsb
59
60	wfi		@ Wait For Interrupt
61
62.endm
63
64.section .text.psci.suspend
65
66.arm
67
68
69#define SUSPEND_FUNC(__name) \
70__name:
71
72#define SUSPEND_END_FUNC(__name) \
73	.size __name, .-__name
74
75.macro check_fit_in_sram since
76	.if (. - \since) > 0x10000
77		.error "Suspend assembly code exceeds dedicated SRAM size"
78	.endif
79.endm
80
81/*
82 * void at91_suspend_sram_fn(struct at91_pm_data*)
83 * @input param:
84 * 	@r0: base address of struct at91_pm_data
85 */
86.align 3
87.global at91_pm_suspend_in_sram
88SUSPEND_FUNC(at91_pm_suspend_in_sram)
89	/* Save registers on stack */
90	stmfd	sp!, {r4 - r12, lr}
91
92	/* Drain write buffer */
93	mov	tmp1, #0
94	mcr	p15, 0, tmp1, c7, c10, 4
95
96	ldr	tmp1, [r0, #PM_DATA_PMC]
97	str	tmp1, .pmc_base
98	ldr	tmp1, [r0, #PM_DATA_RAMC0]
99	str	tmp1, .sramc_base
100	ldr	tmp1, [r0, #PM_DATA_MODE]
101	str	tmp1, .pm_mode
102	/* Both ldrne below are here to preload their address in the TLB */
103	ldr	tmp1, [r0, #PM_DATA_SHDWC]
104	str	tmp1, .shdwc
105	cmp	tmp1, #0
106	ldrne	tmp2, [tmp1, #0]
107	ldr	tmp1, [r0, #PM_DATA_SFRBU]
108	str	tmp1, .sfrbu
109	cmp	tmp1, #0
110	ldrne	tmp2, [tmp1, #0x10]
111
112	/* Active the self-refresh mode */
113	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
114	bl	at91_sramc_self_refresh
115
116	ldr	r0, .pm_mode
117	cmp	r0, #AT91_PM_STANDBY
118	beq	standby
119	cmp	r0, #AT91_PM_BACKUP
120	beq	backup_mode
121
122	bl	at91_ulp_mode
123	b	exit_suspend
124
125standby:
126	/* Wait for interrupt */
127	ldr	pmc, .pmc_base
128	at91_cpu_idle
129	b	exit_suspend
130
131backup_mode:
132	bl	at91_backup_mode
133	b	exit_suspend
134
135exit_suspend:
136	/* Exit the self-refresh mode */
137	mov	r0, #SRAMC_SELF_FRESH_EXIT
138	bl	at91_sramc_self_refresh
139
140	/* Restore registers, and return */
141	ldmfd	sp!, {r4 - r12, pc}
142SUSPEND_END_FUNC(at91_pm_suspend_in_sram)
143
144SUSPEND_FUNC(at91_backup_mode)
145	/* Switch the master clock source to slow clock. */
146	ldr	pmc, .pmc_base
147	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
148	bic	tmp1, tmp1, #AT91_PMC_CSS
149	str	tmp1, [pmc, #AT91_PMC_MCKR]
150
151	wait_mckrdy
152
153	/*BUMEN*/
154	ldr	r0, .sfrbu
155	mov	tmp1, #0x1
156	str	tmp1, [r0, #0x10]
157
158	/* Shutdown */
159	ldr	r0, .shdwc
160	mov	tmp1, #0xA5000000
161	add	tmp1, tmp1, #0x1
162	str	tmp1, [r0, #0]
163SUSPEND_END_FUNC(at91_backup_mode)
164
165.macro at91_pm_ulp0_mode
166	ldr	pmc, .pmc_base
167	ldr	tmp2, .pm_mode
168
169	/* Check if ULP0 fast variant has been requested. */
170	cmp	tmp2, #AT91_PM_ULP0_FAST
171	bne	0f
172
173	/* Set highest prescaler for power saving */
174	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
175	bic	tmp1, tmp1, #AT91_PMC_PRES
176	orr	tmp1, tmp1, #AT91_PMC_PRES_64
177	str	tmp1, [pmc, #AT91_PMC_MCKR]
178	wait_mckrdy
179	b	1f
180
1810:
182	/* Turn off the crystal oscillator */
183	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
184	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
185	orr	tmp1, tmp1, #AT91_PMC_KEY
186	str	tmp1, [pmc, #AT91_CKGR_MOR]
187
188	/* Save RC oscillator state */
189	ldr	tmp1, [pmc, #AT91_PMC_SR]
190	str	tmp1, .saved_osc_status
191	tst	tmp1, #AT91_PMC_MOSCRCS
192	bne	1f
193
194	/* Turn off RC oscillator */
195	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
196	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
197	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
198	orr	tmp1, tmp1, #AT91_PMC_KEY
199	str	tmp1, [pmc, #AT91_CKGR_MOR]
200
201	/* Wait main RC disabled done */
2022:	ldr	tmp1, [pmc, #AT91_PMC_SR]
203	tst	tmp1, #AT91_PMC_MOSCRCS
204	bne	2b
205
206	/* Wait for interrupt */
2071:	at91_cpu_idle
208
209	/* Check if ULP0 fast variant has been requested. */
210	cmp	tmp2, #AT91_PM_ULP0_FAST
211	bne	5f
212
213	/* Set lowest prescaler for fast resume. */
214	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
215	bic	tmp1, tmp1, #AT91_PMC_PRES
216	str	tmp1, [pmc, #AT91_PMC_MCKR]
217	wait_mckrdy
218	b	6f
219
2205:	/* Restore RC oscillator state */
221	ldr	tmp1, .saved_osc_status
222	tst	tmp1, #AT91_PMC_MOSCRCS
223	beq	4f
224
225	/* Turn on RC oscillator */
226	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
227	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
228	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
229	orr	tmp1, tmp1, #AT91_PMC_KEY
230	str	tmp1, [pmc, #AT91_CKGR_MOR]
231
232	/* Wait main RC stabilization */
2333:	ldr	tmp1, [pmc, #AT91_PMC_SR]
234	tst	tmp1, #AT91_PMC_MOSCRCS
235	beq	3b
236
237	/* Turn on the crystal oscillator */
2384:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
239	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
240	orr	tmp1, tmp1, #AT91_PMC_KEY
241	str	tmp1, [pmc, #AT91_CKGR_MOR]
242
243	wait_moscrdy
2446:
245.endm
246
247/**
248 * Note: This procedure only applies on the platform which uses
249 * the external crystal oscillator as a main clock source.
250 */
251.macro at91_pm_ulp1_mode
252	ldr	pmc, .pmc_base
253
254	/* Save RC oscillator state and check if it is enabled. */
255	ldr	tmp1, [pmc, #AT91_PMC_SR]
256	str	tmp1, .saved_osc_status
257	tst	tmp1, #AT91_PMC_MOSCRCS
258	bne	2f
259
260	/* Enable RC oscillator */
261	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
262	orr	tmp1, tmp1, #AT91_PMC_MOSCRCEN
263	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
264	orr	tmp1, tmp1, #AT91_PMC_KEY
265	str	tmp1, [pmc, #AT91_CKGR_MOR]
266
267	/* Wait main RC stabilization */
2681:	ldr	tmp1, [pmc, #AT91_PMC_SR]
269	tst	tmp1, #AT91_PMC_MOSCRCS
270	beq	1b
271
272	/* Switch the main clock source to 12-MHz RC oscillator */
2732:	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
274	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
275	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
276	orr	tmp1, tmp1, #AT91_PMC_KEY
277	str	tmp1, [pmc, #AT91_CKGR_MOR]
278
279	wait_moscsels
280
281	/* Disable the crystal oscillator */
282	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
283	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
284	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
285	orr	tmp1, tmp1, #AT91_PMC_KEY
286	str	tmp1, [pmc, #AT91_CKGR_MOR]
287
288	/* Switch the master clock source to main clock */
289	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
290	bic	tmp1, tmp1, #AT91_PMC_CSS
291	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
292	str	tmp1, [pmc, #AT91_PMC_MCKR]
293
294	wait_mckrdy
295
296	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
297	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
298	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
299	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
300	orr	tmp1, tmp1, #AT91_PMC_KEY
301	str	tmp1, [pmc, #AT91_CKGR_MOR]
302
303	/* Quirk for SAM9X60's PMC */
304	nop
305	nop
306
307	wait_mckrdy
308
309	/* Enable the crystal oscillator */
310	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
311	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
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_moscrdy
317
318	/* Switch the master clock source to slow clock */
319	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
320	bic	tmp1, tmp1, #AT91_PMC_CSS
321	str	tmp1, [pmc, #AT91_PMC_MCKR]
322
323	wait_mckrdy
324
325	/* Switch main clock source to crystal oscillator */
326	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
327	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
328	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
329	orr	tmp1, tmp1, #AT91_PMC_KEY
330	str	tmp1, [pmc, #AT91_CKGR_MOR]
331
332	wait_moscsels
333
334	/* Switch the master clock source to main clock */
335	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
336	bic	tmp1, tmp1, #AT91_PMC_CSS
337	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
338	str	tmp1, [pmc, #AT91_PMC_MCKR]
339
340	wait_mckrdy
341
342	/* Restore RC oscillator state */
343	ldr	tmp1, .saved_osc_status
344	tst	tmp1, #AT91_PMC_MOSCRCS
345	bne	3f
346
347	/* Disable RC oscillator */
348	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
349	bic	tmp1, tmp1, #AT91_PMC_MOSCRCEN
350	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
351	orr	tmp1, tmp1, #AT91_PMC_KEY
352	str	tmp1, [pmc, #AT91_CKGR_MOR]
353
354	/* Wait RC oscillator disable done */
3554:	ldr	tmp1, [pmc, #AT91_PMC_SR]
356	tst	tmp1, #AT91_PMC_MOSCRCS
357	bne	4b
358
3593:
360.endm
361
362.macro at91_plla_disable
363	/* Save PLLA setting and disable it */
364	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
365	str	tmp1, .saved_pllar
366
367	/* Disable PLLA. */
368	mov	tmp1, #AT91_PMC_PLLCOUNT
369	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
370	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
3712:
372.endm
373
374.macro at91_plla_enable
375	ldr	tmp2, .saved_pllar
376
377	/* Restore PLLA setting */
378	str	tmp2, [pmc, #AT91_CKGR_PLLAR]
379
380	/* Enable PLLA. */
381	tst	tmp2, #(AT91_PMC_MUL &  0xff0000)
382	bne	1f
383	tst	tmp2, #(AT91_PMC_MUL & ~0xff0000)
384	beq	2f
385
3861:	ldr	tmp1, [pmc, #AT91_PMC_SR]
387	tst	tmp1, #AT91_PMC_LOCKA
388	beq	1b
3892:
390.endm
391
392SUSPEND_FUNC(at91_ulp_mode)
393	ldr	pmc, .pmc_base
394	ldr	tmp3, .pm_mode
395
396	/* Save Master clock setting */
397	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
398	str	tmp1, .saved_mckr
399
400	/*
401	 * Set master clock source to:
402	 * - MAINCK if using ULP0 fast variant
403	 * - slow clock, otherwise
404	 */
405	bic	tmp1, tmp1, #AT91_PMC_CSS
406	cmp	tmp3, #AT91_PM_ULP0_FAST
407	bne	save_mck
408	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
409save_mck:
410	str	tmp1, [pmc, #AT91_PMC_MCKR]
411
412	wait_mckrdy
413
414	at91_plla_disable
415
416	cmp	tmp3, #AT91_PM_ULP1
417	beq	ulp1_mode
418
419	at91_pm_ulp0_mode
420	b	ulp_exit
421
422ulp1_mode:
423	at91_pm_ulp1_mode
424	b	ulp_exit
425
426ulp_exit:
427	ldr	pmc, .pmc_base
428
429	at91_plla_enable
430
431	/*
432	 * Restore master clock setting
433	 */
434	ldr	tmp2, .saved_mckr
435	str	tmp2, [pmc, #AT91_PMC_MCKR]
436
437	wait_mckrdy
438
439	mov	pc, lr
440SUSPEND_END_FUNC(at91_ulp_mode)
441
442/*
443 * void at91_sramc_self_refresh(unsigned int is_active)
444 *
445 * @input param:
446 *	@r0: 1 - active self-refresh mode
447 *	     0 - exit self-refresh mode
448 * register usage:
449 *	@r2: base address of the sram controller
450 */
451
452SUSPEND_FUNC(at91_sramc_self_refresh)
453	ldr	r2, .sramc_base
454
455	/*
456	 * DDR Memory controller
457	 */
458	tst	r0, #SRAMC_SELF_FRESH_ACTIVE
459	beq	ddrc_exit_sf
460
461	/* LPDDR1 --> force DDR2 mode during self-refresh */
462	ldr	r3, [r2, #AT91_DDRSDRC_MDR]
463	str	r3, .saved_sam9_mdr
464	bic	r3, r3, #~AT91_DDRSDRC_MD
465	cmp	r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
466	ldreq	r3, [r2, #AT91_DDRSDRC_MDR]
467	biceq	r3, r3, #AT91_DDRSDRC_MD
468	orreq	r3, r3, #AT91_DDRSDRC_MD_DDR2
469	streq	r3, [r2, #AT91_DDRSDRC_MDR]
470
471	/* Active DDRC self-refresh mode */
472	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
473	str	r3, .saved_sam9_lpr
474	bic	r3, r3, #AT91_DDRSDRC_LPCB
475	orr	r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
476	str	r3, [r2, #AT91_DDRSDRC_LPR]
477
478	b	exit_sramc_sf
479
480ddrc_exit_sf:
481	/* Restore MDR in case of LPDDR1 */
482	ldr	r3, .saved_sam9_mdr
483	str	r3, [r2, #AT91_DDRSDRC_MDR]
484	/* Restore LPR on AT91 with DDRAM */
485	ldr	r3, .saved_sam9_lpr
486	str	r3, [r2, #AT91_DDRSDRC_LPR]
487
488exit_sramc_sf:
489	mov	pc, lr
490SUSPEND_END_FUNC(at91_sramc_self_refresh)
491
492.pmc_base:
493	.word 0
494.sramc_base:
495	.word 0
496.shdwc:
497	.word 0
498.sfrbu:
499	.word 0
500.pm_mode:
501	.word 0
502.saved_mckr:
503	.word 0
504.saved_pllar:
505	.word 0
506.saved_sam9_lpr:
507	.word 0
508.saved_sam9_mdr:
509	.word 0
510.saved_osc_status:
511	.word 0
512
513.global at91_pm_suspend_in_sram_sz
514at91_pm_suspend_in_sram_sz:
515	.word .-at91_pm_suspend_in_sram
516
517check_fit_in_sram at91_pm_suspend_in_sram
518