Commit | Line | Data |
---|---|---|
74e91335 JH |
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) | |
74e91335 JH |
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 | |
74e91335 JH |
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 */ |