S32 SDK
power_manager_common.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  */
18 
19 
51 #include <stddef.h>
52 #include "power_manager.h"
53 
54 /*******************************************************************************
55  * Internal Variables
56  ******************************************************************************/
57 
60 
61 /*******************************************************************************
62  * PROTOTYPES
63  ******************************************************************************/
64 
65 static status_t POWER_SYS_CallbacksManagement(power_manager_notify_struct_t *notifyStruct, uint8_t *currentStaticCallback, power_manager_policy_t policy);
66 /* Implementation-specific - defined in smc, mc_me etc */
67 extern status_t POWER_SYS_DoInit(void);
68 extern status_t POWER_SYS_DoDeinit(void);
69 extern status_t POWER_SYS_DoSetMode(const power_manager_user_config_t * const configPtr);
70 
71 
72 /*******************************************************************************
73  * Code
74  ******************************************************************************/
75 
76 /*FUNCTION**********************************************************************
77  *
78  * Function Name : POWER_SYS_Init
79  * Description : Initializes the Power manager for operation.
80  * This function initializes the Power manager and its run-time state structure.
81  * Reference to an array of Power mode configuration structures has to be passed
82  * as parameter along with parameter specifying its size. At least one power mode
83  * configuration is required. Optionally, reference to array of predefined
84  * call-backs can be passed with its size parameter.
85  * For details about call-backs refer to the power_manager_callback_user_config_t.
86  * As Power manager stores only references to array of these structures they have
87  * to exist while Power manager is used.
88  *
89  * Implements POWER_SYS_Init_Activity
90  *END**************************************************************************/
92  uint8_t configsNumber,
93  power_manager_callback_user_config_t *(* callbacksPtr)[],
94  uint8_t callbacksNumber)
95 {
96  DEV_ASSERT(powerConfigsPtr != NULL); /* Reference to the power configurations is valid. */
97  DEV_ASSERT(configsNumber != 0U); /* Power configuration index is valid. */
98  DEV_ASSERT(gPowerManagerState.configs == NULL); /* Driver is not initialized, reference to configuration is not valid. */
99  DEV_ASSERT(gPowerManagerState.configsNumber == 0U); /* Driver is not initialized, number of configurations is zero. */
100 
101 
102  /* Store references to user-defined power mode configurations */
103  gPowerManagerState.configs = (power_manager_user_config_t *(*)[])powerConfigsPtr;
104  gPowerManagerState.configsNumber = configsNumber;
105  gPowerManagerState.currentConfig = 0U;
106  /* Store references to user-defined callback configurations and increment call-back handle counter */
107  if (callbacksPtr != NULL)
108  {
109  gPowerManagerState.staticCallbacks = (power_manager_callback_user_config_t *(*)[])callbacksPtr;
110  gPowerManagerState.staticCallbacksNumber = callbacksNumber;
111  /* Default value of handle of last call-back that returned error */
112  gPowerManagerState.errorCallbackIndex = callbacksNumber;
113  }
114  else
115  {
116  gPowerManagerState.staticCallbacks = NULL;
117  gPowerManagerState.staticCallbacksNumber = 0U;
118  gPowerManagerState.errorCallbackIndex = 0U;
119  }
120 
121  return POWER_SYS_DoInit();
122 }
123 
124 /*FUNCTION**********************************************************************
125  *
126  * Function Name : POWER_SYS_Deinit
127  * Description : Deinitializes the Power manager.
128  *
129  * Implements POWER_SYS_Deinit_Activity
130  *END**************************************************************************/
132 {
133  gPowerManagerState.configs = NULL;
134  gPowerManagerState.configsNumber = 0U;
135  gPowerManagerState.staticCallbacks = NULL;
136  gPowerManagerState.staticCallbacksNumber = 0U;
137 
138  return POWER_SYS_DoDeinit();
139 }
140 
141 /*FUNCTION**********************************************************************
142  *
143  * Function Name : POWER_SYS_GetLastMode
144  * Description : This function returns power mode set as the last one.
145  *
146  * This function returns index of power mode which was set using POWER_SYS_SetMode() as the last one.
147  * If the power mode was entered although some of the registered call-back denied the mode change
148  * or if any of the call-backs invoked after the entering/restoring run mode failed then the return
149  * code of this function has STATUS_ERROR value.
150  * value.
151  *
152  * Implements POWER_SYS_GetLastMode_Activity
153  *END**************************************************************************/
154 status_t POWER_SYS_GetLastMode(uint8_t* powerModeIndexPtr)
155 {
156  status_t returnCode; /* Function return */
157 
158  /* Pass index of user-defined configuration structure of currently running power mode */
159  *powerModeIndexPtr = gPowerManagerState.currentConfig;
160  /* Return whether all call-backs executed without error */
161  if (gPowerManagerState.errorCallbackIndex == gPowerManagerState.staticCallbacksNumber)
162  {
163  returnCode = STATUS_SUCCESS;
164  }
165  else
166  {
167  returnCode = STATUS_ERROR;
168  }
169  return returnCode;
170 }
171 
172 /*FUNCTION**********************************************************************
173  *
174  * Function Name : POWER_SYS_GetLastModeConfig
175  * Description : This function returns user configuration structure of power mode set as the last one.
176  *
177  * This function returns reference to configuration structure which was set using POWER_SYS_SetMode()
178  * as the last one. If the current power mode was entered although some of the registered call-back denied
179  * the mode change or if any of the call-backs invoked after the entering/restoring run mode failed then
180  * the return code of this function has STATUS_ERROR value.
181  *
182  * Implements POWER_SYS_GetLastModeConfig_Activity
183  *END**************************************************************************/
185 {
186  status_t returnCode; /* Function return */
187  /* Pass reference to user-defined configuration structure of currently running power mode */
188  *powerModePtr = (*gPowerManagerState.configs)[gPowerManagerState.currentConfig];
189  /* Return whether all call-backs executed without error */
190  if (gPowerManagerState.errorCallbackIndex == gPowerManagerState.staticCallbacksNumber)
191  {
192  returnCode = STATUS_SUCCESS;
193  }
194  else
195  {
196  returnCode = STATUS_ERROR;
197  }
198  return returnCode;
199 }
200 
201 /*FUNCTION**********************************************************************
202  *
203  * Function Name : POWER_SYS_GetErrorCallbackIndex
204  * Description : Returns the last failed notification callback.
205  *
206  * This function returns index of the last call-back that failed during the power mode switch while
207  * the last POWER_SYS_SetMode() was called. If the last POWER_SYS_SetMode() call ended successfully
208  * value equal to callbacks number is returned. Returned value represents index in the array of
209  * static call-backs.
210  *
211  * Implements POWER_SYS_GetErrorCallbackIndex_Activity
212  *END**************************************************************************/
214 {
215  return gPowerManagerState.errorCallbackIndex;
216 }
217 
218 /*FUNCTION**********************************************************************
219  *
220  * Function Name : POWER_SYS_GetErrorCallback
221  * Description : Get the callback which returns error in last mode switch.
222  *
223  * Implements POWER_SYS_GetErrorCallback_Activity
224  *END**************************************************************************/
226  /* If all callbacks return success. */
227  return (gPowerManagerState.errorCallbackIndex
228  >= gPowerManagerState.staticCallbacksNumber) ?
229  NULL :
230  (*gPowerManagerState.staticCallbacks)[gPowerManagerState.errorCallbackIndex];
231 }
232 
233 /*FUNCTION**********************************************************************************************
234  * Function Name : POWER_SYS_CallbacksManagement
235  * Description : Internal function used by POWER_SYS_SetMode function for callback management
236  * notifyStruct callback notification structure
237  * currentStaticCallback index to array of statically registered call-backs
238  * policy transaction policy
239  *
240  *END***************************************************************************************************/
241 static status_t POWER_SYS_CallbacksManagement(power_manager_notify_struct_t *notifyStruct, uint8_t *currentStaticCallback, power_manager_policy_t policy)
242 {
243  uint8_t callbacksNumber; /* The total number of callbacks */
244  status_t returnCode = STATUS_SUCCESS; /* Function return */
245  status_t errorCode = STATUS_SUCCESS; /* Error code to be returned (error case) */
246  status_t callbackStatusCode; /* Status code returned by callback function */
247  power_manager_callback_type_t callbackTypeFilter; /* Callback types to be excluded */
248 
249  switch(notifyStruct->notifyType)
250  {
251  /* notify before */
253  callbacksNumber = gPowerManagerState.staticCallbacksNumber;
254  callbackTypeFilter = POWER_MANAGER_CALLBACK_AFTER;
255  errorCode = STATUS_MCU_NOTIFY_BEFORE_ERROR;
256  break;
257  /* notify after */
259  callbacksNumber = gPowerManagerState.staticCallbacksNumber;
260  callbackTypeFilter = POWER_MANAGER_CALLBACK_BEFORE;
261  errorCode = STATUS_MCU_NOTIFY_AFTER_ERROR;
262  break;
263  /* notify recover */
265  callbacksNumber = *currentStaticCallback;
266  callbackTypeFilter = POWER_MANAGER_CALLBACK_AFTER;
267  errorCode = STATUS_MCU_NOTIFY_BEFORE_ERROR;
268  break;
269  default:
270  /* invalid value for notifyType */
271  DEV_ASSERT(false);
272  callbacksNumber = 0U;
273  callbackTypeFilter = POWER_MANAGER_CALLBACK_BEFORE;
274  break;
275  }
276 
277  /* From all statically registered call-backs... */
278  for ((*currentStaticCallback) = 0U; (*currentStaticCallback) < callbacksNumber; (*currentStaticCallback)++)
279  {
280  /* Pointer to callback configuration */
281  const power_manager_callback_user_config_t * const callbackConfig = ((*gPowerManagerState.staticCallbacks)[*currentStaticCallback]);
282 
283  /* Check pointer to static callback configuration */
284  if ( callbackConfig != NULL ){
285  /* ...notify only those which asked to be called */
286  if ( callbackTypeFilter != callbackConfig->callbackType)
287  {
288  /* In case that call-back returned error code mark it, store the call-back handle and eventually cancel the mode switch */
289 
290  callbackStatusCode = callbackConfig->callbackFunction(notifyStruct, callbackConfig->callbackData);
291  if (STATUS_SUCCESS != callbackStatusCode)
292  {
293  returnCode = errorCode;
294  gPowerManagerState.errorCallbackIndex = *currentStaticCallback;
295  /* If not forcing power mode switch, call all already notified call-backs to revert their state as the mode change is canceled */
296  if (policy != POWER_MANAGER_POLICY_FORCIBLE)
297  {
298  break;
299  }
300  }
301  }
302  }
303  }
304 
305  return returnCode;
306 }
307 
308 /*FUNCTION**********************************************************************
309  *
310  * Function Name : POWER_SYS_SetMode
311  * Description : Configures the power mode.
312  *
313  * This function switches to one of the defined power modes. Requested mode number is passed
314  * as an input parameter. This function notifies all registered callback functions before
315  * the mode change (using POWER_MANAGER_CALLBACK_BEFORE set as callback type parameter),
316  * sets specific power options defined in the power mode configuration and enters the specified
317  * mode. In case of succesfull switch, this function also invokes all registered callbacks after
318  * the mode change (using POWER_MANAGER_CALLBACK_AFTER).
319  * The actual mode switch is performed by POWER_SYS_DoSetMode in the specific implementation.
320  * Callbacks are invoked in the following order: All registered callbacks are notified
321  * ordered by index in the callbacks array (see callbacksPtr parameter of POWER_SYS_Init()).
322  * The same order is used for before and after switch notifications.
323  * The notifications before the power mode switch can be used to obtain confirmation about
324  * the change from registered callbacks. If any registered callback denies the power
325  * mode change, further execution of this function depends on mode change policy: the mode
326  * change is either forced (POWER_MANAGER_POLICY_FORCIBLE) or exited (POWER_MANAGER_POLICY_AGREEMENT).
327  * When mode change is forced, the result of the before switch notifications are ignored. If
328  * agreement is required, if any callback returns an error code then further notifications
329  * before switch notifications are cancelled and all already notified callbacks are re-invoked
330  * with POWER_MANAGER_CALLBACK_AFTER set as callback type parameter. The index of the callback
331  * which returned error code during pre-switch notifications is stored (any error codes during
332  * callbacks re-invocation are ignored) and POWER_SYS_GetErrorCallback() can be used to get it.
333  * Regardless of the policies, if any callback returned an error code, an error code denoting in which phase
334  * the error occurred is returned when POWER_SYS_SetMode() exits.
335  * It is possible to enter any mode supported by the processor. Refer to the chip reference manual
336  * for list of available power modes. If it is necessary to switch into intermediate power mode prior to
337  * entering requested mode (for example, when switching from Run into Very low power wait through Very low
338  * power run mode), then the intermediate mode is entered without invoking the callback mechanism.
339  *
340  * Implements POWER_SYS_SetMode_Activity
341  *END**************************************************************************/
342 status_t POWER_SYS_SetMode(uint8_t powerModeIndex, power_manager_policy_t policy)
343 {
344  power_manager_user_config_t * configPtr; /* Local pointer to the requested user-defined power mode configuration */
345  status_t returnCode; /* Function return */
346  status_t errorCode;
347  bool successfulSwitch; /* Power mode switch is successful or not */
348  uint8_t currentStaticCallback = 0U; /* Index to array of statically registered call-backs */
349  power_manager_notify_struct_t notifyStruct; /* Callback notification structure */
350 
351  /* Driver is already initialized. */
352  DEV_ASSERT(gPowerManagerState.configs != NULL);
353  DEV_ASSERT(gPowerManagerState.configsNumber != 0U);
354 
355  /* Power mode index is valid. */
356  DEV_ASSERT(powerModeIndex < gPowerManagerState.configsNumber);
357 
358  /* Initialization of local pointer to the requested user-defined power mode configuration */
359  configPtr = (*gPowerManagerState.configs)[powerModeIndex];
360 
361  /* Reference to the requested user-defined power mode configuration is valid. */
362  DEV_ASSERT(configPtr != NULL);
363 
364  /* Default value of handle of last call-back that returned error */
365  gPowerManagerState.errorCallbackIndex = gPowerManagerState.staticCallbacksNumber;
366 
367  /* Set the transaction policy in the notification structure */
368  notifyStruct.policy = policy;
369 
370  /* Set the target power mode configuration in the notification structure */
371  notifyStruct.targetPowerConfigIndex = powerModeIndex;
372  notifyStruct.targetPowerConfigPtr = configPtr;
373 
374  /* Notify those which asked to be called before the power mode change */
376  returnCode = POWER_SYS_CallbacksManagement(&notifyStruct,&currentStaticCallback,policy);
377 
378  /* Power mode switch */
379 
380  /* In case that any call-back returned error code and policy doesn't force the mode switch go to after switch call-backs */
381  if ((policy == POWER_MANAGER_POLICY_FORCIBLE) || (returnCode == STATUS_SUCCESS))
382  {
383  returnCode = POWER_SYS_DoSetMode(configPtr);
384  successfulSwitch = (STATUS_SUCCESS == returnCode);
385  }
386  else
387  {
388  /* Unsuccessful switch */
389  successfulSwitch = false;
390  }
391 
392  if (successfulSwitch)
393  {
394  /* End of successful switch */
395 
396  /* Update current configuration index */
397  gPowerManagerState.currentConfig = powerModeIndex;
398 
399  /* Notify those which asked to be called after the power mode change */
400  notifyStruct.notifyType = POWER_MANAGER_NOTIFY_AFTER;
401  returnCode = POWER_SYS_CallbacksManagement(&notifyStruct,&currentStaticCallback,POWER_MANAGER_POLICY_FORCIBLE);
402  }
403  else
404  {
405  /* End of unsuccessful switch */
406 
407  /* Notify those which have been called before the power mode change */
409  errorCode = POWER_SYS_CallbacksManagement(&notifyStruct,&currentStaticCallback,POWER_MANAGER_POLICY_FORCIBLE);
410  (void)(errorCode);
411  }
412  return returnCode;
413 }
414 
415 /*******************************************************************************
416  * EOF
417  ******************************************************************************/
418 
status_t POWER_SYS_GetLastMode(uint8_t *powerModeIndexPtr)
This function returns the last successfully set power mode.
status_t POWER_SYS_SetMode(uint8_t powerModeIndex, power_manager_policy_t policy)
This function configures the power mode.
status_t POWER_SYS_Deinit(void)
This function deinitializes the Power manager.
status_t POWER_SYS_Init(power_manager_user_config_t *(*powerConfigsPtr)[], uint8_t configsNumber, power_manager_callback_user_config_t *(*callbacksPtr)[], uint8_t callbacksNumber)
Power manager initialization for operation.
status_t POWER_SYS_DoSetMode(const power_manager_user_config_t *const configPtr)
power_manager_policy_t
Power manager policies.
Definition: power_manager.h:94
power_manager_callback_user_config_t *(* staticCallbacks)[]
uint8_t POWER_SYS_GetErrorCallbackIndex(void)
This function returns the last failed notification callback.
power_manager_notify_t notifyType
power_manager_callback_type_t
The callback type indicates when a callback will be invoked.
power_manager_callback_user_config_t * POWER_SYS_GetErrorCallback(void)
This function returns the callback configuration structure for the last failed notification.
#define DEV_ASSERT(x)
Definition: devassert.h:78
status_t POWER_SYS_DoInit(void)
power_manager_callback_t callbackFunction
callback configuration structure
static status_t POWER_SYS_CallbacksManagement(power_manager_notify_struct_t *notifyStruct, uint8_t *currentStaticCallback, power_manager_policy_t policy)
power_manager_user_config_t * targetPowerConfigPtr
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:31
power_manager_callback_data_t * callbackData
power_manager_state_t gPowerManagerState
Power manager internal structure.
status_t POWER_SYS_DoDeinit(void)
power_manager_user_config_t *(* configs)[]
Power mode user configuration structure.
Power mode user configuration structure.
Definition: smc_hal.h:114
Power manager internal state structure.
power_manager_policy_t policy
power_manager_callback_type_t callbackType
status_t POWER_SYS_GetLastModeConfig(power_manager_user_config_t **powerModePtr)
This function returns the user configuration structure of the last successfully set power mode...