1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_msmc.h"
10 
11 #if defined(__riscv)
12 #define CONFIG_NORMAL_SLEEP EVENT_UNIT->SLPCTRL = (EVENT_UNIT->SLPCTRL & ~0x03) | (1 << 0)
13 #define CONFIG_DEEP_SLEEP EVENT_UNIT->SLPCTRL |= 0x03;
14 #else
15 #define CONFIG_NORMAL_SLEEP SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk
16 #define CONFIG_DEEP_SLEEP SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk
17 #endif
18 
SMC_SetPowerModeRun(SMC_Type * base)19 status_t SMC_SetPowerModeRun(SMC_Type *base)
20 {
21     uint32_t reg;
22 
23     reg = base->PMCTRL;
24     /* configure Normal RUN mode */
25     reg &= ~SMC_PMCTRL_RUNM_MASK;
26     reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
27     base->PMCTRL = reg;
28 
29     return kStatus_Success;
30 }
31 
SMC_SetPowerModeHsrun(SMC_Type * base)32 status_t SMC_SetPowerModeHsrun(SMC_Type *base)
33 {
34     uint32_t reg;
35 
36     reg = base->PMCTRL;
37     /* configure High Speed RUN mode */
38     reg &= ~SMC_PMCTRL_RUNM_MASK;
39     reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
40     base->PMCTRL = reg;
41 
42     return kStatus_Success;
43 }
44 
SMC_SetPowerModeWait(SMC_Type * base)45 status_t SMC_SetPowerModeWait(SMC_Type *base)
46 {
47     /* configure Normal Wait mode */
48     CONFIG_NORMAL_SLEEP;
49 
50     __DSB();
51     __WFI();
52     __ISB();
53 
54     return kStatus_Success;
55 }
56 
SMC_SetPowerModeStop(SMC_Type * base,smc_partial_stop_option_t option)57 status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
58 {
59     uint32_t reg;
60 
61     /* configure the Partial Stop mode in Noraml Stop mode */
62     reg = base->PMCTRL;
63     reg &= ~(SMC_PMCTRL_PSTOPO_MASK | SMC_PMCTRL_STOPM_MASK);
64     reg |= ((uint32_t)option << SMC_PMCTRL_PSTOPO_SHIFT) | (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
65     base->PMCTRL = reg;
66 
67     /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
68     CONFIG_DEEP_SLEEP;
69 
70     /* read back to make sure the configuration valid before entering stop mode */
71     (void)base->PMCTRL;
72     __DSB();
73     __WFI();
74     __ISB();
75 
76 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
77     /* check whether the power mode enter Stop mode succeed */
78     if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
79     {
80         return kStatus_SMC_StopAbort;
81     }
82     else
83     {
84         return kStatus_Success;
85     }
86 #else
87     return kStatus_Success;
88 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
89 }
90 
SMC_SetPowerModeVlpr(SMC_Type * base)91 status_t SMC_SetPowerModeVlpr(SMC_Type *base)
92 {
93     uint32_t reg;
94 
95     reg = base->PMCTRL;
96     /* configure VLPR mode */
97     reg &= ~SMC_PMCTRL_RUNM_MASK;
98     reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
99     base->PMCTRL = reg;
100 
101     return kStatus_Success;
102 }
103 
SMC_SetPowerModeVlpw(SMC_Type * base)104 status_t SMC_SetPowerModeVlpw(SMC_Type *base)
105 {
106     /* configure VLPW mode */
107     /* Clear the SLEEPDEEP bit to disable deep sleep mode */
108     CONFIG_NORMAL_SLEEP;
109 
110     __DSB();
111     __WFI();
112     __ISB();
113 
114     return kStatus_Success;
115 }
116 
SMC_SetPowerModeVlps(SMC_Type * base)117 status_t SMC_SetPowerModeVlps(SMC_Type *base)
118 {
119     uint32_t reg;
120 
121     /* configure VLPS mode */
122     reg = base->PMCTRL;
123     reg &= ~SMC_PMCTRL_STOPM_MASK;
124     reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
125     base->PMCTRL = reg;
126 
127     /* Set the SLEEPDEEP bit to enable deep sleep mode */
128     CONFIG_DEEP_SLEEP;
129 
130     /* read back to make sure the configuration valid before enter stop mode */
131     (void)base->PMCTRL;
132     __DSB();
133     __WFI();
134     __ISB();
135 
136 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
137     /* check whether the power mode enter Stop mode succeed */
138     if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
139     {
140         return kStatus_SMC_StopAbort;
141     }
142     else
143     {
144         return kStatus_Success;
145     }
146 #else
147     return kStatus_Success;
148 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
149 }
150 
SMC_SetPowerModeLls(SMC_Type * base)151 status_t SMC_SetPowerModeLls(SMC_Type *base)
152 {
153     uint32_t reg;
154 
155     /* configure to LLS mode */
156     reg = base->PMCTRL;
157     reg &= ~SMC_PMCTRL_STOPM_MASK;
158     reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
159     base->PMCTRL = reg;
160 
161     /* Set the SLEEPDEEP bit to enable deep sleep mode */
162     CONFIG_DEEP_SLEEP;
163 
164     /* read back to make sure the configuration valid before entering stop mode */
165     (void)base->PMCTRL;
166     __DSB();
167     __WFI();
168     __ISB();
169 
170 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
171     /* check whether the power mode enter Stop mode succeed */
172     if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
173     {
174         return kStatus_SMC_StopAbort;
175     }
176     else
177     {
178         return kStatus_Success;
179     }
180 #else
181     return kStatus_Success;
182 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
183 }
184 
185 #if (defined(FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) && FSL_FEATURE_SMC_HAS_SUB_STOP_MODE)
186 
187 #if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE0)
SMC_SetPowerModeVlls0(SMC_Type * base)188 status_t SMC_SetPowerModeVlls0(SMC_Type *base)
189 {
190     uint32_t reg;
191 
192     /* configure to VLLS mode */
193     reg = base->PMCTRL;
194     reg &= ~SMC_PMCTRL_STOPM_MASK;
195     reg |= (kSMC_StopVlls0 << SMC_PMCTRL_STOPM_SHIFT);
196     base->PMCTRL = reg;
197 
198     /* Set the SLEEPDEEP bit to enable deep sleep mode */
199     CONFIG_DEEP_SLEEP;
200 
201     /* read back to make sure the configuration valid before enter stop mode */
202     (void)base->PMCTRL;
203     __DSB();
204     __WFI();
205     __ISB();
206 
207     return kStatus_Success;
208 }
209 #endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
210 
211 #if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE2)
SMC_SetPowerModeVlls2(SMC_Type * base)212 status_t SMC_SetPowerModeVlls2(SMC_Type *base)
213 {
214     uint32_t reg;
215 
216     /* configure to VLLS mode */
217     reg = base->PMCTRL;
218     reg &= ~SMC_PMCTRL_STOPM_MASK;
219     reg |= (kSMC_StopVlls2 << SMC_PMCTRL_STOPM_SHIFT);
220     base->PMCTRL = reg;
221 
222     /* Set the SLEEPDEEP bit to enable deep sleep mode */
223     CONFIG_DEEP_SLEEP;
224 
225     /* read back to make sure the configuration valid before enter stop mode */
226     (void)base->PMCTRL;
227     __DSB();
228     __WFI();
229     __ISB();
230 
231     return kStatus_Success;
232 }
233 #endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
234 
235 #else /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
SMC_SetPowerModeVlls(SMC_Type * base)236 status_t SMC_SetPowerModeVlls(SMC_Type *base)
237 {
238     uint32_t reg;
239 
240     /* configure to VLLS mode */
241     reg = base->PMCTRL;
242     reg &= ~SMC_PMCTRL_STOPM_MASK;
243     reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
244     base->PMCTRL = reg;
245 
246 #if defined(__riscv)
247     EVENT->SCR = (EVENT->SCR & ~0x03) | (1 << 1);
248 #else
249     /* Set the SLEEPDEEP bit to enable deep sleep mode */
250     CONFIG_DEEP_SLEEP;
251 #endif
252 
253     /* read back to make sure the configuration valid before enter stop mode */
254     (void)base->PMCTRL;
255     __DSB();
256     __WFI();
257     __ISB();
258 
259 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
260     /* check whether the power mode enter Stop mode succeed */
261     if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
262     {
263         return kStatus_SMC_StopAbort;
264     }
265     else
266     {
267         return kStatus_Success;
268     }
269 #else
270     return kStatus_Success;
271 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
272 }
273 #endif /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
274 
SMC_ConfigureResetPinFilter(SMC_Type * base,const smc_reset_pin_filter_config_t * config)275 void SMC_ConfigureResetPinFilter(SMC_Type *base, const smc_reset_pin_filter_config_t *config)
276 {
277     assert(config);
278 
279     uint32_t reg;
280 
281     reg = SMC_RPC_FILTCFG(config->slowClockFilterCount) | SMC_RPC_FILTEN(config->enableFilter);
282 #if (defined(FSL_FEATURE_SMC_HAS_RPC_LPOFEN) && FSL_FEATURE_SMC_HAS_RPC_LPOFEN)
283     if (config->enableLpoFilter)
284     {
285         reg |= SMC_RPC_LPOFEN_MASK;
286     }
287 #endif /* FSL_FEATURE_SMC_HAS_RPC_LPOFEN */
288 
289     base->RPC = reg;
290 }
291