1515
1616#define NVIC_MEMBER_SIZE (member ) ARRAY_SIZE(((NVIC_Type *)0)->member)
1717
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+
1825/* Currently dynamic regions are only used in case of userspace or stack guard and
1926 * stack guard is not used by default on Cortex-M33 because there is a dedicated
2027 * mechanism for stack overflow detection. Unless those condition change we don't
@@ -55,12 +62,25 @@ typedef struct {
5562 uint32_t MMFAR ;
5663 uint32_t BFAR ;
5764 uint32_t AFSR ;
65+ uint32_t CPACR ;
5866} _scb_context_t ;
5967
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+
6077struct backup {
6178 _nvic_context_t nvic_context ;
6279 _mpu_context_t mpu_context ;
6380 _scb_context_t scb_context ;
81+ #if defined(CONFIG_FPU ) && !defined(CONFIG_FPU_SHARING )
82+ _fpu_context_t fpu_context ;
83+ #endif
6484};
6585
6686static __noinit struct backup backup_data ;
@@ -71,7 +91,7 @@ extern int z_arm_mpu_init(void);
7191/* MPU registers cannot be simply copied because content of RBARx RLARx registers
7292 * depends on region which is selected by RNR register.
7393 */
74- static void mpu_suspend (_mpu_context_t * backup )
94+ static void mpu_save (_mpu_context_t * backup )
7595{
7696 if (!MPU_USE_DYNAMIC_REGIONS ) {
7797 return ;
@@ -89,7 +109,7 @@ static void mpu_suspend(_mpu_context_t *backup)
89109 backup -> CTRL = MPU -> CTRL ;
90110}
91111
92- static void mpu_resume (_mpu_context_t * backup )
112+ static void mpu_restore (_mpu_context_t * backup )
93113{
94114 if (!MPU_USE_DYNAMIC_REGIONS ) {
95115 z_arm_mpu_init ();
@@ -111,21 +131,21 @@ static void mpu_resume(_mpu_context_t *backup)
111131 MPU -> CTRL = backup -> CTRL ;
112132}
113133
114- static void nvic_suspend (_nvic_context_t * backup )
134+ static void nvic_save (_nvic_context_t * backup )
115135{
116136 memcpy (backup -> ISER , (uint32_t * )NVIC -> ISER , sizeof (NVIC -> ISER ));
117137 memcpy (backup -> ISPR , (uint32_t * )NVIC -> ISPR , sizeof (NVIC -> ISPR ));
118138 memcpy (backup -> IPR , (uint32_t * )NVIC -> IPR , sizeof (NVIC -> IPR ));
119139}
120140
121- static void nvic_resume (_nvic_context_t * backup )
141+ static void nvic_restore (_nvic_context_t * backup )
122142{
123143 memcpy ((uint32_t * )NVIC -> ISER , backup -> ISER , sizeof (NVIC -> ISER ));
124144 memcpy ((uint32_t * )NVIC -> ISPR , backup -> ISPR , sizeof (NVIC -> ISPR ));
125145 memcpy ((uint32_t * )NVIC -> IPR , backup -> IPR , sizeof (NVIC -> IPR ));
126146}
127147
128- static void scb_suspend (_scb_context_t * backup )
148+ static void scb_save (_scb_context_t * backup )
129149{
130150 backup -> ICSR = SCB -> ICSR ;
131151 backup -> VTOR = SCB -> VTOR ;
@@ -140,9 +160,10 @@ static void scb_suspend(_scb_context_t *backup)
140160 backup -> MMFAR = SCB -> MMFAR ;
141161 backup -> BFAR = SCB -> BFAR ;
142162 backup -> AFSR = SCB -> AFSR ;
163+ backup -> CPACR = SCB -> CPACR ;
143164}
144165
145- static void scb_resume (_scb_context_t * backup )
166+ static void scb_restore (_scb_context_t * backup )
146167{
147168 SCB -> ICSR = backup -> ICSR ;
148169 SCB -> VTOR = backup -> VTOR ;
@@ -157,25 +178,77 @@ static void scb_resume(_scb_context_t *backup)
157178 SCB -> MMFAR = backup -> MMFAR ;
158179 SCB -> BFAR = backup -> BFAR ;
159180 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" );
160218}
219+ #endif /* !defined(CONFIG_FPU_SHARING) */
220+ #endif /* defined(CONFIG_FPU) */
161221
162222int soc_s2ram_suspend (pm_s2ram_system_off_fn_t system_off )
163223{
164224 int ret ;
165225
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 );
169235 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. */
171237 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
172245 if (ret < 0 ) {
173246 return ret ;
174247 }
175248
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 );
179252
180253 return ret ;
181254}
0 commit comments