1 /*
2  * Copyright 2021-2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <setjmp.h>
9 
10 #include "fsl_pm_core.h"
11 #include "fsl_pm_device.h"
12 
13 #include "fsl_cmc.h"
14 #include "fsl_spc.h"
15 #include "fsl_wuu.h"
16 #include "fsl_clock.h"
17 #include "fsl_crc.h"
18 
19 /*
20  * $Coverage Justification Reference$
21  *
22  * $Justification pm_device_c_ref_1$
23  * Following lines added to avoid MISRA violations and will never hit.
24  *
25  * $Justification pm_device_c_ref_2$
26  * Set chip in low-power modes will disconnect debugger and it is unable to get coverage data.
27  *
28  * $Justification pm_device_c_ref_3$
29  * Following lines will power off selected RAM block and it is unable to get coverage data.
30  */
31 
32 /*******************************************************************************
33  * Macros
34  ******************************************************************************/
35 #define WUU_PIN_FLAG_MASK                                                                                              \
36     (WUU_PF_WUF0_MASK | WUU_PF_WUF2_MASK | WUU_PF_WUF3_MASK | WUU_PF_WUF4_MASK | WUU_PF_WUF5_MASK | WUU_PF_WUF7_MASK | \
37      WUU_PF_WUF8_MASK | WUU_PF_WUF9_MASK | WUU_PF_WUF10_MASK | WUU_PF_WUF11_MASK | WUU_PF_WUF12_MASK |                 \
38      WUU_PF_WUF13_MASK | WUU_PF_WUF14_MASK | WUU_PF_WUF15_MASK | WUU_PF_WUF27_MASK | WUU_PF_WUF28_MASK)
39 
40 /*******************************************************************************
41  * Prototypes
42  ******************************************************************************/
43 typedef struct _pm_dev_resource_recode pm_dev_resource_recode_t;
44 
45 static void PM_DEV_WakeupFunction(void);
46 static void PM_DEV_EnterLowPowerMode(uint8_t stateIndex, pm_resc_mask_t *pSoftRescMask, pm_resc_group_t *pSysRescGroup);
47 static void PM_DEV_CleanExitLowPowerMode(void);
48 static uint8_t PM_DEV_FindOperateMode(uint32_t rescIndex, pm_resc_group_t *pSysRescGroup);
49 static void PM_DEV_SetRAMOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode);
50 static void PM_DEV_SetFro192MOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode);
51 static void PM_DEV_SetFro6MOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode);
52 static void PM_DEV_SetWakePowerDomainOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode);
53 static void PM_DEV_SaveRuntimeContext(void);
54 static void PM_DEV_RestoreRuntimeContext(void);
55 
56 static void PM_DEV_EnableBasicResources(pm_resc_mask_t *pSoftRescMask, pm_resc_group_t *pSysRescGroup);
57 
58 #if (defined(FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER) && FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER)
59 static status_t PM_DEV_ManageWakeupSource(pm_wakeup_source_t *ws, bool enable);
60 static bool PM_DEV_IsWakeupSource(pm_wakeup_source_t *ws);
61 #endif /* FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER */
62 
63 /*******************************************************************************
64  * Variables
65  ******************************************************************************/
66 /*!
67  *  |  Module  |    Sleep     | Deep Sleep | Power Down | Deep Power Down |
68  *  |  CM33    |    Static    | Static     |    OFF     |       OFF       |
69  *  | FRO-192M |   Optional   |    OFF     |    OFF     |       OFF       |
70  *  | FRO-6M   |   Optional   |  Optional  |   Optional |       OFF       |
71  *  | FRO-32K  |      ON      |     ON     |   Optional |     Optional    |
72  *  | OSC-RTC  |      ON      |     ON     |   Optional |     Optional    |
73  *  | OSC-RF   |      ON      |  Optional  |   Optional |       OFF       |
74  *  |   SCG    |      ON      |   Static   |    Static  |       OFF       |
75  *  |   PCC    |      ON      |   Static   |    OFF     |       OFF       |
76  *  |  Flash   |  Optional LP |    OFF/LP  |    OFF     |       OFF       |
77  *  |  SRAMx   |   Optional   |   Optional |   Optional |       OFF       |
78  *  |  DCDC    |  Optional LP |  ON, LP or OFF | ON, LP or OFF | OFF |
79  *  |  LDO-CORE | Optional LP |  ON, LP or OFF | ON, LP or OFF | OFF |
80  *  |  LDO-SYS  | Optional LP |  ON, LP | ON, LP | ON, LP |
81  *  |  VDD_CORE HVD | Optional | Optional | Optional | OFF |
82  *  |  VDD_CORE LVD | Optional | Optional | Optional | OFF |
83  *  |  VDD_IO_ABC HVD | Optional | Optional | Optional | OFF |
84  *  |  VDD_IO_ABC LVD | Optional | Optional | Optional | OFF |
85  *  |  VDD_SYS HVD    | Optional | Optional | Optional | OFF |
86  *  |  VDD_SYS LVD    | Optional | Optional | Optional | OFF |
87  */
88 const pm_device_option_t g_devicePMOption = {
89     .states =
90         {
91             /* Sleep */
92             {
93                 .exitLatency = 140U, /* 140 us */
94                 .fixConstraintsMask =
95                     {
96                         .rescMask[0U] = 0x2000UL,
97                     },
98                 .varConstraintsMask =
99                     {
100                         .rescMask[0U] = 0x13FFUL,
101                     },
102             },
103             /* Deep Sleep */
104             {
105                 .exitLatency = 140U, /* 140 us */
106                 .fixConstraintsMask =
107                     {
108                         .rescMask[0] = 0x3880UL,
109                     },
110                 .varConstraintsMask =
111                     {
112                         .rescMask[0] = 0x33FUL,
113                     },
114             },
115             /* Power Down */
116             {
117                 .exitLatency = 600U, /* 600 us */
118                 .fixConstraintsMask =
119                     {
120                         .rescMask[0] = 0x3C80UL,
121                     },
122                 .varConstraintsMask =
123                     {
124                         .rescMask[0] = 0x37FUL,
125                     },
126             },
127             /* Deep Power Down */
128             {
129                 .fixConstraintsMask =
130                     {
131                         .rescMask[0] = 0x3FFFUL,
132                     },
133                 .varConstraintsMask =
134                     {
135                         .rescMask[0] = 0x0UL,
136                     },
137             },
138         },
139     .stateCount = 4U,
140     .enter      = PM_DEV_EnterLowPowerMode,
141     .clean      = PM_DEV_CleanExitLowPowerMode,
142 
143 #if (defined(FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER) && FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER)
144     .manageWakeupSource = PM_DEV_ManageWakeupSource,
145     .isWakeupSource     = PM_DEV_IsWakeupSource,
146 #endif /* FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER */
147 };
148 
149 struct _pm_dev_resource_recode
150 {
151     uint8_t defaultOperateMode : 4U;
152     uint8_t currentOperateMode : 4U;
153     void (*resourceConfigFunc)(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode);
154 };
155 
156 #define PM_RESOURCE_DB_COUNT (10U)
157 
158 AT_ALWAYS_ON_DATA_INIT(pm_dev_resource_recode_t resourceDB[PM_RESOURCE_DB_COUNT]) = {
159     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
160     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
161     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
162     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
163     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
164     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
165     {PM_RESOURCE_OFF, 0U, PM_DEV_SetRAMOperateMode},
166     {PM_RESOURCE_OFF, 0U, PM_DEV_SetFro192MOperateMode},
167     {PM_RESOURCE_OFF, 0U, PM_DEV_SetFro6MOperateMode},
168     {PM_RESOURCE_FULL_ON, PM_RESOURCE_FULL_ON, PM_DEV_SetWakePowerDomainOperateMode},
169 };
170 
171 AT_ALWAYS_ON_DATA_INIT(cmc_power_domain_config_t g_mainWakePDConfig) = {
172     .clock_mode = kCMC_GateAllSystemClocksEnterLowPowerMode,
173     /* we chose to put the main and wake domain in retention (deep sleep) by default if no constraints are set */
174     .main_domain = kCMC_DeepSleepMode,
175     .wake_domain = kCMC_DeepSleepMode,
176 };
177 
178 AT_ALWAYS_ON_DATA(jmp_buf g_coreContext);
179 AT_ALWAYS_ON_DATA(uint32_t g_scbVtor);
180 AT_ALWAYS_ON_DATA(uint32_t g_scbIcsr);
181 AT_ALWAYS_ON_DATA(uint32_t g_scbAircr);
182 AT_ALWAYS_ON_DATA(uint32_t g_scbCCR);
183 AT_ALWAYS_ON_DATA(uint8_t g_scbShp[12]);
184 AT_ALWAYS_ON_DATA(uint32_t g_scbShcsr);
185 AT_ALWAYS_ON_DATA(uint32_t g_nvicIser[16U]);
186 AT_ALWAYS_ON_DATA(uint8_t g_nvicIp[496U]);
187 AT_ALWAYS_ON_DATA(uint32_t g_systickCtrl);
188 AT_ALWAYS_ON_DATA(uint32_t g_systickLoad);
189 AT_ALWAYS_ON_DATA(uint32_t g_cpuControl);
190 AT_ALWAYS_ON_DATA(uint32_t g_wakeupEntry[12]);
191 AT_ALWAYS_ON_DATA(uint32_t crcResult);
192 
193 extern uint32_t m_warmboot_stack_end;
194 
195 /*******************************************************************************
196  * Code
197  ******************************************************************************/
PM_DEV_EnterLowPowerMode(uint8_t stateIndex,pm_resc_mask_t * pSoftRescMask,pm_resc_group_t * pSysRescGroup)198 static void PM_DEV_EnterLowPowerMode(uint8_t stateIndex, pm_resc_mask_t *pSoftRescMask, pm_resc_group_t *pSysRescGroup)
199 {
200     uint8_t rescMaskArrayIndex = 0U;
201     uint8_t rescMaskOffset     = 0U;
202 
203     switch (stateIndex)
204     {
205         case PM_LP_STATE_SLEEP:
206         {
207             rescMaskArrayIndex = PM_RESC_BUS_SYS_CLK_INDEX / 32U;
208             rescMaskOffset     = PM_RESC_BUS_SYS_CLK_INDEX % 32U;
209             if ((pSoftRescMask->rescMask[rescMaskArrayIndex] & (1UL << rescMaskOffset)) != 0UL)
210             {
211                 g_mainWakePDConfig.clock_mode    = kCMC_GateCoreClock;
212                 g_mainWakePDConfig.main_domain   = kCMC_ActiveMode;
213                 g_mainWakePDConfig.wake_domain   = kCMC_ActiveMode;
214                 resourceDB[9].currentOperateMode = PM_RESOURCE_FULL_ON;
215                 pSoftRescMask->rescMask[rescMaskArrayIndex] &= ~(1UL << rescMaskOffset);
216             }
217             else
218             {
219                 g_mainWakePDConfig.clock_mode    = kCMC_GateAllSystemClocksEnterLowPowerMode;
220                 g_mainWakePDConfig.main_domain   = kCMC_SleepMode;
221                 g_mainWakePDConfig.wake_domain   = kCMC_SleepMode;
222                 resourceDB[9].currentOperateMode = PM_RESOURCE_PARTABLE_ON2;
223             }
224             break;
225         }
226 
227         case PM_LP_STATE_DEEP_SLEEP:
228         {
229             g_mainWakePDConfig.clock_mode    = kCMC_GateAllSystemClocksEnterLowPowerMode;
230             g_mainWakePDConfig.main_domain   = kCMC_DeepSleepMode;
231             g_mainWakePDConfig.wake_domain   = kCMC_DeepSleepMode;
232             resourceDB[9].currentOperateMode = PM_RESOURCE_PARTABLE_ON1;
233             break;
234         }
235 
236         case PM_LP_STATE_POWER_DOWN:
237         {
238             g_mainWakePDConfig.clock_mode    = kCMC_GateAllSystemClocksEnterLowPowerMode;
239             g_mainWakePDConfig.main_domain   = kCMC_PowerDownMode;
240             g_mainWakePDConfig.wake_domain   = kCMC_PowerDownMode;
241             resourceDB[9].currentOperateMode = PM_RESOURCE_OFF;
242             break;
243         }
244 
245         case PM_LP_STATE_DEEP_POWER_DOWN:
246         {
247             g_mainWakePDConfig.clock_mode    = kCMC_GateAllSystemClocksEnterLowPowerMode;
248             g_mainWakePDConfig.main_domain   = kCMC_DeepPowerDown;
249             g_mainWakePDConfig.wake_domain   = kCMC_DeepPowerDown;
250             resourceDB[9].currentOperateMode = PM_RESOURCE_OFF;
251             break;
252         }
253 
254         /*
255          * $Line Coverage Justification$
256          * $ref pm_device_c_ref_1$.
257          */
258         default:
259         {
260             /* This branch should never be hit. */
261             break;
262         }
263     }
264     PM_DEV_EnableBasicResources(pSoftRescMask, pSysRescGroup);
265     CMC_SetPowerModeProtection(CMC0, (uint32_t)kCMC_AllowAllLowPowerModes);
266 
267     if ((stateIndex == PM_LP_STATE_SLEEP) || (stateIndex == PM_LP_STATE_DEEP_SLEEP))
268     {
269         if (g_mainWakePDConfig.clock_mode == kCMC_GateCoreClock)
270         {
271             /* This configuration corresponds to WFI only, only the core clock will be gated */
272             CMC_SetClockMode(CMC0, g_mainWakePDConfig.clock_mode);
273             CMC_SetMAINPowerMode(CMC0, g_mainWakePDConfig.main_domain);
274             CMC_SetWAKEPowerMode(CMC0, g_mainWakePDConfig.wake_domain);
275             SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
276             __DSB();
277             __WFI();
278             __ISB();
279         }
280         else
281         {
282             CMC_EnterLowPowerMode(CMC0, &g_mainWakePDConfig);
283         }
284     }
285     else
286     {
287         if (g_mainWakePDConfig.wake_domain <= g_mainWakePDConfig.main_domain)
288         {
289             /* The first word from wakeup address must be SP */
290             g_wakeupEntry[0] = ((uint32_t)&m_warmboot_stack_end);
291 
292             /* The second word from wakeup address must be PC. */
293             g_wakeupEntry[1] = (uint32_t)PM_DEV_WakeupFunction;
294 
295             for (uint32_t i = 2UL; i < 12UL; i++)
296             {
297                 g_wakeupEntry[i] = i;
298             }
299             /* Set wake up address. */
300             SPC_SetWakeUpValue(SPC0, (uint32_t)g_wakeupEntry);
301 
302             /* Don't spend time for crc calculation if crc value is already done, fields are unchanged */
303             if (crcResult == 0UL)
304             {
305                 crc_config_t config;
306                 config.polynomial         = 0x04C11DB7U;
307                 config.seed               = 0xFFFFFFFFU;
308                 config.reflectIn          = false;
309                 config.reflectOut         = false;
310                 config.complementChecksum = false;
311                 config.crcBits            = kCrcBits32;
312                 config.crcResult          = kCrcFinalChecksum;
313 
314                 /* Need to disable clock before CRC_init() to prevent hardfault when going to lowpower */
315                 CLOCK_DisableClock(kCLOCK_Crc0);
316                 CRC_Init(CRC0, &config);
317                 CRC_WriteData(CRC0, (const uint8_t *)((uint32_t)g_wakeupEntry), 48);
318                 crcResult = CRC_Get32bitResult(CRC0);
319             }
320             REGFILE1->REG[0] = crcResult;
321 
322             PM_DEV_SaveRuntimeContext();
323             if (setjmp(g_coreContext) == 0)
324             {
325                 CMC_EnterLowPowerMode(CMC0, &g_mainWakePDConfig);
326             }
327             PM_DEV_RestoreRuntimeContext();
328         }
329     }
330     /* Note: Reconfigure CMC and clear SCR SLEEPDEEP bit to
331      * avoid soc low power when a WFI instruction is called. */
332     CMC_SetClockMode(CMC0, kCMC_GateNoneClock);
333     CMC_SetMAINPowerMode(CMC0, kCMC_ActiveMode);
334     CMC_SetWAKEPowerMode(CMC0, kCMC_ActiveMode);
335     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
336     __DSB();
337 }
338 
PM_DEV_CleanExitLowPowerMode(void)339 static void PM_DEV_CleanExitLowPowerMode(void)
340 {
341     if ((SPC_CheckPowerDomainLowPowerRequest(SPC0, kSPC_PowerDomain0) == true) &&
342         (SPC_GetPowerDomainLowPowerMode(SPC0, kSPC_PowerDomain0) >= kSPC_PowerDownWithSysClockOff))
343     {
344         /*
345          * $Line Coverage Justification$
346          * $ref pm_device_c_ref_2$.
347          */
348         /* We need to release IO isolation when exiting from Power Down mode
349          * This is done here after all peripherals have been reinitialized, to
350          * avoid any glitch on IOs */
351         SPC_ClearPeriphIOIsolationFlag(SPC0);
352     }
353 
354     /* Clear SPC LP request status for next low power phase
355      * The clean up API has been added because the modules registered to notification
356      * could need to read some status registers (like the following one for PM_DEV)
357      * so we don't want a specific module to handle the clear of those status
358      * as it could lead to some modules missing the status information
359      * (depending on the notification order).
360      * So this API is meant to clear everything needed for the platform once
361      * every module got notified. */
362     SPC_ClearPowerDomainLowPowerRequestFlag(SPC0, kSPC_PowerDomain0);
363     SPC_ClearPowerDomainLowPowerRequestFlag(SPC0, kSPC_PowerDomain1);
364     SPC_ClearPowerDomainLowPowerRequestFlag(SPC0, kSPC_PowerDomain2);
365 }
366 
PM_DEV_FindOperateMode(uint32_t rescIndex,pm_resc_group_t * pSysRescGroup)367 static uint8_t PM_DEV_FindOperateMode(uint32_t rescIndex, pm_resc_group_t *pSysRescGroup)
368 {
369     assert(pSysRescGroup);
370     uint32_t u32Tmp = (pSysRescGroup->groupSlice[rescIndex / 8UL] >> (4UL * (rescIndex % 8UL))) & 0xFUL;
371 
372     u32Tmp |= (u32Tmp >> 1UL);
373     u32Tmp |= (u32Tmp >> 2UL);
374 
375     return (uint8_t)(((u32Tmp + 1UL) >> 1UL));
376 }
377 
PM_DEV_EnableBasicResources(pm_resc_mask_t * pSoftRescMask,pm_resc_group_t * pSysRescGroup)378 static void PM_DEV_EnableBasicResources(pm_resc_mask_t *pSoftRescMask, pm_resc_group_t *pSysRescGroup)
379 {
380     assert(pSoftRescMask);
381     assert(pSysRescGroup);
382 
383     uint32_t i     = 0UL;
384     uint8_t opMode = PM_RESOURCE_OFF;
385 
386     for (i = 0UL; i < PM_RESOURCE_DB_COUNT; i++)
387     {
388         if ((pSoftRescMask->rescMask[i / 32UL] & (1UL << (i % 32UL))) != 0UL)
389         {
390             opMode = PM_DEV_FindOperateMode(i, pSysRescGroup);
391             resourceDB[i].resourceConfigFunc(opMode, &resourceDB[i]);
392         }
393     }
394 }
395 
PM_DEV_SetRAMOperateMode(uint8_t operateMode,pm_dev_resource_recode_t * pResourceRecode)396 static void PM_DEV_SetRAMOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode)
397 {
398     assert(pResourceRecode);
399 
400     uint8_t tmp8;
401     uint8_t sramId;
402 
403     tmp8 = pResourceRecode->defaultOperateMode;
404     if (operateMode != tmp8)
405     {
406         tmp8 = operateMode;
407     }
408 
409     sramId = pResourceRecode - resourceDB;
410 
411     switch (tmp8)
412     {
413         case PM_RESOURCE_FULL_ON:
414         {
415             CMC_PowerOnSRAMAllMode(CMC0, 1U << sramId);
416             CMC_PowerOnSRAMLowPowerOnly(CMC0, 1U << sramId);
417             break;
418         }
419 
420         case PM_RESOURCE_PARTABLE_ON1:
421         {
422             CMC_PowerOnSRAMAllMode(CMC0, 1U << sramId);
423             CMC_PowerOffSRAMLowPowerOnly(CMC0, 1U << sramId);
424             break;
425         }
426 
427         /*
428          * $Line Coverage Justification$
429          * $ref pm_device_c_ref_3$.
430          */
431         case PM_RESOURCE_OFF:
432         {
433             CMC_PowerOnSRAMLowPowerOnly(CMC0, 1U << sramId);
434             CMC_PowerOffSRAMAllMode(CMC0, 1U << sramId);
435             break;
436         }
437 
438         /*
439          * $Line Coverage Justification$
440          * $ref pm_device_c_ref_1$.
441          */
442         default:
443         {
444             /* This branch will never be hit. */
445             break;
446         }
447     }
448     pResourceRecode->currentOperateMode = tmp8;
449 }
450 
PM_DEV_SetFro192MOperateMode(uint8_t operateMode,pm_dev_resource_recode_t * pResourceRecode)451 static void PM_DEV_SetFro192MOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode)
452 {
453     assert(pResourceRecode);
454 
455     uint8_t tmp8;
456 
457     tmp8 = pResourceRecode->defaultOperateMode;
458 
459     if (operateMode != tmp8)
460     {
461         tmp8 = operateMode;
462     }
463 
464     if (tmp8 == PM_RESOURCE_FULL_ON)
465     {
466         SCG0->FIRCCSR |= SCG_FIRCCSR_FIRCSTEN_MASK;
467     }
468     else
469     {
470         SCG0->FIRCCSR &= ~SCG_FIRCCSR_FIRCSTEN_MASK;
471     }
472 
473     pResourceRecode->currentOperateMode = tmp8;
474 }
475 
PM_DEV_SetFro6MOperateMode(uint8_t operateMode,pm_dev_resource_recode_t * pResourceRecode)476 static void PM_DEV_SetFro6MOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode)
477 {
478     assert(pResourceRecode);
479 
480     uint8_t tmp8;
481 
482     tmp8 = pResourceRecode->defaultOperateMode;
483 
484     if (operateMode != tmp8)
485     {
486         tmp8 = operateMode;
487     }
488 
489     if (tmp8 == PM_RESOURCE_FULL_ON)
490     {
491         SCG0->SIRCCSR |= SCG_SIRCCSR_SIRCSTEN_MASK;
492     }
493     else
494     {
495         SCG0->SIRCCSR &= ~SCG_SIRCCSR_SIRCSTEN_MASK;
496     }
497 
498     pResourceRecode->currentOperateMode = tmp8;
499 }
500 
PM_DEV_SetWakePowerDomainOperateMode(uint8_t operateMode,pm_dev_resource_recode_t * pResourceRecode)501 static void PM_DEV_SetWakePowerDomainOperateMode(uint8_t operateMode, pm_dev_resource_recode_t *pResourceRecode)
502 {
503     if (operateMode == PM_RESOURCE_FULL_ON)
504     {
505         g_mainWakePDConfig.wake_domain = kCMC_ActiveMode;
506     }
507     else if (operateMode == PM_RESOURCE_PARTABLE_ON2)
508     {
509         if (g_mainWakePDConfig.main_domain >= kCMC_SleepMode)
510         {
511             g_mainWakePDConfig.wake_domain = kCMC_SleepMode;
512         }
513     }
514     /*
515      * $Branch Coverage Justification$
516      * PM_DEV does not provided the software method to power off WAKE power domain.
517      */
518     else if (operateMode == PM_RESOURCE_PARTABLE_ON1)
519     {
520         if (g_mainWakePDConfig.main_domain >= kCMC_DeepSleepMode)
521         {
522             g_mainWakePDConfig.wake_domain = kCMC_DeepSleepMode;
523         }
524     }
525     else
526     {
527         /* MISRA C-2012 rule 15.7 */
528     }
529 
530     pResourceRecode->currentOperateMode = operateMode;
531 }
532 
PM_DEV_WakeupFunction(void)533 static void PM_DEV_WakeupFunction(void)
534 {
535     /*
536      * $Line Coverage Justification$
537      * $ref pm_device_c_ref_2$
538      */
539     WDOG0->CS    = (uint32_t)((WDOG0->CS) & ~WDOG_CS_EN_MASK);
540     WDOG0->TOVAL = 0xFFFF;
541 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
542     SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2));    /* set CP10, CP11 Full Access in Secure mode */
543 #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
544     SCB_NS->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access in Non-secure mode */
545 #endif                                                    /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
546 #endif                                                    /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
547 
548     /* Restore the CONTROL register. */
549     __set_CONTROL(g_cpuControl);
550     longjmp(g_coreContext, (int32_t) true);
551 }
552 
PM_DEV_SaveRuntimeContext(void)553 static void PM_DEV_SaveRuntimeContext(void)
554 {
555     uint32_t i = 0UL;
556 
557     g_scbVtor  = SCB->VTOR;
558     g_scbIcsr  = SCB->ICSR;
559     g_scbAircr = ((SCB->AIRCR) & ~SCB_AIRCR_VECTKEY_Msk) | (0x5FAUL << (uint32_t)SCB_AIRCR_VECTKEY_Pos);
560     g_scbCCR   = SCB->CCR;
561     for (i = 0UL; i < 12UL; i++)
562     {
563         g_scbShp[i] = SCB->SHPR[i];
564     }
565     g_scbShcsr = SCB->SHCSR;
566     for (i = 0UL; i < 16U; i++)
567     {
568         g_nvicIser[i] = NVIC->ISER[i];
569     }
570     for (i = 0UL; i < 496UL; i++)
571     {
572         g_nvicIp[i] = NVIC->IPR[i];
573     }
574     g_cpuControl  = __get_CONTROL();
575     g_systickCtrl = SysTick->CTRL;
576     g_systickLoad = SysTick->LOAD;
577 }
578 
PM_DEV_RestoreRuntimeContext(void)579 static void PM_DEV_RestoreRuntimeContext(void)
580 {
581     uint32_t i;
582 
583     SCB->VTOR  = g_scbVtor;
584     SCB->ICSR  = g_scbIcsr;
585     SCB->AIRCR = g_scbAircr;
586     SCB->CCR   = g_scbCCR;
587     for (i = 0UL; i < 12UL; i++)
588     {
589         SCB->SHPR[i] = g_scbShp[i];
590     }
591     SCB->SHCSR = g_scbShcsr;
592     for (i = 0UL; i < 16UL; i++)
593     {
594         NVIC->ISER[i] = g_nvicIser[i];
595     }
596     for (i = 0UL; i < 496UL; i++)
597     {
598         NVIC->IPR[i] = g_nvicIp[i];
599     }
600     SysTick->CTRL = g_systickCtrl;
601     SysTick->LOAD = g_systickLoad;
602 }
603 
604 #if (defined(FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER) && FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER)
PM_DEV_ManageWakeupSource(pm_wakeup_source_t * ws,bool enable)605 static status_t PM_DEV_ManageWakeupSource(pm_wakeup_source_t *ws, bool enable)
606 {
607     assert(ws);
608 
609     uint32_t inputType;
610     uint32_t inputId;
611     uint32_t irqn;
612     uint32_t misc;
613 
614     PM_DECODE_WAKEUP_SOURCE_ID(ws->wsId);
615 
616     if (inputType == 0UL)
617     {
618         /* Wakeup source is external pin. */
619         wuu_external_wakeup_pin_config_t pinConfig;
620 
621         pinConfig.edge  = enable ? (wuu_external_pin_edge_detection_t)misc : kWUU_ExternalPinDisable;
622         pinConfig.event = kWUU_ExternalPinInterrupt;
623         pinConfig.mode  = kWUU_ExternalPinActiveDSPD;
624 
625         WUU_SetExternalWakeUpPinsConfig(WUU0, (uint8_t)inputId, &pinConfig);
626 
627         if (enable)
628         {
629             (void)EnableIRQ((IRQn_Type)irqn);
630             (void)EnableIRQ(WUU0_IRQn);
631         }
632         else
633         {
634             (void)DisableIRQ((IRQn_Type)irqn);
635             (void)DisableIRQ(WUU0_IRQn);
636         }
637     }
638     else
639     {
640         if (enable)
641         {
642             /* Wakeup source is internal module. */
643             (void)EnableIRQ(WUU0_IRQn);
644             WUU_SetInternalWakeUpModulesConfig(WUU0, (uint8_t)inputId, kWUU_InternalModuleInterrupt);
645             (void)EnableIRQ((IRQn_Type)irqn);
646         }
647         else
648         {
649             WUU0->ME &= ~(1UL << inputId);
650             (void)DisableIRQ((IRQn_Type)irqn);
651             (void)DisableIRQ(WUU0_IRQn);
652         }
653     }
654 
655     return kStatus_Success;
656 }
657 
PM_DEV_IsWakeupSource(pm_wakeup_source_t * ws)658 static bool PM_DEV_IsWakeupSource(pm_wakeup_source_t *ws)
659 {
660     uint32_t inputType;
661     uint32_t inputId;
662     uint32_t irqn;
663     uint32_t misc;
664     uint32_t wuuPf;
665     uint32_t mask;
666     bool ret = false;
667 
668     assert(ws != NULL);
669 
670     PM_DECODE_WAKEUP_SOURCE_ID(ws->wsId);
671 
672     /* Wakeup source is external pin. */
673     if (inputType == 0UL)
674     {
675         wuuPf = WUU_GetExternalWakeUpPinsFlag(WUU0);
676         mask  = (1UL << inputId) & WUU_PIN_FLAG_MASK;
677 
678         if ((wuuPf & mask) != 0UL)
679         {
680             /*
681              * $Line Coverage Justification$
682              * $ref pm_device_c_ref_2$.
683              */
684             /* This wake up source triggered the last wake up */
685             ret = true;
686         }
687     }
688 
689     (void)irqn;
690     (void)misc;
691 
692     return ret;
693 }
694 #endif /* FSL_PM_SUPPORT_WAKEUP_SOURCE_MANAGER */
695