xref: /kernel/linux/linux-5.10/arch/mips/include/asm/pm.h (revision 8c2ecf20)
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (C) 2014 Imagination Technologies Ltd
4 *
5 * PM helper macros for CPU power off (e.g. Suspend-to-RAM).
6 */
7
8#ifndef __ASM_PM_H
9#define __ASM_PM_H
10
11#ifdef __ASSEMBLY__
12
13#include <asm/asm-offsets.h>
14#include <asm/asm.h>
15#include <asm/mipsregs.h>
16#include <asm/regdef.h>
17
18/* Save CPU state to stack for suspend to RAM */
19.macro SUSPEND_SAVE_REGS
20	subu	sp, PT_SIZE
21	/* Call preserved GPRs */
22	LONG_S	$16, PT_R16(sp)
23	LONG_S	$17, PT_R17(sp)
24	LONG_S	$18, PT_R18(sp)
25	LONG_S	$19, PT_R19(sp)
26	LONG_S	$20, PT_R20(sp)
27	LONG_S	$21, PT_R21(sp)
28	LONG_S	$22, PT_R22(sp)
29	LONG_S	$23, PT_R23(sp)
30	LONG_S	$28, PT_R28(sp)
31	LONG_S	$30, PT_R30(sp)
32	LONG_S	$31, PT_R31(sp)
33	/* A couple of CP0 registers with space in pt_regs */
34	mfc0	k0, CP0_STATUS
35	LONG_S	k0, PT_STATUS(sp)
36.endm
37
38/* Restore CPU state from stack after resume from RAM */
39.macro RESUME_RESTORE_REGS_RETURN
40	.set	push
41	.set	noreorder
42	/* A couple of CP0 registers with space in pt_regs */
43	LONG_L	k0, PT_STATUS(sp)
44	mtc0	k0, CP0_STATUS
45	/* Call preserved GPRs */
46	LONG_L	$16, PT_R16(sp)
47	LONG_L	$17, PT_R17(sp)
48	LONG_L	$18, PT_R18(sp)
49	LONG_L	$19, PT_R19(sp)
50	LONG_L	$20, PT_R20(sp)
51	LONG_L	$21, PT_R21(sp)
52	LONG_L	$22, PT_R22(sp)
53	LONG_L	$23, PT_R23(sp)
54	LONG_L	$28, PT_R28(sp)
55	LONG_L	$30, PT_R30(sp)
56	LONG_L	$31, PT_R31(sp)
57	/* Pop and return */
58	jr	ra
59	 addiu	sp, PT_SIZE
60	.set	pop
61.endm
62
63/* Get address of static suspend state into t1 */
64.macro LA_STATIC_SUSPEND
65	la	t1, mips_static_suspend_state
66.endm
67
68/* Save important CPU state for early restoration to global data */
69.macro SUSPEND_SAVE_STATIC
70#ifdef CONFIG_EVA
71	/*
72	 * Segment configuration is saved in global data where it can be easily
73	 * reloaded without depending on the segment configuration.
74	 */
75	mfc0	k0, CP0_PAGEMASK, 2	/* SegCtl0 */
76	LONG_S	k0, SSS_SEGCTL0(t1)
77	mfc0	k0, CP0_PAGEMASK, 3	/* SegCtl1 */
78	LONG_S	k0, SSS_SEGCTL1(t1)
79	mfc0	k0, CP0_PAGEMASK, 4	/* SegCtl2 */
80	LONG_S	k0, SSS_SEGCTL2(t1)
81#endif
82	/* save stack pointer (pointing to GPRs) */
83	LONG_S	sp, SSS_SP(t1)
84.endm
85
86/* Restore important CPU state early from global data */
87.macro RESUME_RESTORE_STATIC
88#ifdef CONFIG_EVA
89	/*
90	 * Segment configuration must be restored prior to any access to
91	 * allocated memory, as it may reside outside of the legacy kernel
92	 * segments.
93	 */
94	LONG_L	k0, SSS_SEGCTL0(t1)
95	mtc0	k0, CP0_PAGEMASK, 2	/* SegCtl0 */
96	LONG_L	k0, SSS_SEGCTL1(t1)
97	mtc0	k0, CP0_PAGEMASK, 3	/* SegCtl1 */
98	LONG_L	k0, SSS_SEGCTL2(t1)
99	mtc0	k0, CP0_PAGEMASK, 4	/* SegCtl2 */
100	tlbw_use_hazard
101#endif
102	/* restore stack pointer (pointing to GPRs) */
103	LONG_L	sp, SSS_SP(t1)
104.endm
105
106/* flush caches to make sure context has reached memory */
107.macro SUSPEND_CACHE_FLUSH
108	.extern	__wback_cache_all
109	.set	push
110	.set	noreorder
111	la	t1, __wback_cache_all
112	LONG_L	t0, 0(t1)
113	jalr	t0
114	 nop
115	.set	pop
116 .endm
117
118/* Save suspend state and flush data caches to RAM */
119.macro SUSPEND_SAVE
120	SUSPEND_SAVE_REGS
121	LA_STATIC_SUSPEND
122	SUSPEND_SAVE_STATIC
123	SUSPEND_CACHE_FLUSH
124.endm
125
126/* Restore saved state after resume from RAM and return */
127.macro RESUME_RESTORE_RETURN
128	LA_STATIC_SUSPEND
129	RESUME_RESTORE_STATIC
130	RESUME_RESTORE_REGS_RETURN
131.endm
132
133#else /* __ASSEMBLY__ */
134
135/**
136 * struct mips_static_suspend_state - Core saved CPU state across S2R.
137 * @segctl:	CP0 Segment control registers.
138 * @sp:		Stack frame where GP register context is saved.
139 *
140 * This structure contains minimal CPU state that must be saved in static kernel
141 * data in order to be able to restore the rest of the state. This includes
142 * segmentation configuration in the case of EVA being enabled, as they must be
143 * restored prior to any kmalloc'd memory being referenced (even the stack
144 * pointer).
145 */
146struct mips_static_suspend_state {
147#ifdef CONFIG_EVA
148	unsigned long segctl[3];
149#endif
150	unsigned long sp;
151};
152
153#endif /* !__ASSEMBLY__ */
154
155#endif /* __ASM_PM_HELPERS_H */
156