Power Management APIs

Power Management Hook Interface

void _sys_soc_resume(void)

Hook function to notify exit of a power policy.

The purpose of this function is to notify exit from deep sleep, low power state or device suspend only policy. States altered at _sys_soc_suspend() should be restored in this function. Exit from each policy requires different handling as follows.

Deep sleep policy exit: App should save information in SoC at _sys_soc_suspend() that will persist across deep sleep. This function should check that information to identify deep sleep recovery. In this case this function will restore states and resume execution at the point were system entered deep sleep. In this mode, this function is called with the interrupt stack. It is important that this function, before interrupts are enabled, restores the stack that was in use when system went to deep sleep. This is to avoid interfering interrupt handlers use of this stack.

Cold boot and deep sleep recovery happen at the same location. Since kernel does not store deep sleep state, kernel will call this function in both cases. It is the responsibility of the power manager application to identify whether it is cold boot or deep sleep exit using state information that it stores. If the function detects cold boot, then it returns immediately.

Low power state policy exit: Low power state policy does a CPU idle wait using a low power CPU idle state supported by the processor. This state is exited by an interrupt. In this case this function would be called from the interrupt’s ISR context. Any state altered at _sys_soc_suspend should be restored and the function should return quickly.

Device suspend only policy exit: This function will be called at the exit of kernel’s CPU idle wait if device suspend only policy was used. Resume operations should be done for devices that were suspended in _sys_soc_suspend(). This function is called in ISR context and it should return quickly.

Return
will not return to caller in deep sleep recovery

int _sys_soc_suspend(int32_t ticks)

Hook function to allow power policy entry.

This function is called by the kernel when it is about to idle. It is passed the number of clock ticks that the kernel calculated as available time to idle. This function should compare this time with the wake latency of various power saving schemes that the power manager application implements and use the one that fits best. The power saving schemes can be mapped to following policies.

Deep sleep policy: This turns off the core voltage rail and system clock, while RAM is retained. This would save most power but would also have a high wake latency. CPU loses state so this function should save CPU states in RAM and the location in this function where system should resume execution at resume. It should re-enable interrupts and return SYS_PM_DEEP_SLEEP.

Low power state policy: Peripherals can be turned off and clocks can be gated depending on time available. Then switches to CPU low power state. In this state the CPU is still active but in a low power state and does not lose any state. This state is exited by an interrupt from where the _sys_soc_resume() will be called. To allow interrupts to occur, this function should ensure that interrupts are atomically enabled before going to the low power CPU idle state. The atomicity of enabling interrupts before entering cpu idle wait is essential to avoid a task switch away from the kernel idle task before the cpu idle wait is reached. This function should return SYS_PM_LOW_POWER_STATE.

Device suspend only policy: This function can take advantage of the kernel’s idling logic by turning off peripherals and clocks depending on available time. It can return SYS_PM_DEVICE_SUSPEND_ONLY to indicate the kernel should do its own CPU idle wait. After the Kernel’s idle wait is completed or if any interrupt occurs, the _sys_soc_resume() function will be called to allow restoring of altered states. Interrupts should not be turned on in this case.

If this function decides to not do any operation then it should return SYS_PM_NOT_HANDLED to let kernel do its normal idle processing.

This function is entered with interrupts disabled. It should re-enable interrupts if it does CPU low power wait or deep sleep.

Parameters
  • ticks: the upcoming kernel idle time
Return Value
  • SYS_PM_NOT_HANDLED: If No PM operations done.
  • SYS_PM_DEVICE_SUSPEND_ONLY: If only devices were suspended.
  • SYS_PM_LOW_POWER_STATE: If LPS policy entered.
  • SYS_PM_DEEP_SLEEP: If Deep Sleep policy entered.

Device Power Management APIs

void device_busy_set(struct device *busy_dev)

Indicate that the device is in the middle of a transaction.

Called by a device driver to indicate that it is in the middle of a transaction.

Parameters
  • busy_dev: Pointer to device structure of the driver instance.

void device_busy_clear(struct device *busy_dev)

Indicate that the device has completed its transaction.

Called by a device driver to indicate the end of a transaction.

Parameters
  • busy_dev: Pointer to device structure of the driver instance.

int device_pm_nop(struct device *unused_device, int unused_policy)

No-op function to initialize unimplemented pm hooks.

This function should be used to initialize device pm hooks for which a device has no operation.

Parameters
  • unused_device: Unused
  • unused_policy: Unused
Return Value
  • 0: Always returns 0

static int device_suspend(struct device *device, int pm_policy)

Call the suspend function of a device.

Called by the Power Manager application to let the device do any policy based PM suspend operations.

Parameters
  • device: Pointer to device structure of the driver instance.
  • pm_policy: PM policy for which this call is made.
Return Value
  • 0: If successful.
  • Errno: Negative errno code if failure.

static int device_resume(struct device *device, int pm_policy)

Call the resume function of a device.

Called by the Power Manager application to let the device do any policy based PM resume operations.

Parameters
  • device: Pointer to device structure of the driver instance.
  • pm_policy: PM policy for which this call is made.
Return Value
  • 0: If successful.
  • Errno: Negative errno code if failure.

void device_list_get(struct device **device_list, int *device_count)

Gets the device structure list array and device count.

Called by the Power Manager application to get the list of device structures associated with the devices in the system. The PM app would use this list to create its own sorted list based on the order it wishes to suspend or resume the devices.

Parameters
  • device_list: Pointer to receive the device list array
  • device_count: Pointer to receive the device count

int device_any_busy_check(void)

Check if any device is in the middle of a transaction.

Called by an application to see if any device is in the middle of a critical transaction that cannot be interrupted.

Return Value
  • 0: if no device is busy
  • -EBUSY: if any device is busy

int device_busy_check(struct device *chk_dev)

Check if a specific device is in the middle of a transaction.

Called by an application to see if a particular device is in the middle of a critical transaction that cannot be interrupted.

Parameters
  • chk_dev: Pointer to device structure of the specific device driver the caller is interested in.
Return Value
  • 0: if the device is not busy
  • -EBUSY: if the device is busy

DEFINE_DEVICE_PM_OPS(_name, _suspend, _resume) struct device_pm_ops _name##_dev_pm_ops = { \ .suspend = _suspend, \ .resume = _resume, \ }

Helper macro to define the device_pm_ops structure.

Parameters
  • _name: name of the device
  • _suspend: name of the suspend function
  • _resume: name of the resume function

DEVICE_PM_OPS_GET(_name) (&_name##_dev_pm_ops)

Macro to get a pointer to the device_ops_structure.

Will return the name of the structure that was created using DEFINE_PM_OPS macro if CONFIG_DEVICE_POWER_MANAGEMENT is defined. Otherwise, will return NULL.

Parameters
  • _name: name of the device

DEVICE_PM_OPS_DECLARE(_name) extern struct device_pm_ops _name##_dev_pm_ops

Macro to declare the device_pm_ops structure.

The declaration would be added if CONFIG_DEVICE_POWER_MANAGEMENT is defined. Otherwise this macro will not add anything.

Parameters
  • _name: name of the device

struct device_pm_ops
#include <device.h>

Structure holding handlers for device PM operations.

Parameters
  • suspend: Pointer to the handler for suspend operations
  • resume: Pointer to the handler for resume operations