1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Sleep helper for Loongson-3 sleep mode.
8  *
9  *  Copyright (C) 2020 Loongson Technology Co., Ltd.
10  *  Author: Huacai Chen <chenhuacai@loongson.cn>
11  */
12 
13 #include <asm/asm.h>
14 #include <asm/asmmacro.h>
15 #include <asm/loongarchregs.h>
16 #include <asm/stackframe.h>
17 #include <asm/addrspace.h>
18 
19 /* preparatory stuff */
20 .macro	SETUP_SLEEP
21 	addi.d		sp, sp, -PT_SIZE
22 	st.d		$r1, sp, PT_R1
23 	st.d		$r2, sp, PT_R2
24 	st.d		$r3, sp, PT_R3
25 	st.d		$r4, sp, PT_R4
26 	st.d		$r21, sp, PT_R21
27 	st.d		$r22, sp, PT_R22
28 	st.d		$r23, sp, PT_R23
29 	st.d		$r24, sp, PT_R24
30 	st.d		$r25, sp, PT_R25
31 	st.d		$r26, sp, PT_R26
32 	st.d		$r27, sp, PT_R27
33 	st.d		$r28, sp, PT_R28
34 	st.d		$r29, sp, PT_R29
35 	st.d		$r30, sp, PT_R30
36 	st.d		$r31, sp, PT_R31
37 
38 	la.pcrel	t0, acpi_saved_sp
39 	st.d		sp, t0, 0
40 .endm
41 
42 .macro SETUP_WAKEUP
43 	ld.d		$r1, sp, PT_R1
44 	ld.d		$r2, sp, PT_R2
45 	ld.d		$r3, sp, PT_R3
46 	ld.d		$r4, sp, PT_R4
47 	ld.d		$r21, sp, PT_R21
48 	ld.d		$r22, sp, PT_R22
49 	ld.d		$r23, sp, PT_R23
50 	ld.d		$r24, sp, PT_R24
51 	ld.d		$r25, sp, PT_R25
52 	ld.d		$r26, sp, PT_R26
53 	ld.d		$r27, sp, PT_R27
54 	ld.d		$r28, sp, PT_R28
55 	ld.d		$r29, sp, PT_R29
56 	ld.d		$r30, sp, PT_R30
57 	ld.d		$r31, sp, PT_R31
58 .endm
59 
60 	.text
61 	.align 12
62 
63 /* Sleep/wakeup code for Loongson-3 */
64 SYM_FUNC_START(loongarch_suspend_enter)
65 	SETUP_SLEEP
66 	bl		__flush_cache_all
67 
68 	/* Pass RA and SP to BIOS */
69 	addi.d		a1, sp, 0
70 	la.pcrel	a0, loongarch_wakeup_start
71 	la.pcrel	t0, loongarch_suspend_addr
72 	ld.d		t0, t0, 0
73 	jirl		a0, t0, 0 /* Call BIOS's STR sleep routine */
74 
75 	/*
76 	 * This is where we return upon wakeup.
77 	 * Reload all of the registers and return.
78 	 */
79 SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
80 	li.d		t0, CSR_DMW0_INIT	# UC, PLV0
81 	csrwr		t0, LOONGARCH_CSR_DMWIN0
82 	li.d		t0, CSR_DMW1_INIT	# CA, PLV0
83 	csrwr		t0, LOONGARCH_CSR_DMWIN1
84 
85 	JUMP_VIRT_ADDR	t0, t1
86 
87 	/* Enable PG */
88 	li.w		t0, 0xb0		# PLV=0, IE=0, PG=1
89 	csrwr		t0, LOONGARCH_CSR_CRMD
90 
91 	la.pcrel	t0, acpi_saved_sp
92 	ld.d		sp, t0, 0
93 	SETUP_WAKEUP
94 	addi.d		sp, sp, PT_SIZE
95 	jr		ra
96 SYM_FUNC_END(loongarch_suspend_enter)
97