1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_msmc.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.msmc"
14 #endif
15 
16 /*!
17  * brief Configure the system to RUN power mode.
18  *
19  * param base SMC peripheral base address.
20  * return SMC configuration error code.
21  */
SMC_SetPowerModeRun(SMC_Type * base)22 status_t SMC_SetPowerModeRun(SMC_Type *base)
23 {
24     uint32_t reg;
25 
26     reg = base->PMCTRL;
27     /* configure Normal RUN mode */
28     reg &= ~SMC_PMCTRL_RUNM_MASK;
29     reg |= ((uint32_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
30     base->PMCTRL = reg;
31 
32     return kStatus_Success;
33 }
34 
35 /*!
36  * brief Configure the system to HSRUN power mode.
37  *
38  * param base SMC peripheral base address.
39  * return SMC configuration error code.
40  */
SMC_SetPowerModeHsrun(SMC_Type * base)41 status_t SMC_SetPowerModeHsrun(SMC_Type *base)
42 {
43     uint32_t reg;
44 
45     reg = base->PMCTRL;
46     /* configure High Speed RUN mode */
47     reg &= ~SMC_PMCTRL_RUNM_MASK;
48     reg |= ((uint32_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
49     base->PMCTRL = reg;
50 
51     return kStatus_Success;
52 }
53 
54 /*!
55  * brief Configure the system to WAIT power mode.
56  *
57  * param base SMC peripheral base address.
58  * return SMC configuration error code.
59  */
SMC_SetPowerModeWait(SMC_Type * base)60 status_t SMC_SetPowerModeWait(SMC_Type *base)
61 {
62     /* configure Normal Wait mode */
63     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
64     __DSB();
65     __WFI();
66     __ISB();
67 
68     return kStatus_Success;
69 }
70 
71 /*!
72  * brief Configure the system to Stop power mode.
73  *
74  * param base SMC peripheral base address.
75  * param  option Partial Stop mode option.
76  * return SMC configuration error code.
77  */
SMC_SetPowerModeStop(SMC_Type * base,smc_partial_stop_option_t option)78 status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
79 {
80     status_t status;
81     uint32_t reg;
82 
83     /* configure the Partial Stop mode in Normal Stop mode */
84     reg = base->PMCTRL;
85     reg &= ~(SMC_PMCTRL_PSTOPO_MASK | SMC_PMCTRL_STOPM_MASK);
86     reg |= ((uint32_t)option << SMC_PMCTRL_PSTOPO_SHIFT) | ((uint32_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
87     base->PMCTRL = reg;
88 
89     /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
90     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
91 
92     /* read back to make sure the configuration valid before entering stop mode */
93     (void)base->PMCTRL;
94     __DSB();
95     __WFI();
96     __ISB();
97 
98 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
99     /* check whether the power mode enter Stop mode succeed */
100     if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
101     {
102         status = kStatus_SMC_StopAbort;
103     }
104     else
105     {
106         status = kStatus_Success;
107     }
108 #else
109     status = kStatus_Success;
110 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
111 
112     return status;
113 }
114 
115 /*!
116  * brief Configure the system to VLPR power mode.
117  *
118  * param base SMC peripheral base address.
119  * return SMC configuration error code.
120  */
SMC_SetPowerModeVlpr(SMC_Type * base)121 status_t SMC_SetPowerModeVlpr(SMC_Type *base)
122 {
123     uint32_t reg;
124 
125     reg = base->PMCTRL;
126     /* configure VLPR mode */
127     reg &= ~SMC_PMCTRL_RUNM_MASK;
128     reg |= ((uint32_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
129     base->PMCTRL = reg;
130 
131     return kStatus_Success;
132 }
133 
134 /*!
135  * brief Configure the system to VLPW power mode.
136  *
137  * param base SMC peripheral base address.
138  * return SMC configuration error code.
139  */
SMC_SetPowerModeVlpw(SMC_Type * base)140 status_t SMC_SetPowerModeVlpw(SMC_Type *base)
141 {
142     /* configure VLPW mode */
143     /* Clear the SLEEPDEEP bit to disable deep sleep mode */
144     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
145     __DSB();
146     __WFI();
147     __ISB();
148 
149     return kStatus_Success;
150 }
151 
152 /*!
153  * brief Configure the system to VLPS power mode.
154  *
155  * param base SMC peripheral base address.
156  * return SMC configuration error code.
157  */
SMC_SetPowerModeVlps(SMC_Type * base)158 status_t SMC_SetPowerModeVlps(SMC_Type *base)
159 {
160     uint32_t reg;
161     status_t status;
162 
163     /* configure VLPS mode */
164     reg = base->PMCTRL;
165     reg &= ~SMC_PMCTRL_STOPM_MASK;
166     reg |= ((uint32_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
167     base->PMCTRL = reg;
168 
169     /* Set the SLEEPDEEP bit to enable deep sleep mode */
170     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
171 
172     /* read back to make sure the configuration valid before enter stop mode */
173     (void)base->PMCTRL;
174     __DSB();
175     __WFI();
176     __ISB();
177 
178 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
179     /* check whether the power mode enter Stop mode succeed */
180     if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
181     {
182         status = kStatus_SMC_StopAbort;
183     }
184     else
185     {
186         status = kStatus_Success;
187     }
188 #else
189     status = kStatus_Success;
190 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
191 
192     return status;
193 }
194 
195 /*!
196  * brief Configure the system to LLS power mode.
197  *
198  * param base SMC peripheral base address.
199  * return SMC configuration error code.
200  */
SMC_SetPowerModeLls(SMC_Type * base)201 status_t SMC_SetPowerModeLls(SMC_Type *base)
202 {
203     uint32_t reg;
204     status_t status;
205 
206     /* configure to LLS mode */
207     reg = base->PMCTRL;
208     reg &= ~SMC_PMCTRL_STOPM_MASK;
209     reg |= ((uint32_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
210     base->PMCTRL = reg;
211 
212     /* Set the SLEEPDEEP bit to enable deep sleep mode */
213     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
214 
215     /* read back to make sure the configuration valid before entering stop mode */
216     (void)base->PMCTRL;
217     __DSB();
218     __WFI();
219     __ISB();
220 
221 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
222     /* check whether the power mode enter Stop mode succeed */
223     if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
224     {
225         status = kStatus_SMC_StopAbort;
226     }
227     else
228     {
229         status = kStatus_Success;
230     }
231 #else
232     status = kStatus_Success;
233 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
234 
235     return status;
236 }
237 
238 #if (defined(FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) && FSL_FEATURE_SMC_HAS_SUB_STOP_MODE)
239 
240 #if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE0)
241 /*!
242  * brief Configure the system to VLLS0 power mode.
243  *
244  * param base SMC peripheral base address.
245  * return SMC configuration error code.
246  */
SMC_SetPowerModeVlls0(SMC_Type * base)247 status_t SMC_SetPowerModeVlls0(SMC_Type *base)
248 {
249     uint32_t reg;
250 
251     /* configure to VLLS mode */
252     reg = base->PMCTRL;
253     reg &= ~SMC_PMCTRL_STOPM_MASK;
254     reg |= ((uint32_t)kSMC_StopVlls0 << SMC_PMCTRL_STOPM_SHIFT);
255     base->PMCTRL = reg;
256 
257     /* Set the SLEEPDEEP bit to enable deep sleep mode */
258     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
259 
260     /* read back to make sure the configuration valid before enter stop mode */
261     (void)base->PMCTRL;
262     __DSB();
263     __WFI();
264     __ISB();
265 
266     return kStatus_Success;
267 }
268 #endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
269 
270 #if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE2)
271 /*!
272  * brief Configure the system to VLLS2 power mode.
273  *
274  * param base SMC peripheral base address.
275  * return SMC configuration error code.
276  */
SMC_SetPowerModeVlls2(SMC_Type * base)277 status_t SMC_SetPowerModeVlls2(SMC_Type *base)
278 {
279     uint32_t reg;
280 
281     /* configure to VLLS mode */
282     reg = base->PMCTRL;
283     reg &= ~SMC_PMCTRL_STOPM_MASK;
284     reg |= ((uint32_t)kSMC_StopVlls2 << SMC_PMCTRL_STOPM_SHIFT);
285     base->PMCTRL = reg;
286 
287     /* Set the SLEEPDEEP bit to enable deep sleep mode */
288     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
289 
290     /* read back to make sure the configuration valid before enter stop mode */
291     (void)base->PMCTRL;
292     __DSB();
293     __WFI();
294     __ISB();
295 
296     return kStatus_Success;
297 }
298 #endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
299 
300 #else /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
301 /*!
302  * brief Configure the system to VLLS power mode.
303  *
304  * param base SMC peripheral base address.
305  * return SMC configuration error code.
306  */
SMC_SetPowerModeVlls(SMC_Type * base)307 status_t SMC_SetPowerModeVlls(SMC_Type *base)
308 {
309     uint32_t reg;
310     status_t status;
311 
312     /* configure to VLLS mode */
313     reg = base->PMCTRL;
314     reg &= ~SMC_PMCTRL_STOPM_MASK;
315     reg |= ((uint32_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
316     base->PMCTRL = reg;
317 
318     /* Set the SLEEPDEEP bit to enable deep sleep mode */
319     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
320 
321     /* read back to make sure the configuration valid before enter stop mode */
322     (void)base->PMCTRL;
323     __DSB();
324     __WFI();
325     __ISB();
326 
327 #if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
328     /* check whether the power mode enter Stop mode succeed */
329     if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK))
330     {
331         status = kStatus_SMC_StopAbort;
332     }
333     else
334     {
335         status = kStatus_Success;
336     }
337 #else
338     status = kStatus_Success;
339 #endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
340 
341     return status;
342 }
343 #endif /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
344 
345 /*!
346  * brief Configures the reset pin filter.
347  *
348  * This function sets the reset pin filter including the enablement/disablement and filter width.
349  *
350  * param base SMC peripheral base address.
351  * param config Pointer to the configuration structure.
352  */
SMC_ConfigureResetPinFilter(SMC_Type * base,const smc_reset_pin_filter_config_t * config)353 void SMC_ConfigureResetPinFilter(SMC_Type *base, const smc_reset_pin_filter_config_t *config)
354 {
355     assert(NULL != config);
356 
357     uint32_t reg;
358 
359     reg = SMC_RPC_FILTCFG(config->slowClockFilterCount) | SMC_RPC_FILTEN(config->enableFilter);
360 #if (defined(FSL_FEATURE_SMC_HAS_RPC_LPOFEN) && FSL_FEATURE_SMC_HAS_RPC_LPOFEN)
361     if (config->enableLpoFilter)
362     {
363         reg |= SMC_RPC_LPOFEN_MASK;
364     }
365 #endif /* FSL_FEATURE_SMC_HAS_RPC_LPOFEN */
366 
367     base->RPC = reg;
368 }
369