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