rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
fsl_smc.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#include "hal.h"
10#include "fsl_smc.h"
11#include "fsl_common.h"
12
13/*******************************************************************************
14 * Definitions
15 ******************************************************************************/
16/* Component ID definition, used by tools. */
17#ifndef FSL_COMPONENT_ID
18#define FSL_COMPONENT_ID "platform.drivers.smc"
19#endif
20
21typedef void (*smc_stop_ram_func_t)(void);
22
23/*******************************************************************************
24 * Prototypes
25 ******************************************************************************/
26static void SMC_EnterStopRamFunc(void);
27
28/*******************************************************************************
29 * Variables
30 ******************************************************************************/
31static uint32_t g_savedPrimask;
32
33/*
34 * The ram function code is:
35 *
36 * uint32_t i;
37 * for (i=0; i<0x8; i++)
38 * {
39 * __NOP();
40 * }
41 * __DSB();
42 * __WFI();
43 * __ISB();
44 *
45 * When entring the stop modes, the flash prefetch might be interrupted, thus
46 * the prefetched code or data might be broken. To make sure the flash is idle
47 * when entring the stop modes, the code is moved to ram. And delay for a while
48 * before WFI to make sure previous flash prefetch is finished.
49 *
50 * Only need to do like this when code is in flash, if code is in rom or ram,
51 * this is not necessary.
52 */
53static uint16_t s_stopRamFuncArray[] = {
54 0x2000, /* MOVS R0, #0 */
55 0x2808, /* CMP R0, #8 */
56 0xD202, /* BCS.N */
57 0xBF00, /* NOP */
58 0x1C40, /* ADDS R0, R0, #1 */
59 0xE7FA, /* B.N */
60 0xF3BF, 0x8F4F, /* DSB */
61 0xBF30, /* WFI */
62 0xF3BF, 0x8F6F, /* ISB */
63 0x4770, /* BX LR */
64};
65
66/*******************************************************************************
67 * Code
68 ******************************************************************************/
69static void SMC_EnterStopRamFunc(void)
70{
71 uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U;
72 smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry;
73 stopRamFunc();
74}
75
76#if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
77/*!
78 * brief Gets the SMC parameter.
79 *
80 * This function gets the SMC parameter including the enabled power mdoes.
81 *
82 * param base SMC peripheral base address.
83 * param param Pointer to the SMC param structure.
84 */
85void SMC_GetParam(SMC_Type *base, smc_param_t *param)
86{
87 uint32_t reg = base->PARAM;
88 param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
89 param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
90 param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
91 param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
92}
93#endif /* FSL_FEATURE_SMC_HAS_PARAM */
94
95/*!
96 * brief Prepares to enter stop modes.
97 *
98 * This function should be called before entering STOP/VLPS/LLS/VLLS modes.
99 */
101{
102 g_savedPrimask = DisableGlobalIRQ();
103 __ISB();
104}
105
106/*!
107 * brief Recovers after wake up from stop modes.
108 *
109 * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
110 * It is used with ref SMC_PreEnterStopModes.
111 */
113{
114 EnableGlobalIRQ(g_savedPrimask);
115 __ISB();
116}
117
118/*!
119 * brief Prepares to enter wait modes.
120 *
121 * This function should be called before entering WAIT/VLPW modes.
122 */
124{
125 g_savedPrimask = DisableGlobalIRQ();
126 __ISB();
127}
128
129/*!
130 * brief Recovers after wake up from stop modes.
131 *
132 * This function should be called after wake up from WAIT/VLPW modes.
133 * It is used with ref SMC_PreEnterWaitModes.
134 */
136{
137 EnableGlobalIRQ(g_savedPrimask);
138 __ISB();
139}
140
141/*!
142 * brief Configures the system to RUN power mode.
143 *
144 * param base SMC peripheral base address.
145 * return SMC configuration error code.
146 */
148{
149 uint8_t reg;
150
151 reg = base->PMCTRL;
152 /* configure Normal RUN mode */
153 reg &= ~SMC_PMCTRL_RUNM_MASK;
154 reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
155 base->PMCTRL = reg;
156
157 return kStatus_Success;
158}
159
160#if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
161/*!
162 * brief Configures the system to HSRUN power mode.
163 *
164 * param base SMC peripheral base address.
165 * return SMC configuration error code.
166 */
168{
169 uint8_t reg;
170
171 reg = base->PMCTRL;
172 /* configure High Speed RUN mode */
173 reg &= ~SMC_PMCTRL_RUNM_MASK;
174 reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
175 base->PMCTRL = reg;
176
177 return kStatus_Success;
178}
179#endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
180
181/*!
182 * brief Configures the system to WAIT power mode.
183 *
184 * param base SMC peripheral base address.
185 * return SMC configuration error code.
186 */
188{
189 /* configure Normal Wait mode */
190 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
191 __DSB();
192 __WFI();
193 __ISB();
194
195 return kStatus_Success;
196}
197
198/*!
199 * brief Configures the system to Stop power mode.
200 *
201 * param base SMC peripheral base address.
202 * param option Partial Stop mode option.
203 * return SMC configuration error code.
204 */
206{
207 uint8_t reg;
208
209#if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
210 /* configure the Partial Stop mode in Normal Stop mode */
211 reg = base->STOPCTRL;
212 reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
213 reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
214 base->STOPCTRL = reg;
215#endif
216
217 /* configure Normal Stop mode */
218 reg = base->PMCTRL;
219 reg &= ~SMC_PMCTRL_STOPM_MASK;
220 reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
221 base->PMCTRL = reg;
222
223 /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
224 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
225
226 /* read back to make sure the configuration valid before enter stop mode */
227 (void)base->PMCTRL;
229
230 /* check whether the power mode enter Stop mode succeed */
231 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
232 {
234 }
235 else
236 {
237 return kStatus_Success;
238 }
239}
240
241/*!
242 * brief Configures the system to VLPR power mode.
243 *
244 * param base SMC peripheral base address.
245 * return SMC configuration error code.
246 */
248#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
249 ,
250 bool wakeupMode
251#endif
252 )
253{
254 uint8_t reg;
255
256 reg = base->PMCTRL;
257#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
258 /* configure whether the system remains in VLP mode on an interrupt */
259 if (wakeupMode)
260 {
261 /* exits to RUN mode on an interrupt */
262 reg |= SMC_PMCTRL_LPWUI_MASK;
263 }
264 else
265 {
266 /* remains in VLP mode on an interrupt */
267 reg &= ~SMC_PMCTRL_LPWUI_MASK;
268 }
269#endif /* FSL_FEATURE_SMC_HAS_LPWUI */
270
271 /* configure VLPR mode */
272 reg &= ~SMC_PMCTRL_RUNM_MASK;
273 reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
274 base->PMCTRL = reg;
275
276 return kStatus_Success;
277}
278
279/*!
280 * brief Configures the system to VLPW power mode.
281 *
282 * param base SMC peripheral base address.
283 * return SMC configuration error code.
284 */
286{
287 /* configure VLPW mode */
288 /* Set the SLEEPDEEP bit to enable deep sleep mode */
289 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
290 __DSB();
291 __WFI();
292 __ISB();
293
294 return kStatus_Success;
295}
296
297/*!
298 * brief Configures the system to VLPS power mode.
299 *
300 * param base SMC peripheral base address.
301 * return SMC configuration error code.
302 */
304{
305 uint8_t reg;
306
307 /* configure VLPS mode */
308 reg = base->PMCTRL;
309 reg &= ~SMC_PMCTRL_STOPM_MASK;
310 reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
311 base->PMCTRL = reg;
312
313 /* Set the SLEEPDEEP bit to enable deep sleep mode */
314 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
315
316 /* read back to make sure the configuration valid before enter stop mode */
317 (void)base->PMCTRL;
319
320 /* check whether the power mode enter VLPS mode succeed */
321 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
322 {
324 }
325 else
326 {
327 return kStatus_Success;
328 }
329}
330
331#if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
332/*!
333 * brief Configures the system to LLS power mode.
334 *
335 * param base SMC peripheral base address.
336 * return SMC configuration error code.
337 */
339#if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
340 (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
341 ,
343#endif
344 )
345{
346 uint8_t reg;
347
348 /* configure to LLS mode */
349 reg = base->PMCTRL;
350 reg &= ~SMC_PMCTRL_STOPM_MASK;
351 reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
352 base->PMCTRL = reg;
353
354/* configure LLS sub-mode*/
355#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
356 reg = base->STOPCTRL;
357 reg &= ~SMC_STOPCTRL_LLSM_MASK;
358 reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
359 base->STOPCTRL = reg;
360#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
361
362#if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
363 if (config->enableLpoClock)
364 {
365 base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK;
366 }
367 else
368 {
369 base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK;
370 }
371#endif /* FSL_FEATURE_SMC_HAS_LPOPO */
372
373 /* Set the SLEEPDEEP bit to enable deep sleep mode */
374 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
375
376 /* read back to make sure the configuration valid before enter stop mode */
377 (void)base->PMCTRL;
379
380 /* check whether the power mode enter LLS mode succeed */
381 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
382 {
384 }
385 else
386 {
387 return kStatus_Success;
388 }
389}
390#endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
391
392#if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
393/*!
394 * brief Configures the system to VLLS power mode.
395 *
396 * param base SMC peripheral base address.
397 * param config The VLLS power mode configuration structure.
398 * return SMC configuration error code.
399 */
401{
402 uint8_t reg;
403
404#if (defined(FSL_FEATURE_SMC_HAS_PORPO) && FSL_FEATURE_SMC_HAS_PORPO)
405#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) || \
406 (defined(FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) && FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) || \
407 (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
408 if (config->subMode == kSMC_StopSub0)
409#endif
410 {
411 /* configure whether the Por Detect work in Vlls0 mode */
412 if (config->enablePorDetectInVlls0)
413 {
414#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
415 base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
416#else
417 base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
418#endif
419 }
420 else
421 {
422#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
423 base->VLLSCTRL |= SMC_VLLSCTRL_PORPO_MASK;
424#else
425 base->STOPCTRL |= SMC_STOPCTRL_PORPO_MASK;
426#endif
427 }
428 }
429#endif /* FSL_FEATURE_SMC_HAS_PORPO */
430
431#if (defined(FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION) && FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION)
432 else if (config->subMode == kSMC_StopSub2)
433 {
434 /* configure whether the Por Detect work in Vlls0 mode */
435 if (config->enableRam2InVlls2)
436 {
437#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
438 base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
439#else
440 base->STOPCTRL |= SMC_STOPCTRL_RAM2PO_MASK;
441#endif
442 }
443 else
444 {
445#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
446 base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
447#else
448 base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
449#endif
450 }
451 }
452 else
453 {
454 }
455#endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
456
457 /* configure to VLLS mode */
458 reg = base->PMCTRL;
459 reg &= ~SMC_PMCTRL_STOPM_MASK;
460 reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
461 base->PMCTRL = reg;
462
463/* configure the VLLS sub-mode */
464#if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
465 reg = base->VLLSCTRL;
466 reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
467 reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
468 base->VLLSCTRL = reg;
469#else
470#if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
471 reg = base->STOPCTRL;
472 reg &= ~SMC_STOPCTRL_LLSM_MASK;
473 reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
474 base->STOPCTRL = reg;
475#else
476 reg = base->STOPCTRL;
477 reg &= ~SMC_STOPCTRL_VLLSM_MASK;
478 reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
479 base->STOPCTRL = reg;
480#endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
481#endif
482
483#if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
484 if (config->enableLpoClock)
485 {
486 base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK;
487 }
488 else
489 {
490 base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK;
491 }
492#endif /* FSL_FEATURE_SMC_HAS_LPOPO */
493
494 /* Set the SLEEPDEEP bit to enable deep sleep mode */
495 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
496
497 /* read back to make sure the configuration valid before enter stop mode */
498 (void)base->PMCTRL;
500
501 /* check whether the power mode enter LLS mode succeed */
502 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
503 {
505 }
506 else
507 {
508 return kStatus_Success;
509 }
510}
511#endif /* FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE */
static constexpr persistent_config_s * config
status_t SMC_SetPowerModeLls(SMC_Type *base #if((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) &&FSL_FEATURE_SMC_HAS_LLS_SUBMODE)||\‍(defined(FSL_FEATURE_SMC_HAS_LPOPO) &&FSL_FEATURE_SMC_HAS_LPOPO)), const smc_power_mode_lls_config_t *config #endif)
Definition fsl_smc.c:338
static uint32_t g_savedPrimask
Definition fsl_smc.c:31
void(* smc_stop_ram_func_t)(void)
Definition fsl_smc.c:21
status_t SMC_SetPowerModeVlpr(SMC_Type *base #if(defined(FSL_FEATURE_SMC_HAS_LPWUI) &&FSL_FEATURE_SMC_HAS_LPWUI), bool wakeupMode #endif)
Definition fsl_smc.c:247
static void SMC_EnterStopRamFunc(void)
Definition fsl_smc.c:69
static uint16_t s_stopRamFuncArray[]
Definition fsl_smc.c:53
int32_t status_t
Type used for all status and error return values.
Definition fsl_common.h:169
@ kStatus_Success
Definition fsl_common.h:159
void SMC_GetParam(SMC_Type *base, smc_param_t *param)
Gets the SMC parameter.
Definition fsl_smc.c:85
void SMC_PostExitStopModes(void)
Recovers after wake up from stop modes.
Definition fsl_smc.c:112
void SMC_PreEnterWaitModes(void)
Prepares to enter wait modes.
Definition fsl_smc.c:123
void SMC_PreEnterStopModes(void)
Prepares to enter stop modes.
Definition fsl_smc.c:100
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
Configures the system to VLPW power mode.
Definition fsl_smc.c:285
enum _smc_partial_stop_mode smc_partial_stop_option_t
Partial STOP option.
status_t SMC_SetPowerModeVlps(SMC_Type *base)
Configures the system to VLPS power mode.
Definition fsl_smc.c:303
status_t SMC_SetPowerModeRun(SMC_Type *base)
Configures the system to RUN power mode.
Definition fsl_smc.c:147
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
Configures the system to Stop power mode.
Definition fsl_smc.c:205
status_t SMC_SetPowerModeWait(SMC_Type *base)
Configures the system to WAIT power mode.
Definition fsl_smc.c:187
void SMC_PostExitWaitModes(void)
Recovers after wake up from stop modes.
Definition fsl_smc.c:135
status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
Configures the system to VLLS power mode.
Definition fsl_smc.c:400
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
Configures the system to HSRUN power mode.
Definition fsl_smc.c:167
@ kSMC_StopSub2
Definition fsl_smc.h:118
@ kSMC_StopSub0
Definition fsl_smc.h:116
@ kSMC_StopVlps
Definition fsl_smc.h:99
@ kSMC_StopLls
Definition fsl_smc.h:101
@ kSMC_StopNormal
Definition fsl_smc.h:98
@ kSMC_StopVlls
Definition fsl_smc.h:104
@ kStatus_SMC_StopAbort
Definition fsl_smc.h:138
@ kSMC_RunNormal
Definition fsl_smc.h:86
@ kSMC_RunVlpr
Definition fsl_smc.h:87
@ kSMC_Hsrun
Definition fsl_smc.h:89
IP parameter definition.
Definition fsl_smc.h:158
SMC Low-Leakage Stop power mode configuration.
Definition fsl_smc.h:172
SMC Very Low-Leakage Stop power mode configuration.
Definition fsl_smc.h:187
static tstrWifiInitParam param