xref: /rk3399_rockchip-uboot/arch/arm/cpu/armv7/sleep.S (revision a059684b230de0815e3ccd6a419dda35c4a0106d)
154925552SJoseph Chen/*
254925552SJoseph Chen * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
354925552SJoseph Chen *
454925552SJoseph Chen * SPDX-License-Identifier:	GPL-2.0+
554925552SJoseph Chen */
654925552SJoseph Chen
754925552SJoseph Chen#include <asm/arm32_macros.S>
854925552SJoseph Chen#include <asm/macro.h>
954925552SJoseph Chen#include <asm-offsets.h>
1054925552SJoseph Chen#include <asm/psci.h>
1154925552SJoseph Chen#include <config.h>
1254925552SJoseph Chen#include <linux/linkage.h>
1354925552SJoseph Chen
1454925552SJoseph Chen	.globl cpu_suspend
1554925552SJoseph Chen	.globl cpu_do_suspend
1654925552SJoseph Chen	.globl cpu_suspend_save
1754925552SJoseph Chen	.globl cpu_resume
1854925552SJoseph Chen	.globl cpu_do_resume
1954925552SJoseph Chen
2054925552SJoseph Chen/*
2154925552SJoseph Chen * int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
2254925552SJoseph Chen * @arg will be passed to fn as argument
2354925552SJoseph Chen * return value: 0 - cpu resumed from suspended state.
2454925552SJoseph Chen *		 -1 - cpu not suspended.
2554925552SJoseph Chen */
2654925552SJoseph ChenENTRY(cpu_suspend)
2754925552SJoseph Chen	push	{r4 - r12, lr}
2854925552SJoseph Chen
2954925552SJoseph Chen	mov	r5, sp
3054925552SJoseph Chen	sub	sp, sp, #PM_CTX_SIZE
3154925552SJoseph Chen	push	{r0, r1}
3254925552SJoseph Chen
33abf4f551SJoseph Chen	/* r9 is gd, save it to __suspend_gd !!! */
34abf4f551SJoseph Chen	adr	r4, __suspend_gd
3554925552SJoseph Chen	str	r9, [r4]
3654925552SJoseph Chen
3754925552SJoseph Chen	mov	r1, r5
3854925552SJoseph Chen	add	r0, sp, #8
3954925552SJoseph Chen	blx	cpu_suspend_save
4054925552SJoseph Chen
4154925552SJoseph Chen	adr	lr, aborted
4254925552SJoseph Chen	/* Jump to arch specific suspend */
4354925552SJoseph Chen	pop	{r0, pc}
4454925552SJoseph Chen
4554925552SJoseph Chenaborted:
4654925552SJoseph Chen	/* cpu not suspended */
4754925552SJoseph Chen	add	sp, sp, #PM_CTX_SIZE
4854925552SJoseph Chen	/* Return -1 to the caller */
4954925552SJoseph Chen	mov	r0, #(-1)
5054925552SJoseph Chen
5154925552SJoseph Chensuspend_return:
5254925552SJoseph Chen	pop	{r4 - r12, pc}
5354925552SJoseph ChenENDPROC(cpu_suspend)
5454925552SJoseph Chen
5554925552SJoseph ChenENTRY(cpu_do_suspend)
5654925552SJoseph Chen	push	{r4 - r11}
5754925552SJoseph Chen
5854925552SJoseph Chen	read_midr r4
5954925552SJoseph Chen	ubfx	r5, r4, #4, #12
60*a059684bSJoseph Chen
6154925552SJoseph Chen	ldr     r4, CORTEX_A7_PART_NUM
6254925552SJoseph Chen	cmp	r5, r4
6354925552SJoseph Chen	beq	a7_suspend
64*a059684bSJoseph Chen
6554925552SJoseph Chen	ldr     r4, CORTEX_A9_PART_NUM
6654925552SJoseph Chen	cmp	r5, r4
6754925552SJoseph Chen	beq	a9_suspend
6854925552SJoseph Chen
69*a059684bSJoseph Chen	b	other_suspend
7054925552SJoseph Chen
7154925552SJoseph Chen	/* A9 needs PCR/DIAG */
7254925552SJoseph Chena9_suspend:
7354925552SJoseph Chen	read_pcr r4
7454925552SJoseph Chen	read_diag r5
7554925552SJoseph Chen	stmia	r0!, {r4 - r5}
7654925552SJoseph Chen
7754925552SJoseph Chena7_suspend:
7854925552SJoseph Chen	read_fcseidr r4
7954925552SJoseph Chen	read_tpidruro r5
8054925552SJoseph Chen	stmia	r0!, {r4 - r5}
8154925552SJoseph Chen
82*a059684bSJoseph Chenother_suspend:
8354925552SJoseph Chen	read_dacr  r4
8454925552SJoseph Chen	read_ttbr0 r5
8554925552SJoseph Chen	read_ttbr1 r6
8654925552SJoseph Chen	read_ttbcr r7
8754925552SJoseph Chen	read_sctlr r8
8854925552SJoseph Chen	read_actlr r9
8954925552SJoseph Chen	read_cpacr r10
9054925552SJoseph Chen	stmia	r0!, {r4 - r10}
9154925552SJoseph Chen
9254925552SJoseph Chen	read_prrr r4
9354925552SJoseph Chen	read_nmrr r5
9454925552SJoseph Chen	read_vbar r6
9554925552SJoseph Chen	mrs r7, CPSR
9654925552SJoseph Chen	stmia	r0, {r4 - r7}
9754925552SJoseph Chen
9854925552SJoseph Chen	pop	{r4 - r11}
9954925552SJoseph Chen	bx	lr
10054925552SJoseph ChenENDPROC(cpu_do_suspend)
10154925552SJoseph Chen
10254925552SJoseph ChenENTRY(cpu_resume)
10354925552SJoseph Chen	/* Disable interrupt */
10454925552SJoseph Chen	cpsid	aif
10554925552SJoseph Chen
10654925552SJoseph Chen	/* Load gd !! */
107abf4f551SJoseph Chen	adr r1, __suspend_gd
10854925552SJoseph Chen	ldr r2, [r1]
10954925552SJoseph Chen
11054925552SJoseph Chen	/* Get pm_ctx */
11154925552SJoseph Chen	add r2, r2, #PM_CTX_PHYS
11254925552SJoseph Chen	ldr r0, [r2]
11354925552SJoseph Chen
11454925552SJoseph Chen	/* Need to use r0!, because cpu_do_resume needs it */
11554925552SJoseph Chen	ldmia	r0!, {sp, pc}
11654925552SJoseph ChenENDPROC(cpu_resume)
11754925552SJoseph Chen
11854925552SJoseph Chen/*
11954925552SJoseph Chen * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
12054925552SJoseph Chen * Restore the registers stored when cpu_do_suspend
12154925552SJoseph Chen * r0 points to the physical base address of the suspend_regs
12254925552SJoseph Chen * field of struct pm_ctx.
12354925552SJoseph Chen */
12454925552SJoseph ChenENTRY(cpu_do_resume)
12554925552SJoseph Chen	read_midr r4
12654925552SJoseph Chen	ubfx	r5, r4, #4, #12
127*a059684bSJoseph Chen
128*a059684bSJoseph Chen	ldr	r4, CORTEX_A9_PART_NUM
129*a059684bSJoseph Chen	cmp	r5, r4
130*a059684bSJoseph Chen	beq	a9_resume
131*a059684bSJoseph Chen
13254925552SJoseph Chen	ldr     r4, CORTEX_A7_PART_NUM
13354925552SJoseph Chen	cmp	r5, r4
13454925552SJoseph Chen	beq	a7_resume
13554925552SJoseph Chen
136*a059684bSJoseph Chen	/* v7 resume */
137*a059684bSJoseph Chen	mov	ip, #0
138*a059684bSJoseph Chen	/* Invalidate icache to PoU */
139*a059684bSJoseph Chen	write_iciallu
140*a059684bSJoseph Chen	/* set reserved context */
141*a059684bSJoseph Chen	write_contextidr ip
142*a059684bSJoseph Chen	b	other_resume
143*a059684bSJoseph Chen
144*a059684bSJoseph Chena9_resume:
14554925552SJoseph Chen	/*
14654925552SJoseph Chen	 * A9 needs PCR/DIAG
14754925552SJoseph Chen	 */
14854925552SJoseph Chen	ldmia   r0!, {r4 - r5}
14954925552SJoseph Chen	write_pcr r4
15054925552SJoseph Chen	write_diag r5
15154925552SJoseph Chen
15254925552SJoseph Chena7_resume:
15354925552SJoseph Chen	/* v7 resume */
15454925552SJoseph Chen	mov	ip, #0
15554925552SJoseph Chen
15654925552SJoseph Chen	/* Invalidate icache to PoU */
15754925552SJoseph Chen	write_iciallu
15854925552SJoseph Chen	/* set reserved context */
15954925552SJoseph Chen	write_contextidr ip
16054925552SJoseph Chen
16154925552SJoseph Chen	ldmia	r0!, {r4 - r5}
16254925552SJoseph Chen	write_fcseidr r4
16354925552SJoseph Chen	write_tpidruro r5
16454925552SJoseph Chen
165*a059684bSJoseph Chenother_resume:
16654925552SJoseph Chen	ldmia	r0!, {r4 - r10}
16754925552SJoseph Chen	/* Invalidate entire TLB */
16854925552SJoseph Chen	write_tlbiall
16954925552SJoseph Chen	write_dacr r4
17054925552SJoseph Chen	write_ttbr0 r5
17154925552SJoseph Chen	write_ttbr1 r6
17254925552SJoseph Chen	write_ttbcr r7
17354925552SJoseph Chen
17454925552SJoseph Chen	ldmia	r0, {r4 - r7}
17554925552SJoseph Chen	write_prrr  r4
17654925552SJoseph Chen	write_nmrr  r5
17754925552SJoseph Chen	write_vbar  r6
17854925552SJoseph Chen
17954925552SJoseph Chen	write_actlr r9
18054925552SJoseph Chen	write_cpacr r10
18154925552SJoseph Chen	write_bpiall
18254925552SJoseph Chen	isb
18354925552SJoseph Chen	dsb
18454925552SJoseph Chen
18554925552SJoseph Chen	/* MMU will be enabled here */
18654925552SJoseph Chen	write_sctlr r8
18754925552SJoseph Chen	isb
18854925552SJoseph Chen
18954925552SJoseph Chen	/* Restore interrupt */
19054925552SJoseph Chen	msr CPSR_c, r7
19154925552SJoseph Chen
19254925552SJoseph Chen	mov	r0, #0
19354925552SJoseph Chen	b	suspend_return
19454925552SJoseph ChenENDPROC(cpu_do_resume)
19554925552SJoseph Chen
19654925552SJoseph Chen.align 4
197abf4f551SJoseph Chen__suspend_gd:
19854925552SJoseph Chen	.word	0x0
19954925552SJoseph ChenCORTEX_A7_PART_NUM:
20054925552SJoseph Chen	.word	0xC07
20154925552SJoseph ChenCORTEX_A9_PART_NUM:
20254925552SJoseph Chen	.word	0xC09
203