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