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 */
64SYM_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	 */
79SYM_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
96SYM_FUNC_END(loongarch_suspend_enter)
97