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,77 @@ 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" : : "r" (backup -> S ) : "memory" );
209
+ }
210
+
211
+ static void fpu_restore (_fpu_context_t * backup )
212
+ {
213
+ FPU -> FPCCR = backup -> FPCCR ;
214
+ FPU -> FPCAR = backup -> FPCAR ;
215
+ FPU -> FPDSCR = backup -> FPDSCR ;
216
+
217
+ __asm__ volatile ("vldmia %0, {s0-s31}\n" : : "r" (backup -> S ) : "memory" );
160
218
}
219
+ #endif /* !defined(CONFIG_FPU_SHARING) */
220
+ #endif /* defined(CONFIG_FPU) */
161
221
162
222
int soc_s2ram_suspend (pm_s2ram_system_off_fn_t system_off )
163
223
{
164
224
int ret ;
165
225
166
- scb_suspend (& backup_data .scb_context );
167
- nvic_suspend (& backup_data .nvic_context );
168
- mpu_suspend (& backup_data .mpu_context );
226
+ scb_save (& backup_data .scb_context );
227
+ #if defined(CONFIG_FPU )
228
+ #if !defined(CONFIG_FPU_SHARING )
229
+ fpu_save (& backup_data .fpu_context );
230
+ #endif
231
+ fpu_power_down ();
232
+ #endif
233
+ nvic_save (& backup_data .nvic_context );
234
+ mpu_save (& backup_data .mpu_context );
169
235
ret = arch_pm_s2ram_suspend (system_off );
170
- /* Cache is powered down so power up is needed even if s2ram failed. */
236
+ /* Cache and FPU are powered down so power up is needed even if s2ram failed. */
171
237
nrf_power_up_cache ();
238
+ #if defined(CONFIG_FPU )
239
+ fpu_power_up ();
240
+ #if !defined(CONFIG_FPU_SHARING )
241
+ /* Also the FPU content might be lost. */
242
+ fpu_restore (& backup_data .fpu_context );
243
+ #endif
244
+ #endif
172
245
if (ret < 0 ) {
173
246
return ret ;
174
247
}
175
248
176
- mpu_resume (& backup_data .mpu_context );
177
- nvic_resume (& backup_data .nvic_context );
178
- scb_resume (& backup_data .scb_context );
249
+ mpu_restore (& backup_data .mpu_context );
250
+ nvic_restore (& backup_data .nvic_context );
251
+ scb_restore (& backup_data .scb_context );
179
252
180
253
return ret ;
181
254
}
0 commit comments