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