1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Based on swsusp_32.S, modified for FSL BookE by
4 * Anton Vorontsov <avorontsov@ru.mvista.com>
5 * Copyright (c) 2009-2010 MontaVista Software, LLC.
6 */
7
8#include <linux/threads.h>
9#include <asm/processor.h>
10#include <asm/page.h>
11#include <asm/cputable.h>
12#include <asm/thread_info.h>
13#include <asm/ppc_asm.h>
14#include <asm/asm-offsets.h>
15#include <asm/mmu.h>
16
17/*
18 * Structure for storing CPU registers on the save area.
19 */
20#define SL_SP		0
21#define SL_PC		4
22#define SL_MSR		8
23#define SL_TCR		0xc
24#define SL_SPRG0	0x10
25#define SL_SPRG1	0x14
26#define SL_SPRG2	0x18
27#define SL_SPRG3	0x1c
28#define SL_SPRG4	0x20
29#define SL_SPRG5	0x24
30#define SL_SPRG6	0x28
31#define SL_SPRG7	0x2c
32#define SL_TBU		0x30
33#define SL_TBL		0x34
34#define SL_R2		0x38
35#define SL_CR		0x3c
36#define SL_LR		0x40
37#define SL_R12		0x44	/* r12 to r31 */
38#define SL_SIZE		(SL_R12 + 80)
39
40	.section .data
41	.align	5
42
43_GLOBAL(swsusp_save_area)
44	.space	SL_SIZE
45
46
47	.section .text
48	.align	5
49
50_GLOBAL(swsusp_arch_suspend)
51	lis	r11,swsusp_save_area@h
52	ori	r11,r11,swsusp_save_area@l
53
54	mflr	r0
55	stw	r0,SL_LR(r11)
56	mfcr	r0
57	stw	r0,SL_CR(r11)
58	stw	r1,SL_SP(r11)
59	stw	r2,SL_R2(r11)
60	stmw	r12,SL_R12(r11)
61
62	/* Save MSR & TCR */
63	mfmsr	r4
64	stw	r4,SL_MSR(r11)
65	mfspr	r4,SPRN_TCR
66	stw	r4,SL_TCR(r11)
67
68	/* Get a stable timebase and save it */
691:	mfspr	r4,SPRN_TBRU
70	stw	r4,SL_TBU(r11)
71	mfspr	r5,SPRN_TBRL
72	stw	r5,SL_TBL(r11)
73	mfspr	r3,SPRN_TBRU
74	cmpw	r3,r4
75	bne	1b
76
77	/* Save SPRGs */
78	mfspr	r4,SPRN_SPRG0
79	stw	r4,SL_SPRG0(r11)
80	mfspr	r4,SPRN_SPRG1
81	stw	r4,SL_SPRG1(r11)
82	mfspr	r4,SPRN_SPRG2
83	stw	r4,SL_SPRG2(r11)
84	mfspr	r4,SPRN_SPRG3
85	stw	r4,SL_SPRG3(r11)
86	mfspr	r4,SPRN_SPRG4
87	stw	r4,SL_SPRG4(r11)
88	mfspr	r4,SPRN_SPRG5
89	stw	r4,SL_SPRG5(r11)
90	mfspr	r4,SPRN_SPRG6
91	stw	r4,SL_SPRG6(r11)
92	mfspr	r4,SPRN_SPRG7
93	stw	r4,SL_SPRG7(r11)
94
95	/* Call the low level suspend stuff (we should probably have made
96	 * a stackframe...
97	 */
98	bl	swsusp_save
99
100	/* Restore LR from the save area */
101	lis	r11,swsusp_save_area@h
102	ori	r11,r11,swsusp_save_area@l
103	lwz	r0,SL_LR(r11)
104	mtlr	r0
105
106	blr
107
108_GLOBAL(swsusp_arch_resume)
109	sync
110
111	/* Load ptr the list of pages to copy in r3 */
112	lis	r11,(restore_pblist)@h
113	ori	r11,r11,restore_pblist@l
114	lwz	r3,0(r11)
115
116	/* Copy the pages. This is a very basic implementation, to
117	 * be replaced by something more cache efficient */
1181:
119	li	r0,256
120	mtctr	r0
121	lwz	r5,pbe_address(r3)	/* source */
122	lwz	r6,pbe_orig_address(r3)	/* destination */
1232:
124	lwz	r8,0(r5)
125	lwz	r9,4(r5)
126	lwz	r10,8(r5)
127	lwz	r11,12(r5)
128	addi	r5,r5,16
129	stw	r8,0(r6)
130	stw	r9,4(r6)
131	stw	r10,8(r6)
132	stw	r11,12(r6)
133	addi	r6,r6,16
134	bdnz	2b
135	lwz	r3,pbe_next(r3)
136	cmpwi	0,r3,0
137	bne	1b
138
139	bl flush_dcache_L1
140	bl flush_instruction_cache
141
142	lis	r11,swsusp_save_area@h
143	ori	r11,r11,swsusp_save_area@l
144
145	/*
146	 * Mappings from virtual addresses to physical addresses may be
147	 * different than they were prior to restoring hibernation state.
148	 * Invalidate the TLB so that the boot CPU is using the new
149	 * mappings.
150	 */
151	bl	_tlbil_all
152
153	lwz	r4,SL_SPRG0(r11)
154	mtspr	SPRN_SPRG0,r4
155	lwz	r4,SL_SPRG1(r11)
156	mtspr	SPRN_SPRG1,r4
157	lwz	r4,SL_SPRG2(r11)
158	mtspr	SPRN_SPRG2,r4
159	lwz	r4,SL_SPRG3(r11)
160	mtspr	SPRN_SPRG3,r4
161	lwz	r4,SL_SPRG4(r11)
162	mtspr	SPRN_SPRG4,r4
163	lwz	r4,SL_SPRG5(r11)
164	mtspr	SPRN_SPRG5,r4
165	lwz	r4,SL_SPRG6(r11)
166	mtspr	SPRN_SPRG6,r4
167	lwz	r4,SL_SPRG7(r11)
168	mtspr	SPRN_SPRG7,r4
169
170	/* restore the MSR */
171	lwz	r3,SL_MSR(r11)
172	mtmsr	r3
173
174	/* Restore TB */
175	li	r3,0
176	mtspr	SPRN_TBWL,r3
177	lwz	r3,SL_TBU(r11)
178	lwz	r4,SL_TBL(r11)
179	mtspr	SPRN_TBWU,r3
180	mtspr	SPRN_TBWL,r4
181
182	/* Restore TCR and clear any pending bits in TSR. */
183	lwz	r4,SL_TCR(r11)
184	mtspr	SPRN_TCR,r4
185	lis	r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
186	mtspr	SPRN_TSR,r4
187
188	/* Kick decrementer */
189	li	r0,1
190	mtdec	r0
191
192	/* Restore the callee-saved registers and return */
193	lwz	r0,SL_CR(r11)
194	mtcr	r0
195	lwz	r2,SL_R2(r11)
196	lmw	r12,SL_R12(r11)
197	lwz	r1,SL_SP(r11)
198	lwz	r0,SL_LR(r11)
199	mtlr	r0
200
201	li	r3,0
202	blr
203