1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2018, 2020-2021 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef _FSL_POWER_H_
9 #define _FSL_POWER_H_
10 
11 #include "fsl_common.h"
12 
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /*!
18  * @addtogroup power
19  * @{
20  */
21 
22 /*! @name Driver version */
23 /*@{*/
24 /*! @brief power driver version 2.1.0. */
25 #define FSL_POWER_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
26 /*@}*/
27 
28 /*! @brief PMU PCON reserved mask, used to clear reserved field which should not write 1*/
29 #define PMUC_PCON_RESERVED_MASK ((0xf << 4) | (0x6 << 8) | 0xfffff000u)
30 
31 #define POWER_EnbaleLPO                    POWER_EnableLPO
32 #define POWER_EnbaleLPOInDeepPowerDownMode POWER_EnableLPOInDeepPowerDownMode
33 
34 /*! @brief power down configurations mask */
35 typedef enum pd_bits
36 {
37     kPDRUNCFG_PD_FRO_OUT = SYSCON_PDRUNCFG_FROOUT_PD_MASK,
38     kPDRUNCFG_PD_FRO     = SYSCON_PDRUNCFG_FRO_PD_MASK,
39     kPDRUNCFG_PD_FLASH   = SYSCON_PDRUNCFG_FLASH_PD_MASK,
40     kPDRUNCFG_PD_BOD     = SYSCON_PDRUNCFG_BOD_PD_MASK,
41     kPDRUNCFG_PD_ADC0    = SYSCON_PDRUNCFG_ADC_PD_MASK,
42     kPDRUNCFG_PD_SYSOSC  = SYSCON_PDRUNCFG_SYSOSC_PD_MASK,
43     kPDRUNCFG_PD_LPO_OSC = SYSCON_PDRUNCFG_LPOSC_PD_MASK,
44     kPDRUNCFG_PD_SYSPLL  = SYSCON_PDRUNCFG_SYSPLL_PD_MASK,
45     kPDRUNCFG_PD_ACMP    = SYSCON_PDRUNCFG_ACMP_MASK,
46 
47     /*
48     This enum member has no practical meaning,it is used to avoid MISRA issue,
49     user should not trying to use it.
50     */
51     kPDRUNCFG_ForceUnsigned = (int)0x80000000U,
52 } pd_bit_t;
53 
54 /*! @brief Deep sleep and power down mode wake up configurations */
55 enum _power_wakeup
56 {
57     kPDAWAKECFG_Wakeup_FRO_OUT = SYSCON_PDAWAKECFG_FROOUT_PD_MASK,
58     kPDAWAKECFG_Wakeup_FRO     = SYSCON_PDAWAKECFG_FRO_PD_MASK,
59     kPDAWAKECFG_Wakeup_FLASH   = SYSCON_PDAWAKECFG_FLASH_PD_MASK,
60     kPDAWAKECFG_Wakeup_BOD     = SYSCON_PDAWAKECFG_BOD_PD_MASK,
61     kPDAWAKECFG_Wakeup_ADC     = SYSCON_PDAWAKECFG_ADC_PD_MASK,
62     kPDAWAKECFG_Wakeup_SYSOSC  = SYSCON_PDAWAKECFG_SYSOSC_PD_MASK,
63     kPDAWAKECFG_Wakeup_LP_OSC  = SYSCON_PDAWAKECFG_LPOSC_PD_MASK,
64     kPDAWAKECFG_Wakeup_ACMP    = SYSCON_PDAWAKECFG_ACMP_MASK,
65 };
66 
67 /*! @brief Deep sleep/power down mode active part */
68 enum _power_deep_sleep_active
69 {
70     kPDSLEEPCFG_DeepSleepBODActive   = SYSCON_PDSLEEPCFG_BOD_PD_MASK,
71     kPDSLEEPCFG_DeepSleepLPOscActive = SYSCON_PDSLEEPCFG_LPOSC_PD_MASK,
72 };
73 
74 /*! @brief pmu general purpose register index */
75 typedef enum _power_gen_reg
76 {
77     kPmu_GenReg0 = 0U, /*!< general purpose register0 */
78     kPmu_GenReg1 = 1U, /*!< general purpose register1 */
79     kPmu_GenReg2 = 2U, /*!< general purpose register2 */
80     kPmu_GenReg3 = 3U, /*!< general purpose register3 */
81     kPmu_GenReg4 = 4U, /*!< DPDCTRL bit 31-8 */
82 } power_gen_reg_t;
83 
84 /* Power mode configuration API parameter */
85 typedef enum _power_mode_config
86 {
87     kPmu_Sleep          = 0U,
88     kPmu_Deep_Sleep     = 1U,
89     kPmu_PowerDown      = 2U,
90     kPmu_Deep_PowerDown = 3U,
91 } power_mode_cfg_t;
92 
93 /*!
94  * @brief BOD reset level, if VDD below reset level value, the reset will be
95  * asserted.
96  */
97 typedef enum _power_bod_reset_level
98 {
99     kBod_ResetLevelReserved = 0U, /*!< BOD Reset Level reserved. */
100     kBod_ResetLevel1,             /*!< BOD Reset Level1: 2.05V */
101     kBod_ResetLevel2,             /*!< BOD Reset Level2: 2.35V */
102     kBod_ResetLevel3,             /*!< BOD Reset Level3: 2.63V */
103 } power_bod_reset_level_t;
104 
105 /*!
106  * @brief BOD interrupt level, if VDD below interrupt level value, the BOD interrupt
107  * will be asserted.
108  */
109 typedef enum _power_bod_interrupt_level
110 {
111     kBod_InterruptLevelReserved = 0U, /*!< BOD interrupt level reserved. */
112     kBod_InterruptLevel1,             /*!< BOD interrupt level1: 2.25V. */
113     kBod_InterruptLevel2,             /*!< BOD interrupt level2: 2.55V. */
114     kBod_InterruptLevel3,             /*!< BOD interrupt level3: 2.84V. */
115 } power_bod_interrupt_level_t;
116 
117 /*******************************************************************************
118  * API
119  ******************************************************************************/
120 
121 #ifdef __cplusplus
122 extern "C" {
123 #endif
124 
125 /*!
126  * @name SYSCON Power Configuration
127  * @{
128  */
129 
130 /*!
131  * @brief API to enable PDRUNCFG bit in the Syscon. Note that enabling the bit powers down the peripheral
132  *
133  * @param en    peripheral for which to enable the PDRUNCFG bit
134  * @return none
135  */
POWER_EnablePD(pd_bit_t en)136 static inline void POWER_EnablePD(pd_bit_t en)
137 {
138     SYSCON->PDRUNCFG |= (uint32_t)en;
139 }
140 
141 /*!
142  * @brief API to disable PDRUNCFG bit in the Syscon. Note that disabling the bit powers up the peripheral
143  *
144  * @param en    peripheral for which to disable the PDRUNCFG bit
145  * @return none
146  */
POWER_DisablePD(pd_bit_t en)147 static inline void POWER_DisablePD(pd_bit_t en)
148 {
149     SYSCON->PDRUNCFG &= ~(uint32_t)en;
150 }
151 
152 /*!
153  * @brief API to config wakeup configurations for deep sleep mode and power down mode.
154  *
155  * @param mask: wake up configurations for deep sleep mode and power down mode, reference _power_wakeup.
156  * @param powerDown: true is power down the mask part, false is powered part.
157  */
POWER_WakeUpConfig(uint32_t mask,bool powerDown)158 static inline void POWER_WakeUpConfig(uint32_t mask, bool powerDown)
159 {
160     if (powerDown)
161     {
162         SYSCON->PDAWAKECFG |= mask;
163     }
164     else
165     {
166         SYSCON->PDAWAKECFG &= ~mask;
167     }
168 }
169 
170 /*!
171  * @brief API to config active part for deep sleep mode and power down mode.
172  *
173  * @param mask: active part configurations for deep sleep mode and power down mode, reference _power_deep_sleep_active.
174  * @param powerDown: true is power down the mask part, false is powered part.
175  */
POWER_DeepSleepConfig(uint32_t mask,bool powerDown)176 static inline void POWER_DeepSleepConfig(uint32_t mask, bool powerDown)
177 {
178     if (powerDown)
179     {
180         SYSCON->PDSLEEPCFG |= mask;
181     }
182     else
183     {
184         SYSCON->PDSLEEPCFG &= ~mask;
185     }
186 }
187 
188 /* @} */
189 
190 /*!
191  * @name ARM core Power Configuration
192  * @{
193  */
194 
195 /*!
196  * @brief API to enable deep sleep bit in the ARM Core.
197  *
198  * @return none
199  */
POWER_EnableDeepSleep(void)200 static inline void POWER_EnableDeepSleep(void)
201 {
202     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
203 }
204 
205 /*!
206  * @brief API to disable deep sleep bit in the ARM Core.
207  *
208  * @return none
209  */
POWER_DisableDeepSleep(void)210 static inline void POWER_DisableDeepSleep(void)
211 {
212     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
213 }
214 
215 /* @} */
216 
217 /*!
218  * @name PMU functionality
219  * @{
220  */
221 
222 /*!
223  * @brief API to enter sleep power mode.
224  *
225  * @return none
226  */
227 void POWER_EnterSleep(void);
228 
229 /*!
230  * @brief API to enter deep sleep power mode.
231  *
232  * @param activePart: should be a single or combine value of _power_deep_sleep_active .
233  * @return none
234  */
235 void POWER_EnterDeepSleep(uint32_t activePart);
236 
237 /*!
238  * @brief API to enter power down mode.
239  *
240  * @param activePart: should be a single or combine value of _power_deep_sleep_active .
241  * @return none
242  */
243 void POWER_EnterPowerDown(uint32_t activePart);
244 
245 /*!
246  * @brief API to enter deep power down mode.
247  *
248  * @return none
249  */
250 void POWER_EnterDeepPowerDownMode(void);
251 
252 /*!
253  * @brief API to get sleep mode flag.
254  *
255  * @return sleep mode flag: 0 is active mode, 1 is sleep mode entered.
256  */
POWER_GetSleepModeFlag(void)257 static inline uint32_t POWER_GetSleepModeFlag(void)
258 {
259     return (PMU->PCON & PMU_PCON_SLEEPFLAG_MASK) >> PMU_PCON_SLEEPFLAG_SHIFT;
260 }
261 
262 /*!
263  * @brief API to clear sleep mode flag.
264  *
265  */
POWER_ClrSleepModeFlag(void)266 static inline void POWER_ClrSleepModeFlag(void)
267 {
268     PMU->PCON |= PMU_PCON_SLEEPFLAG_MASK;
269 }
270 
271 /*!
272  * @brief API to get deep power down mode flag.
273  *
274  * @return sleep mode flag: 0 not deep power down, 1 is deep power down mode entered.
275  */
POWER_GetDeepPowerDownModeFlag(void)276 static inline uint32_t POWER_GetDeepPowerDownModeFlag(void)
277 {
278     return (PMU->PCON & PMU_PCON_DPDFLAG_MASK) >> PMU_PCON_DPDFLAG_SHIFT;
279 }
280 
281 /*!
282  * @brief API to clear deep power down mode flag.
283  *
284  */
POWER_ClrDeepPowerDownModeFlag(void)285 static inline void POWER_ClrDeepPowerDownModeFlag(void)
286 {
287     PMU->PCON |= PMU_PCON_DPDFLAG_MASK;
288 }
289 
290 /*!
291  * @brief API to enable non deep power down mode.
292  *
293  * @param enable: true is enable non deep power down, otherwise disable.
294  */
POWER_EnableNonDpd(bool enable)295 static inline void POWER_EnableNonDpd(bool enable)
296 {
297     if (enable)
298     {
299         PMU->PCON |= PMU_PCON_NODPD_MASK;
300     }
301     else
302     {
303         PMU->PCON &= ~PMU_PCON_NODPD_MASK;
304     }
305 }
306 
307 /*!
308  * @brief API to enable LPO.
309  *
310  * @param enable: true to enable LPO, false to disable LPO.
311  */
POWER_EnableLPO(bool enable)312 static inline void POWER_EnableLPO(bool enable)
313 {
314     if (enable)
315     {
316         PMU->DPDCTRL |= PMU_DPDCTRL_ULPOSCEN_MASK;
317     }
318     else
319     {
320         PMU->DPDCTRL &= ~PMU_DPDCTRL_ULPOSCEN_MASK;
321     }
322 }
323 
324 /*!
325  * @brief API to enable LPO in deep power down mode.
326  *
327  * @param enable: true to enable LPO, false to disable LPO.
328  */
POWER_EnableLPOInDeepPowerDownMode(bool enable)329 static inline void POWER_EnableLPOInDeepPowerDownMode(bool enable)
330 {
331     if (enable)
332     {
333         PMU->DPDCTRL |= PMU_DPDCTRL_ULPOSCDPDEN_MASK;
334     }
335     else
336     {
337         PMU->DPDCTRL &= ~PMU_DPDCTRL_ULPOSCDPDEN_MASK;
338     }
339 }
340 
341 /*!
342  * @brief API to retore data to general purpose register which can be retain during deep power down mode.
343  * Note the kPMU_GenReg4 can retore 3 byte data only, so the general purpose register can store 19bytes data.
344  * @param index: general purpose data register index.
345  * @param data: data to restore.
346  */
POWER_SetRetainData(power_gen_reg_t index,uint32_t data)347 static inline void POWER_SetRetainData(power_gen_reg_t index, uint32_t data)
348 {
349     if (index <= kPmu_GenReg3)
350     {
351         PMU->GPREG[index] = data;
352     }
353     else
354     {
355         /* only three byte can store in GPDATA field */
356         PMU->DPDCTRL = (PMU->DPDCTRL & (~PMU_DPDCTRL_GPDATA_MASK)) | PMU_DPDCTRL_GPDATA(data);
357     }
358 }
359 
360 /*!
361  * @brief API to get data from general purpose register which retain during deep power down mode.
362  * Note the kPMU_GenReg4 can retore 3 byte data only, so the general purpose register can store 19bytes data.
363  * @param index: general purpose data register index.
364  * @return data stored in the general purpose register.
365  */
POWER_GetRetainData(power_gen_reg_t index)366 static inline uint32_t POWER_GetRetainData(power_gen_reg_t index)
367 {
368     if (index == kPmu_GenReg4)
369     {
370         return (PMU->DPDCTRL & PMU_DPDCTRL_GPDATA_MASK) >> PMU_DPDCTRL_GPDATA_SHIFT;
371     }
372 
373     return PMU->GPREG[index];
374 }
375 
376 /*!
377  * @brief API to enable external clock input for self wake up timer.
378  *
379  * @param enable: true is enable external clock input for self-wake-up timer, otherwise disable.
380  * @param enHysteresis: true is enable Hysteresis for the pin, otherwise disable.
381  */
POWER_EnableWktClkIn(bool enable,bool enHysteresis)382 static inline void POWER_EnableWktClkIn(bool enable, bool enHysteresis)
383 {
384     PMU->DPDCTRL = (PMU->DPDCTRL & (~(PMU_DPDCTRL_WAKEUPCLKHYS_MASK | PMU_DPDCTRL_WAKECLKPAD_DISABLE_MASK))) |
385                    PMU_DPDCTRL_WAKECLKPAD_DISABLE(enable) | PMU_DPDCTRL_WAKEUPCLKHYS(enHysteresis);
386 }
387 
388 /*!
389  * @brief API to enable wake up pin for deep power down mode.
390  *
391  * @param enable: true is enable, otherwise disable.
392  * @param enHysteresis: true is enable Hysteresis for the pin, otherwise disable.
393  */
POWER_EnableWakeupPinForDeepPowerDown(bool enable,bool enHysteresis)394 static inline void POWER_EnableWakeupPinForDeepPowerDown(bool enable, bool enHysteresis)
395 {
396     PMU->DPDCTRL = (PMU->DPDCTRL & (~(PMU_DPDCTRL_WAKEUPHYS_MASK | PMU_DPDCTRL_WAKEPAD_DISABLE_MASK))) |
397                    PMU_DPDCTRL_WAKEPAD_DISABLE(!enable) | PMU_DPDCTRL_WAKEUPHYS(enHysteresis);
398 }
399 
400 /*!
401  * @brief API to enable external clock input for self wake up timer.
402  *
403  * @param enable: true is enable , otherwise disable.
404  * @param enHysteresis: true is enable Hysteresis for the pin, otherwise disable.
405  */
POWER_EnableResetPinForDeepPowerDown(bool enable,bool enHysteresis)406 static inline void POWER_EnableResetPinForDeepPowerDown(bool enable, bool enHysteresis)
407 {
408     PMU->DPDCTRL = (PMU->DPDCTRL & (~(PMU_DPDCTRL_RESETHYS_MASK | PMU_DPDCTRL_RESET_DISABLE_MASK))) |
409                    PMU_DPDCTRL_RESET_DISABLE(!enable) | PMU_DPDCTRL_RESETHYS(enHysteresis);
410 }
411 
412 /*!
413  * @brief Set Bod interrupt level and reset level.
414  *
415  * @param resetLevel BOD reset threshold level, please refer to @ref power_bod_reset_level_t.
416  * @param interruptLevel BOD interrupt threshold level, please refer to @ref power_bod_interrupt_level_t.
417  * @param enable Used to enable/disable the BOD interrupt and BOD reset.
418  */
POWER_SetBodLevel(power_bod_reset_level_t resetLevel,power_bod_interrupt_level_t interruptLevel,bool enable)419 static inline void POWER_SetBodLevel(power_bod_reset_level_t resetLevel,
420                                      power_bod_interrupt_level_t interruptLevel,
421                                      bool enable)
422 {
423     SYSCON->BODCTRL = SYSCON_BODCTRL_BODRSTLEV(resetLevel) | SYSCON_BODCTRL_BODINTVAL(interruptLevel) |
424                       SYSCON_BODCTRL_BODRSTENA(enable);
425 }
426 /* @} */
427 
428 #ifdef __cplusplus
429 }
430 #endif
431 
432 /*!
433  * @}
434  */
435 
436 #endif /* _FSL_POWER_H_ */
437