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