1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2018, NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #include "fsl_power.h"
9 /* Component ID definition, used by tools. */
10 #ifndef FSL_COMPONENT_ID
11 #define FSL_COMPONENT_ID "platform.drivers.power_no_lib"
12 #endif
13 
14 /*******************************************************************************
15  * Code
16  ******************************************************************************/
17 /*!
18  * brief API to enter sleep power mode.
19  *
20  * return none
21  */
POWER_EnterSleep(void)22 void POWER_EnterSleep(void)
23 {
24     uint32_t pmsk;
25 
26     pmsk = __get_PRIMASK();
27     __disable_irq();
28 
29     /* sleep mode */
30     PMU->PCON &= ~PMU_PCON_PM_MASK;
31     /* disable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
32     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
33 
34     /* Enter powerdown mode */
35     __WFI();
36 
37     __set_PRIMASK(pmsk);
38 }
39 
40 /*!
41  * brief API to enter deep sleep power mode.
42  *
43  * param activePart: should be a single or combine value of _power_deep_sleep_active .
44  * return none
45  */
POWER_EnterDeepSleep(uint32_t activePart)46 void POWER_EnterDeepSleep(uint32_t activePart)
47 {
48     assert((SYSCON->MAINCLKSEL & SYSCON_MAINCLKSEL_SEL_MASK) == 0U);
49 
50     uint32_t pmsk;
51 
52     pmsk = __get_PRIMASK();
53     __disable_irq();
54 
55     PMU->PCON = (PMU->PCON & (~PMU_PCON_PM_MASK)) | PMU_PCON_PM(kPmu_Deep_Sleep);
56 
57     /* remain active during power down mode */
58     SYSCON->PDSLEEPCFG &= ~activePart;
59 
60     /* enable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
61     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
62 
63     /* Enter powerdown mode */
64     __WFI();
65 
66     /* disable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
67     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
68     __set_PRIMASK(pmsk);
69 }
70 
71 /*!
72  * brief API to enter power down mode.
73  *
74  * param activePart: should be a single or combine value of _power_deep_sleep_active .
75  * return none
76  */
POWER_EnterPowerDown(uint32_t activePart)77 void POWER_EnterPowerDown(uint32_t activePart)
78 {
79     assert((SYSCON->MAINCLKSEL & SYSCON_MAINCLKSEL_SEL_MASK) == 0U);
80 
81     uint32_t pmsk;
82 
83     pmsk = __get_PRIMASK();
84     __disable_irq();
85 
86     PMU->PCON = (PMU->PCON & (~PMU_PCON_PM_MASK)) | PMU_PCON_PM(kPmu_PowerDown);
87 
88     /* remain active during power down mode */
89     SYSCON->PDSLEEPCFG &= ~activePart;
90 
91     /* enable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
92     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
93 
94     /* Enter powerdown mode */
95     __WFI();
96 
97     /* disable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
98     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
99     __set_PRIMASK(pmsk);
100 }
101 
102 /*!
103  * brief API to enter deep power down mode.
104  *
105  * return none
106  */
POWER_EnterDeepPowerDownMode(void)107 void POWER_EnterDeepPowerDownMode(void)
108 {
109     uint32_t pmsk;
110 
111     pmsk = __get_PRIMASK();
112     __disable_irq();
113 
114     /* make sure NODPD is cleared  */
115     PMU->PCON = (PMU->PCON & (~(PMU_PCON_PM_MASK | PMU_PCON_NODPD_MASK))) | PMU_PCON_PM(kPmu_Deep_PowerDown);
116 
117     /* enable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
118     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
119 
120     /* Enter powerdown mode */
121     __WFI();
122 
123     /* disable Deepsleep mode in the ARM-CORTEX M0+ SCR register */
124     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
125     __set_PRIMASK(pmsk);
126 }
127 
EnableDeepSleepIRQ(IRQn_Type interrupt)128 void EnableDeepSleepIRQ(IRQn_Type interrupt)
129 {
130     uint32_t intNumber = (uint32_t)interrupt;
131 
132     if(intNumber >= 24u)
133     {
134         /* enable pin interrupt wake up in the STARTERP0 register */
135         SYSCON->STARTERP0 |= 1UL << (intNumber - 24u);
136     }
137     else
138     {
139         /* enable interrupt wake up in the STARTERP1 register */
140         SYSCON->STARTERP1 |= 1UL << intNumber;
141     }
142     /* also enable interrupt at NVIC */
143     (void)EnableIRQ(interrupt);
144 }
145 
DisableDeepSleepIRQ(IRQn_Type interrupt)146 void DisableDeepSleepIRQ(IRQn_Type interrupt)
147 {
148     uint32_t intNumber = (uint32_t)interrupt;
149 
150     /* also disable interrupt at NVIC */
151     (void)DisableIRQ(interrupt);
152 
153     if(intNumber >= 24u)
154     {
155         /* disable pin interrupt wake up in the STARTERP0 register */
156         SYSCON->STARTERP0 &= ~(1UL << (intNumber - 24u));
157     }
158     else
159     {
160         /* disable interrupt wake up in the STARTERP1 register */
161         SYSCON->STARTERP1 &= ~(1UL << intNumber);
162     }
163 }
164