S32 SDK
power_manager_S32K1xx.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
49 #include <stddef.h>
50 #include "power_manager.h"
51 #include "power_smc_hw_access.h"
52 
54 #define POWER_SET_MODE_TIMEOUT 1000U
55 
58 
59 /*******************************************************************************
60  * INTERNAL FUNCTIONS
61  ******************************************************************************/
63 
65 
67 
68 /*******************************************************************************
69  * Code
70  ******************************************************************************/
71 
72 /*******************************************************************************
73  *
74  * It is expected that prior to the POWER_SYS_Init() call the write-once protection
75  * register was configured appropriately allowing entry to all required low power
76  * modes.
77  * The following is an example of how to set up two power modes and one
78  * callback, and initialize the Power manager with structures containing their settings.
79  * The example shows two possible ways the configuration structures can be stored
80  * (ROM or RAM), although it is expected that they will be placed in the read-only
81  * memory to save the RAM space. (Note: In the example it is assumed that the programmed chip
82  * doesn't support any optional power options described in the power_manager_user_config_t)
83  * :
84  * @code
85  *
86  * power_manager_user_config_t vlprConfig = { vlprConfig power mode configuration
87  * .powerMode = POWER_MANAGER_VLPR,
88  * .sleepOnExitOption = false,
89  * .sleepOnExitValue = false,
90  * };
91  *
92  * power_manager_user_config_t stopConfig = { stopConfig power mode configuration
93  * .powerMode = POWER_MANAGER_STOP,
94  * .sleepOnExitOption = false,
95  * .sleepOnExitValue = false,
96  * };
97  *
98  * power_manager_user_config_t const * powerConfigsArr[] = { Power mode configurations array
99  * &vlprConfig,
100  * &stopConfig
101  * };
102  *
103  * power_manager_callback_user_config_t callbackCfg0 = { Callback configuration structure callbackCfg0
104  * .callbackFunction = &callback0,
105  * .callbackType = POWER_MANAGER_CALLBACK_BEFORE_AFTER,
106  * .callbackData = (void *)0,
107  * };
108  *
109  * power_manager_callback_user_config_t const * callbacksConfigsArr[] = { Callback configuration structures array
110  * &callbackCfg0
111  * };
112  *
113  * status_t callback0(power_manager_notify_struct_t * notify, Definition of power manager callback
114  * power_manager_callback_data_t * dataPtr)
115  * {
116  * status_t ret = STATUS_SUCCESS;
117  * ...
118  * return ret;
119  * }
120  *
121  * int main(void) Main function
122  * {
123  * status_t ret = STATUS_SUCCESS;
124  *
125  * Calling of init method
126  * POWER_SYS_Init(&powerConfigsArr, 2U, &powerStaticCallbacksConfigsArr, 1U);
127  *
128  * Switch to VLPR mode
129  * ret = POWER_SYS_SetMode(MODE_VLPR,POWER_MANAGER_POLICY_AGREEMENT);
130  *
131  * if (ret != STATUS_SUCCESS)
132  * {
133  * return -1;
134  * }
135  * return 0;
136  * }
137  *
138  * @endcode
139  *
140  *END**************************************************************************/
142 {
143  smc_power_mode_protection_config_t powerModeProtConfig =
144  {
145  .vlpProt = true, /* Very low power mode is allowed. */
146  .hsrunProt = true /* High speed mode is allowed. */
147  };
148 
149  /* Very low power modes and high speed mode are not protected. */
150  SMC_SetProtectionMode(SMC, &powerModeProtConfig);
151 
152  return STATUS_SUCCESS;
153 }
154 
155 /*FUNCTION**********************************************************************
156  *
157  * Function Name : POWER_SYS_DoDeinit
158  * Description : This function performs the actual implementation-specific de-initialization.
159  *
160  *
161  *END**************************************************************************/
163 {
164  return STATUS_SUCCESS;
165 }
166 
167 /*FUNCTION**********************************************************************
168  *
169  * Function Name : POWER_SYS_DoSetMode
170  * Description : This function performs the actual implementation-specific logic to switch
171  * to one of the defined power modes.
172  *
173  *
174  *END**************************************************************************/
176 {
177  status_t returnCode; /* Function return */
178 
179  /* Check whether the power mode is a sleeping or a running power mode */
180  if (configPtr->powerMode <= POWER_MANAGER_VLPR)
181  {
182  /* Switch to a running power mode */
183  returnCode = POWER_SYS_SwitchToRunningPowerMode(configPtr);
184  }
185  else
186  {
187  /* Switch to a sleeping power mode */
188  returnCode = POWER_SYS_SwitchToSleepingPowerMode(configPtr);
189  }
190 
191  return returnCode;
192 }
193 
194 /*FUNCTION**********************************************************************
195  *
196  * Function Name : POWER_SYS_GetCurrentMode
197  * Description : Returns currently running power mode.
198  *
199  * Implements POWER_SYS_GetCurrentMode_Activity
200  *
201  *END**************************************************************************/
203 {
204  power_manager_modes_t retVal;
205 
206  switch (SMC_GetPowerModeStatus(SMC))
207  {
208  #if FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE
209  /* High speed run mode */
210  case STAT_HSRUN:
211  retVal = POWER_MANAGER_HSRUN;
212  break;
213  #endif
214  /* Run mode */
215  case STAT_RUN:
216  retVal = POWER_MANAGER_RUN;
217  break;
218  /* Very low power run mode */
219  case STAT_VLPR:
220  retVal = POWER_MANAGER_VLPR;
221  break;
222  /* This should never happen - core has to be in some run mode to execute code */
223  default:
224  retVal = POWER_MANAGER_MAX;
225  break;
226  }
227 
228  return retVal;
229 }
230 
231 /*FUNCTION**********************************************************************
232  *
233  * Function Name : POWER_SYS_WaitForModeStatus
234  * Description : Internal function used by POWER_SYS_SwitchToSleepingPowerMode and
235  * POWER_SYS_SwitchToRunningPowerMode functions
236  *
237  *END**************************************************************************/
239 {
240  status_t retCode;
241  power_mode_stat_t modeStat;
242  uint32_t i = 0U;
243 
244  switch (mode)
245  {
246  case SMC_RUN:
247  modeStat = STAT_RUN;
248  retCode = STATUS_SUCCESS;
249  break;
250  case SMC_VLPR:
251  modeStat = STAT_VLPR;
252  retCode = STATUS_SUCCESS;
253  break;
254  #if FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE
255  case SMC_HSRUN:
256  modeStat = STAT_HSRUN;
257  retCode = STATUS_SUCCESS;
258  break;
259  #endif
260  default:
261  /* invalid parameter */
262  modeStat = STAT_INVALID;
263  retCode = STATUS_UNSUPPORTED;
264  break;
265  }
266 
267  if (STATUS_SUCCESS == retCode)
268  {
269  for ( ; i < POWER_SET_MODE_TIMEOUT; i++)
270  {
271  if (SMC_GetPowerModeStatus(SMC) == modeStat)
272  {
273  break;
274  }
275  }
276  }
277 
278  if (i >= POWER_SET_MODE_TIMEOUT)
279  {
281  }
282 
283  return retCode;
284 }
285 
286 /*FUNCTION**********************************************************************
287  *
288  * Function Name : POWER_SYS_SwitchToRunningPowerMode
289  * Description :Internal function used by POWER_SYS_SetMode function to switch to a running power mode
290  * configPtr pointer to the requested user-defined power mode configuration
291  *
292  *END**************************************************************************/
294 {
295  smc_power_mode_config_t halModeConfig; /* SMC HAL layer configuration structure */
296  status_t returnCode;
297 
298  /* Configure the HAL layer */
299  switch (configPtr->powerMode)
300  {
301  #if FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE
302  /* High speed run mode */
303  case POWER_MANAGER_HSRUN:
304  /* High speed run mode can be entered only from Run mode */
305  if (SMC_GetPowerModeStatus(SMC) != STAT_RUN)
306  {
307  SMC_SetRunModeControl(SMC, SMC_RUN);
308  returnCode = POWER_SYS_WaitForModeStatus(SMC_RUN);
309  }
310  else
311  {
312  returnCode = STATUS_SUCCESS;
313  }
314 
315  if (STATUS_SUCCESS == returnCode)
316  {
317  halModeConfig.powerModeName = POWER_MANAGER_HSRUN;
318 
319  /* Switch the mode */
320  if (SMC_SetPowerMode(SMC, &halModeConfig) == STATUS_SUCCESS)
321  {
323  }
324  else
325  {
326  returnCode = STATUS_MCU_TRANSITION_FAILED;
327  }
328  }
329 
330  break;
331  #endif /* if FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
332  /* Run mode */
333  case POWER_MANAGER_RUN:
334  halModeConfig.powerModeName = POWER_MANAGER_RUN;
335  returnCode = STATUS_SUCCESS;
336  /* Switch the mode */
337  if (SMC_SetPowerMode(SMC, &halModeConfig) == STATUS_SUCCESS)
338  {
339  returnCode = POWER_SYS_WaitForModeStatus(SMC_RUN);
340  }
341  else
342  {
343  returnCode = STATUS_MCU_TRANSITION_FAILED;
344  }
345 
346  break;
347  /* Very low power run mode */
348  case POWER_MANAGER_VLPR:
349  /* Very low power run mode can be entered only from Run mode */
350  if (SMC_GetPowerModeStatus(SMC) != STAT_RUN)
351  {
352  SMC_SetRunModeControl(SMC, SMC_RUN);
353  returnCode = POWER_SYS_WaitForModeStatus(SMC_RUN);
354  }
355  else
356  {
357  returnCode = STATUS_SUCCESS;
358  }
359 
360  if (STATUS_SUCCESS == returnCode)
361  {
362  halModeConfig.powerModeName = POWER_MANAGER_VLPR;
363 
364  /* Switch the mode */
365  if (SMC_SetPowerMode(SMC, &halModeConfig) == STATUS_SUCCESS)
366  {
368  }
369  else
370  {
371  returnCode = STATUS_MCU_TRANSITION_FAILED;
372  }
373  }
374 
375  break;
376  /* Wait mode */
377  default:
378  /* invalid power mode */
379  returnCode = STATUS_UNSUPPORTED;
380  halModeConfig.powerModeName = POWER_MANAGER_MAX;
381  break;
382  }
383 
384  return returnCode;
385 }
386 
387 /*FUNCTION**********************************************************************
388  *
389  * Function Name : POWER_SYS_SwitchToSleepingPowerMode
390  * Description :Internal function used by POWER_SYS_SetMode function to switch to a sleeping power mode
391  * configPtr pointer to the requested user-defined power mode configuration
392  *
393  *END**************************************************************************/
395 {
396  smc_power_mode_config_t halModeConfig; /* SMC HAL layer configuration structure */
397  status_t returnCode; /* return value */
398  power_mode_stat_t pwrModeStat; /* power mode stat */
399 
400  /* Configure the HAL layer */
401  switch (configPtr->powerMode)
402  {
403  #if FEATURE_SMC_HAS_WAIT_VLPW
404  /* Wait mode */
405  case POWER_MANAGER_WAIT:
406  /* Wait mode can be entered only from Run mode */
407  if (SMC_GetPowerModeStatus(SMC) != STAT_RUN)
408  {
409  SMC_SetRunModeControl(SMC, SMC_RUN);
410  returnCode = POWER_SYS_WaitForModeStatus(SMC_RUN);
411  }
412  else
413  {
414  returnCode = STATUS_SUCCESS;
415  }
416 
417  halModeConfig.powerModeName = POWER_MANAGER_WAIT;
418  break;
419  /* Very low power wait mode */
420  case POWER_MANAGER_VLPW:
421  /* Very low power wait mode can be netered only from Very low power run mode */
422  if (SMC_GetPowerModeStatus(SMC) != STAT_VLPR)
423  {
424  SMC_SetRunModeControl(SMC, SMC_VLPR);
426  }
427  else
428  {
429  returnCode = STATUS_SUCCESS;
430  }
431 
432  halModeConfig.powerModeName = POWER_MANAGER_VLPW;
433  break;
434  #endif /* if FEATURE_SMC_HAS_WAIT_VLPW */
435  #if FEATURE_SMC_HAS_PSTOPO
436  /* Partial stop modes */
437  case POWER_MANAGER_PSTOP1:
438  /* fall-through */
439  case POWER_MANAGER_PSTOP2:
440  /* fall-through */
441  #endif
442  #if FEATURE_SMC_HAS_STOPO
443  /* Stop modes */
444  case POWER_MANAGER_STOP1:
445  /* fall-through */
446  case POWER_MANAGER_STOP2:
447  /* fall-through */
448  #endif
449  /* Stop mode */
450  case POWER_MANAGER_STOP:
451  /* Stop mode can be entered only from Run mode */
452  if (SMC_GetPowerModeStatus(SMC) != STAT_RUN)
453  {
454  SMC_SetRunModeControl(SMC, SMC_RUN);
455  returnCode = POWER_SYS_WaitForModeStatus(SMC_RUN);
456  }
457  else
458  {
459  returnCode = STATUS_SUCCESS;
460  }
461 
462  halModeConfig.powerModeName = POWER_MANAGER_STOP;
463  #if FEATURE_SMC_HAS_PSTOPO
464  halModeConfig.pstopOption = true;
465  /* Set the partial stop option value */
466  if (POWER_MANAGER_PSTOP1 == configPtr->powerMode)
467  {
468  halModeConfig.pstopOptionValue = SMC_PSTOP_STOP1;
469  }
470  else if (POWER_MANAGER_PSTOP2 == configPtr->powerMode)
471  {
472  halModeConfig.pstopOptionValue = SMC_PSTOP_STOP2;
473  }
474  else
475  {
476  halModeConfig.pstopOptionValue = SMC_PSTOP_STOP;
477  }
478 
479  #endif /* if FEATURE_SMC_HAS_PSTOPO */
480  #if FEATURE_SMC_HAS_STOPO
481  /* Set the stop option value */
482  if (POWER_MANAGER_STOP1 == configPtr->powerMode)
483  {
484  halModeConfig.stopOption = true;
485  halModeConfig.stopOptionValue = SMC_STOP1;
486  }
487  else if (POWER_MANAGER_STOP2 == configPtr->powerMode)
488  {
489  halModeConfig.stopOption = true;
490  halModeConfig.stopOptionValue = SMC_STOP2;
491  }
492  else
493  {
494  halModeConfig.stopOption = false;
495  }
496 
497  #endif /* if FEATURE_SMC_HAS_STOPO */
498  break;
499  /* Very low power stop mode */
500  case POWER_MANAGER_VLPS:
501  pwrModeStat = SMC_GetPowerModeStatus(SMC);
502  /* Very low power stop mode can be entered only from Run mode or Very low power run mode*/
503  if ((pwrModeStat != STAT_RUN) && (pwrModeStat != STAT_VLPR))
504  {
505  SMC_SetRunModeControl(SMC, SMC_RUN);
506  returnCode = POWER_SYS_WaitForModeStatus(SMC_RUN);
507  }
508  else
509  {
510  returnCode = STATUS_SUCCESS;
511  }
512 
513  halModeConfig.powerModeName = POWER_MANAGER_VLPS;
514  break;
515  default:
516  /* invalid power mode */
517  returnCode = STATUS_UNSUPPORTED;
518  halModeConfig.powerModeName = POWER_MANAGER_MAX;
519  break;
520  }
521 
522  if (STATUS_SUCCESS == returnCode)
523  {
524  /* Configure ARM core what to do after interrupt invoked in (deep) sleep state */
525  if (configPtr->sleepOnExitOption)
526  {
527  if (configPtr->sleepOnExitValue)
528  {
529  /* Go back to (deep) sleep state on ISR exit */
531  }
532  else
533  {
534  /* Do not re-enter (deep) sleep state on ISR exit */
536  }
537  }
538 
539  /* Switch the mode */
540  if (SMC_SetPowerMode(SMC, &halModeConfig) != STATUS_SUCCESS)
541  {
542  returnCode = STATUS_MCU_TRANSITION_FAILED;
543  }
544  }
545 
546  return returnCode;
547 }
548 
549 /*******************************************************************************
550  * EOF
551  ******************************************************************************/
#define SMC
Definition: S32K142.h:10991
static status_t POWER_SYS_SwitchToRunningPowerMode(const power_manager_user_config_t *const configPtr)
power_manager_state_t gPowerManagerState
Power manager internal structure.
Definition: power_manager.c:51
power_mode_stat_t
Power Modes in PMSTAT Implements power_mode_stat_t_Class.
Power mode protection configuration Implements smc_power_mode_protection_config_t_Class.
power_manager_modes_t powerModeName
status_t POWER_SYS_DoDeinit(void)
This function implementation-specific de-initialization of power manager.
status_t POWER_SYS_DoInit(void)
This function implementation-specific configuration of power modes.
#define S32_SCB
Definition: S32K142.h:9720
smc_run_mode_t
Run mode definition Implements smc_run_mode_t_Class.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
#define S32_SCB_SCR_SLEEPONEXIT_MASK
Definition: S32K142.h:9845
power_manager_modes_t POWER_SYS_GetCurrentMode(void)
This function returns currently running power mode.
Power mode control configuration used for calling the SMC_SYS_SetPowerMode API Implements smc_power_m...
Power mode user configuration structure.
static status_t POWER_SYS_WaitForModeStatus(smc_run_mode_t mode)
static status_t POWER_SYS_SwitchToSleepingPowerMode(const power_manager_user_config_t *const configPtr)
Power manager internal state structure.
#define POWER_SET_MODE_TIMEOUT
power_manager_modes_t
Power modes enumeration.
status_t POWER_SYS_DoSetMode(const power_manager_user_config_t *const configPtr)
This function configures the power mode.