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