Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / mips / include / asm / pm.h
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  */
146 struct 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 */