summaryrefslogtreecommitdiffstats
path: root/arch/nds32/kernel/sleep.S
blob: ca4e61f3656fddf1a931a41d4f156bb798b92bee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2017 Andes Technology Corporation */

#include <asm/memory.h>

.data
.global sp_tmp
sp_tmp:
.long

.text
.globl suspend2ram
.globl cpu_resume

suspend2ram:
	pushm   $r0, $r31
#if defined(CONFIG_HWZOL)
	mfusr   $r0, $lc
	mfusr   $r1, $le
	mfusr   $r2, $lb
#endif
	mfsr	$r3, $mr0
	mfsr    $r4, $mr1
	mfsr    $r5, $mr4
	mfsr    $r6, $mr6
	mfsr    $r7, $mr7
	mfsr    $r8, $mr8
	mfsr    $r9, $ir0
	mfsr    $r10, $ir1
	mfsr    $r11, $ir2
	mfsr    $r12, $ir3
	mfsr    $r13, $ir9
	mfsr    $r14, $ir10
	mfsr    $r15, $ir12
	mfsr    $r16, $ir13
	mfsr    $r17, $ir14
	mfsr    $r18, $ir15
	pushm   $r0, $r19
#if defined(CONFIG_FPU)
	jal	store_fpu_for_suspend
#endif
	tlbop	FlushAll
	isb

	// transfer $sp from va to pa
	sethi	$r0, hi20(PAGE_OFFSET)
	ori	$r0, $r0, lo12(PAGE_OFFSET)
	movi	$r2, PHYS_OFFSET
	sub	$r1, $sp, $r0
	add	$r2, $r1, $r2

	// store pa($sp) to sp_tmp
	sethi 	$r1, hi20(sp_tmp)
	swi	$r2, [$r1 + lo12(sp_tmp)]

	pushm	$r16, $r25
	pushm	$r29, $r30
#ifdef	CONFIG_CACHE_L2
	jal	dcache_wb_all_level
#else
	jal	cpu_dcache_wb_all
#endif
	popm	$r29, $r30
	popm	$r16, $r25

	// get wake_mask and loop in standby
	la	$r1, wake_mask
	lwi	$r1, [$r1]
self_loop:
	standby wake_grant
	mfsr	$r2, $ir15
	and	$r2, $r1, $r2
	beqz	$r2, self_loop

	// set ipc to resume address
	la	$r1, resume_addr
	lwi	$r1, [$r1]
	mtsr	$r1, $ipc
	isb

	// reset psw, turn off the address translation
	li      $r2, 0x7000a
	mtsr    $r2, $ipsw
	isb

	iret
cpu_resume:
	// translate the address of sp_tmp variable to pa
	la	$r1, sp_tmp
	sethi   $r0, hi20(PAGE_OFFSET)
	ori     $r0, $r0, lo12(PAGE_OFFSET)
	movi    $r2, PHYS_OFFSET
	sub     $r1, $r1, $r0
	add     $r1, $r1, $r2

	// access the sp_tmp to get stack pointer
	lwi	$sp, [$r1]

	popm	$r0, $r19
#if defined(CONFIG_HWZOL)
	mtusr   $r0, $lb
	mtusr   $r1, $lc
	mtusr   $r2, $le
#endif
	mtsr	$r3, $mr0
	mtsr    $r4, $mr1
	mtsr    $r5, $mr4
	mtsr    $r6, $mr6
	mtsr    $r7, $mr7
	mtsr    $r8, $mr8
	// set original psw to ipsw
	mtsr    $r9, $ir1

	mtsr    $r11, $ir2
	mtsr    $r12, $ir3

	// set ipc to RR
	la	$r13, RR
	mtsr	$r13, $ir9

	mtsr    $r14, $ir10
	mtsr    $r15, $ir12
	mtsr    $r16, $ir13
	mtsr    $r17, $ir14
	mtsr    $r18, $ir15
	popm    $r0, $r31

	isb
	iret
RR:
	ret