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