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