15
15
16
16
#define NVIC_MEMBER_SIZE (member ) ARRAY_SIZE(((NVIC_Type *)0)->member)
17
17
18
+ /* Coprocessor Power Control Register Definitions */
19
+ #define SCnSCB_CPPWR_SU11_Pos 22U /*!< CPPWR: SU11 Position */
20
+ #define SCnSCB_CPPWR_SU11_Msk (1UL << SCnSCB_CPPWR_SU11_Pos) /*!< CPPWR: SU11 Mask */
21
+
22
+ #define SCnSCB_CPPWR_SU10_Pos 20U /*!< CPPWR: SU10 Position */
23
+ #define SCnSCB_CPPWR_SU10_Msk (1UL << SCnSCB_CPPWR_SU10_Pos) /*!< CPPWR: SU10 Mask */
24
+
18
25
/* Currently dynamic regions are only used in case of userspace or stack guard and
19
26
* stack guard is not used by default on Cortex-M33 because there is a dedicated
20
27
* mechanism for stack overflow detection. Unless those condition change we don't
@@ -55,12 +62,25 @@ typedef struct {
55
62
uint32_t MMFAR ;
56
63
uint32_t BFAR ;
57
64
uint32_t AFSR ;
65
+ uint32_t CPACR ;
58
66
} _scb_context_t ;
59
67
68
+ #if defined(CONFIG_FPU ) && !defined(CONFIG_FPU_SHARING )
69
+ typedef struct {
70
+ uint32_t FPCCR ;
71
+ uint32_t FPCAR ;
72
+ uint32_t FPDSCR ;
73
+ uint32_t S [32 ];
74
+ } _fpu_context_t ;
75
+ #endif
76
+
60
77
struct backup {
61
78
_nvic_context_t nvic_context ;
62
79
_mpu_context_t mpu_context ;
63
80
_scb_context_t scb_context ;
81
+ #if defined(CONFIG_FPU ) && !defined(CONFIG_FPU_SHARING )
82
+ _fpu_context_t fpu_context ;
83
+ #endif
64
84
};
65
85
66
86
static __noinit struct backup backup_data ;
@@ -71,7 +91,7 @@ extern int z_arm_mpu_init(void);
71
91
/* MPU registers cannot be simply copied because content of RBARx RLARx registers
72
92
* depends on region which is selected by RNR register.
73
93
*/
74
- static void mpu_suspend (_mpu_context_t * backup )
94
+ static void mpu_save (_mpu_context_t * backup )
75
95
{
76
96
if (!MPU_USE_DYNAMIC_REGIONS ) {
77
97
return ;
@@ -89,7 +109,7 @@ static void mpu_suspend(_mpu_context_t *backup)
89
109
backup -> CTRL = MPU -> CTRL ;
90
110
}
91
111
92
- static void mpu_resume (_mpu_context_t * backup )
112
+ static void mpu_restore (_mpu_context_t * backup )
93
113
{
94
114
if (!MPU_USE_DYNAMIC_REGIONS ) {
95
115
z_arm_mpu_init ();
@@ -111,21 +131,21 @@ static void mpu_resume(_mpu_context_t *backup)
111
131
MPU -> CTRL = backup -> CTRL ;
112
132
}
113
133
114
- static void nvic_suspend (_nvic_context_t * backup )
134
+ static void nvic_save (_nvic_context_t * backup )
115
135
{
116
136
memcpy (backup -> ISER , (uint32_t * )NVIC -> ISER , sizeof (NVIC -> ISER ));
117
137
memcpy (backup -> ISPR , (uint32_t * )NVIC -> ISPR , sizeof (NVIC -> ISPR ));
118
138
memcpy (backup -> IPR , (uint32_t * )NVIC -> IPR , sizeof (NVIC -> IPR ));
119
139
}
120
140
121
- static void nvic_resume (_nvic_context_t * backup )
141
+ static void nvic_restore (_nvic_context_t * backup )
122
142
{
123
143
memcpy ((uint32_t * )NVIC -> ISER , backup -> ISER , sizeof (NVIC -> ISER ));
124
144
memcpy ((uint32_t * )NVIC -> ISPR , backup -> ISPR , sizeof (NVIC -> ISPR ));
125
145
memcpy ((uint32_t * )NVIC -> IPR , backup -> IPR , sizeof (NVIC -> IPR ));
126
146
}
127
147
128
- static void scb_suspend (_scb_context_t * backup )
148
+ static void scb_save (_scb_context_t * backup )
129
149
{
130
150
backup -> ICSR = SCB -> ICSR ;
131
151
backup -> VTOR = SCB -> VTOR ;
@@ -140,9 +160,10 @@ static void scb_suspend(_scb_context_t *backup)
140
160
backup -> MMFAR = SCB -> MMFAR ;
141
161
backup -> BFAR = SCB -> BFAR ;
142
162
backup -> AFSR = SCB -> AFSR ;
163
+ backup -> CPACR = SCB -> CPACR ;
143
164
}
144
165
145
- static void scb_resume (_scb_context_t * backup )
166
+ static void scb_restore (_scb_context_t * backup )
146
167
{
147
168
SCB -> ICSR = backup -> ICSR ;
148
169
SCB -> VTOR = backup -> VTOR ;
@@ -157,25 +178,85 @@ static void scb_resume(_scb_context_t *backup)
157
178
SCB -> MMFAR = backup -> MMFAR ;
158
179
SCB -> BFAR = backup -> BFAR ;
159
180
SCB -> AFSR = backup -> AFSR ;
181
+ SCB -> CPACR = backup -> CPACR ;
182
+ }
183
+
184
+ #if defined(CONFIG_FPU )
185
+ static void fpu_power_down (void )
186
+ {
187
+ SCB -> CPACR &= (~(CPACR_CP10_Msk | CPACR_CP11_Msk ));
188
+ SCnSCB -> CPPWR |= (SCnSCB_CPPWR_SU11_Msk | SCnSCB_CPPWR_SU10_Msk );
189
+ __DSB ();
190
+ __ISB ();
191
+ }
192
+
193
+ static void fpu_power_up (void )
194
+ {
195
+ SCnSCB -> CPPWR &= (~(SCnSCB_CPPWR_SU11_Msk | SCnSCB_CPPWR_SU10_Msk ));
196
+ SCB -> CPACR |= (CPACR_CP10_Msk | CPACR_CP11_Msk );
197
+ __DSB ();
198
+ __ISB ();
199
+ }
200
+
201
+ #if !defined(CONFIG_FPU_SHARING )
202
+ static void fpu_save (_fpu_context_t * backup )
203
+ {
204
+ backup -> FPCCR = FPU -> FPCCR ;
205
+ backup -> FPCAR = FPU -> FPCAR ;
206
+ backup -> FPDSCR = FPU -> FPDSCR ;
207
+
208
+ __asm__ volatile ("vstmia %0, {s0-s31}\n"
209
+ :
210
+ : "r" (backup -> S )
211
+ : "memory"
212
+ );
213
+ }
214
+
215
+ static void fpu_restore (_fpu_context_t * backup )
216
+ {
217
+ FPU -> FPCCR = backup -> FPCCR ;
218
+ FPU -> FPCAR = backup -> FPCAR ;
219
+ FPU -> FPDSCR = backup -> FPDSCR ;
220
+
221
+ __asm__ volatile ("vldmia %0, {s0-s31}\n"
222
+ :
223
+ : "r" (backup -> S )
224
+ : "memory"
225
+ );
160
226
}
227
+ #endif /* !defined(CONFIG_FPU_SHARING) */
228
+ #endif /* defined(CONFIG_FPU) */
161
229
162
230
int soc_s2ram_suspend (pm_s2ram_system_off_fn_t system_off )
163
231
{
164
232
int ret ;
165
233
166
- scb_suspend (& backup_data .scb_context );
167
- nvic_suspend (& backup_data .nvic_context );
168
- mpu_suspend (& backup_data .mpu_context );
234
+ scb_save (& backup_data .scb_context );
235
+ #if defined(CONFIG_FPU )
236
+ #if !defined(CONFIG_FPU_SHARING )
237
+ fpu_save (& backup_data .fpu_context );
238
+ #endif
239
+ fpu_power_down ();
240
+ #endif
241
+ nvic_save (& backup_data .nvic_context );
242
+ mpu_save (& backup_data .mpu_context );
169
243
ret = arch_pm_s2ram_suspend (system_off );
170
- /* Cache is powered down so power up is needed even if s2ram failed. */
244
+ /* Cache and FPU are powered down so power up is needed even if s2ram failed. */
171
245
nrf_power_up_cache ();
246
+ #if defined(CONFIG_FPU )
247
+ fpu_power_up ();
248
+ #if !defined(CONFIG_FPU_SHARING )
249
+ /* Also the FPU content might be lost. */
250
+ fpu_restore (& backup_data .fpu_context );
251
+ #endif
252
+ #endif
172
253
if (ret < 0 ) {
173
254
return ret ;
174
255
}
175
256
176
- mpu_resume (& backup_data .mpu_context );
177
- nvic_resume (& backup_data .nvic_context );
178
- scb_resume (& backup_data .scb_context );
257
+ mpu_restore (& backup_data .mpu_context );
258
+ nvic_restore (& backup_data .nvic_context );
259
+ scb_restore (& backup_data .scb_context );
179
260
180
261
return ret ;
181
262
}
0 commit comments