xref: /rk3399_rockchip-uboot/arch/arm/cpu/armv7/sleep.S (revision abf4f551161df5ae2d6b87d75deeb1b3ed5cdd4e)
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
33*abf4f551SJoseph Chen	/* r9 is gd, save it to __suspend_gd !!! */
34*abf4f551SJoseph 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
6054925552SJoseph Chen	ldr     r4, CORTEX_A7_PART_NUM
6154925552SJoseph Chen	cmp	r5, r4
6254925552SJoseph Chen	beq	a7_suspend
6354925552SJoseph Chen	ldr     r4, CORTEX_A9_PART_NUM
6454925552SJoseph Chen	cmp	r5, r4
6554925552SJoseph Chen	beq	a9_suspend
6654925552SJoseph Chen
6754925552SJoseph Chen	/* cpu not supported */
6854925552SJoseph Chen	b	.
6954925552SJoseph Chen
7054925552SJoseph Chen	/* A9 needs PCR/DIAG */
7154925552SJoseph Chena9_suspend:
7254925552SJoseph Chen	read_pcr r4
7354925552SJoseph Chen	read_diag r5
7454925552SJoseph Chen	stmia	r0!, {r4 - r5}
7554925552SJoseph Chen
7654925552SJoseph Chena7_suspend:
7754925552SJoseph Chen	read_fcseidr r4
7854925552SJoseph Chen	read_tpidruro r5
7954925552SJoseph Chen	stmia	r0!, {r4 - r5}
8054925552SJoseph Chen
8154925552SJoseph Chen	read_dacr  r4
8254925552SJoseph Chen	read_ttbr0 r5
8354925552SJoseph Chen	read_ttbr1 r6
8454925552SJoseph Chen	read_ttbcr r7
8554925552SJoseph Chen	read_sctlr r8
8654925552SJoseph Chen	read_actlr r9
8754925552SJoseph Chen	read_cpacr r10
8854925552SJoseph Chen	stmia	r0!, {r4 - r10}
8954925552SJoseph Chen
9054925552SJoseph Chen	read_prrr r4
9154925552SJoseph Chen	read_nmrr r5
9254925552SJoseph Chen	read_vbar r6
9354925552SJoseph Chen	mrs r7, CPSR
9454925552SJoseph Chen	stmia	r0, {r4 - r7}
9554925552SJoseph Chen
9654925552SJoseph Chen	pop	{r4 - r11}
9754925552SJoseph Chen	bx	lr
9854925552SJoseph ChenENDPROC(cpu_do_suspend)
9954925552SJoseph Chen
10054925552SJoseph ChenENTRY(cpu_resume)
10154925552SJoseph Chen	/* Disable interrupt */
10254925552SJoseph Chen	cpsid	aif
10354925552SJoseph Chen
10454925552SJoseph Chen	/* Load gd !! */
105*abf4f551SJoseph Chen	adr r1, __suspend_gd
10654925552SJoseph Chen	ldr r2, [r1]
10754925552SJoseph Chen
10854925552SJoseph Chen	/* Get pm_ctx */
10954925552SJoseph Chen	add r2, r2, #PM_CTX_PHYS
11054925552SJoseph Chen	ldr r0, [r2]
11154925552SJoseph Chen
11254925552SJoseph Chen	/* Need to use r0!, because cpu_do_resume needs it */
11354925552SJoseph Chen	ldmia	r0!, {sp, pc}
11454925552SJoseph ChenENDPROC(cpu_resume)
11554925552SJoseph Chen
11654925552SJoseph Chen/*
11754925552SJoseph Chen * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
11854925552SJoseph Chen * Restore the registers stored when cpu_do_suspend
11954925552SJoseph Chen * r0 points to the physical base address of the suspend_regs
12054925552SJoseph Chen * field of struct pm_ctx.
12154925552SJoseph Chen */
12254925552SJoseph ChenENTRY(cpu_do_resume)
12354925552SJoseph Chen	read_midr r4
12454925552SJoseph Chen	ubfx	r5, r4, #4, #12
12554925552SJoseph Chen	ldr     r4, CORTEX_A7_PART_NUM
12654925552SJoseph Chen	cmp	r5, r4
12754925552SJoseph Chen	beq	a7_resume
12854925552SJoseph Chen
12954925552SJoseph Chen	/*
13054925552SJoseph Chen	 * A9 needs PCR/DIAG
13154925552SJoseph Chen	 */
13254925552SJoseph Chen	ldmia   r0!, {r4 - r5}
13354925552SJoseph Chen	write_pcr r4
13454925552SJoseph Chen	write_diag r5
13554925552SJoseph Chen
13654925552SJoseph Chena7_resume:
13754925552SJoseph Chen	/* v7 resume */
13854925552SJoseph Chen	mov	ip, #0
13954925552SJoseph Chen
14054925552SJoseph Chen	/* Invalidate icache to PoU */
14154925552SJoseph Chen	write_iciallu
14254925552SJoseph Chen	/* set reserved context */
14354925552SJoseph Chen	write_contextidr ip
14454925552SJoseph Chen
14554925552SJoseph Chen	ldmia	r0!, {r4 - r5}
14654925552SJoseph Chen	write_fcseidr r4
14754925552SJoseph Chen	write_tpidruro r5
14854925552SJoseph Chen
14954925552SJoseph Chen	ldmia	r0!, {r4 - r10}
15054925552SJoseph Chen	/* Invalidate entire TLB */
15154925552SJoseph Chen	write_tlbiall
15254925552SJoseph Chen	write_dacr r4
15354925552SJoseph Chen	write_ttbr0 r5
15454925552SJoseph Chen	write_ttbr1 r6
15554925552SJoseph Chen	write_ttbcr r7
15654925552SJoseph Chen
15754925552SJoseph Chen	ldmia	r0, {r4 - r7}
15854925552SJoseph Chen	write_prrr  r4
15954925552SJoseph Chen	write_nmrr  r5
16054925552SJoseph Chen	write_vbar  r6
16154925552SJoseph Chen
16254925552SJoseph Chen	write_actlr r9
16354925552SJoseph Chen	write_cpacr r10
16454925552SJoseph Chen	write_bpiall
16554925552SJoseph Chen	isb
16654925552SJoseph Chen	dsb
16754925552SJoseph Chen
16854925552SJoseph Chen	/* MMU will be enabled here */
16954925552SJoseph Chen	write_sctlr r8
17054925552SJoseph Chen	isb
17154925552SJoseph Chen
17254925552SJoseph Chen	/* Restore interrupt */
17354925552SJoseph Chen	msr CPSR_c, r7
17454925552SJoseph Chen
17554925552SJoseph Chen	mov	r0, #0
17654925552SJoseph Chen	b	suspend_return
17754925552SJoseph ChenENDPROC(cpu_do_resume)
17854925552SJoseph Chen
17954925552SJoseph Chen.align 4
180*abf4f551SJoseph Chen__suspend_gd:
18154925552SJoseph Chen	.word	0x0
18254925552SJoseph ChenCORTEX_A7_PART_NUM:
18354925552SJoseph Chen	.word	0xC07
18454925552SJoseph ChenCORTEX_A9_PART_NUM:
18554925552SJoseph Chen	.word	0xC09
186