This is the documentation for the latest (main) development branch of Zephyr. If you are looking for the documentation of previous releases, use the drop-down menu on the left and select the desired version.

Power Management

Zephyr RTOS power management subsystem provides several means for a system integrator to implement power management support that can take full advantage of the power saving features of SOCs.

Terminology

SOC interface

This is a general term for the components that have knowledge of the SOC and provide interfaces to the hardware features. It will abstract the SOC specific implementations to the applications and the OS.

Idle Thread

A system thread that runs when there are no other threads ready to run.

Power gating

Power gating reduces power consumption by shutting off current to blocks of the integrated circuit that are not in use.

Power State

SOC Power State describes processor and device power states implemented at the SOC level. Power states are represented by pm_state and each one has a different meaning.

Device Runtime Power Management

Device Runtime Power Management (PM) refers the capability of devices be able of saving energy independently of the the system. Devices will keep reference of their usage and will automatically be suspended or resumed. This feature is enabled via the :CONFIG_PM_DEVICE_RUNTIME Kconfig option.

Overview

The interfaces and APIs provided by the power management subsystem are designed to be architecture and SOC independent. This enables power management implementations to be easily adapted to different SOCs and architectures.

The architecture and SOC independence is achieved by separating the core infrastructure and the SOC specific implementations. The SOC specific implementations are abstracted to the application and the OS using hardware abstraction layers.

The power management features are classified into the following categories.

  • System Power Management

  • Device Power Management

System Power Management

The kernel enters the idle state when it has nothing to schedule. If enabled via the CONFIG_PM Kconfig option, the Power Management Subsystem can put an idle system in one of the supported power states, based on the selected power management policy and the duration of the idle time allotted by the kernel.

It is an application responsibility to set up a wake up event. A wake up event will typically be an interrupt triggered by one of the SoC peripheral modules such as a SysTick, RTC, counter, or GPIO. Depending on the power mode entered, only some SoC peripheral modules may be active and can be used as a wake up source.

The following diagram describes system power management:

System power management

Some handful examples using different power management features:

Power States

The power management subsystem contains a set of states based on power consumption and context retention.

The list of available power states is defined by pm_state. In general power states with higher indexes will offer greater power savings and have higher wake latencies. Following is a thorough list of available states:

enumerator PM_STATE_ACTIVE

Runtime active state.

The system is fully powered and active.

Note

This state is correlated with ACPI G0/S0 state

enumerator PM_STATE_RUNTIME_IDLE

Runtime idle state.

Runtime idle is a system sleep state in which all of the cores enter deepest possible idle state and wait for interrupts, no requirements for the devices, leaving them at the states where they are.

Note

This state is correlated with ACPI S0ix state

enumerator PM_STATE_SUSPEND_TO_IDLE

Suspend to idle state.

The system goes through a normal platform suspend where it puts all of the cores in deepest possible idle state and may puts peripherals into low-power states. No operating state is lost (ie. the cpu core does not lose execution context), so the system can go back to where it left off easily enough.

Note

This state is correlated with ACPI S1 state

enumerator PM_STATE_STANDBY

Standby state.

In addition to putting peripherals into low-power states all non-boot CPUs are powered off. It should allow more energy to be saved relative to suspend to idle, but the resume latency will generally be greater than for that state. But it should be the same state with suspend to idle state on uniprocesser system.

Note

This state is correlated with ACPI S2 state

enumerator PM_STATE_SUSPEND_TO_RAM

Suspend to ram state.

This state offers significant energy savings by powering off as much of the system as possible, where memory should be placed into the self-refresh mode to retain its contents. The state of devices and CPUs is saved and held in memory, and it may require some boot- strapping code in ROM to resume the system from it.

Note

This state is correlated with ACPI S3 state

enumerator PM_STATE_SUSPEND_TO_DISK

Suspend to disk state.

This state offers significant energy savings by powering off as much of the system as possible, including the memory. The contents of memory are written to disk or other non-volatile storage, and on resume it’s read back into memory with the help of boot-strapping code, restores the system to the same point of execution where it went to suspend to disk.

Note

This state is correlated with ACPI S4 state

enumerator PM_STATE_SOFT_OFF

Soft off state.

This state consumes a minimal amount of power and requires a large latency in order to return to runtime active state. The contents of system(CPU and memory) will not be preserved, so the system will be restarted as if from initial power-up and kernel boot.

Note

This state is correlated with ACPI G2/S5 state

Power States Constraint

The power management subsystem allows different Zephyr components and applications to set constraints on various power states preventing the system from transitiioning into these states. This can be used by devices when executing tasks in background to avoid the system to go to a specific state where it would lose context. Constraints can be set, released and checked using the follow APIs:

void pm_constraint_set(enum pm_state state)

Set a constraint for a power state.

Disabled state cannot be selected by the Zephyr power management policies. Application defined policy should use the pm_constraint_get function to check if given state is enabled and could be used.

Note

This API is refcount

Parameters
  • state[in] Power state to be disabled.

void pm_constraint_release(enum pm_state state)

Release a constraint for a power state.

Enabled state can be selected by the Zephyr power management policies. Application defined policy should use the pm_constraint_get function to check if given state is enabled and could be used. By default all power states are enabled.

Note

This API is refcount

Parameters
  • state[in] Power state to be enabled.

bool pm_constraint_get(enum pm_state state)

Check if particular power state is enabled.

This function returns true if given power state is enabled.

Parameters
  • state[in] Power state.

Power Management Policies

The power management subsystem supports the following power management policies:

  • Residency based

  • Application defined

The policy manager is responsible for informing the power subsystem which power state the system should transition to based on states defined by the platform and possible runtime constraints

Information about states can be found in the device tree, see dts/bindings/power/state.yaml.

Residency

The power management system enters the power state which offers the highest power savings, and with a minimum residency value (in device tree, see dts/bindings/power/state.yaml) less than or equal to the scheduled system idle time duration.

This policy also accounts for the time necessary to become active again. The core logic used by this policy to select the best power state is:

if (time_to_next_scheduled_event >= (state.min_residency_us + state.exit_latency))) {
   return state
}

Application

The power management policy is defined by the application which has to implement the following function.

struct pm_state_info pm_policy_next_state(int32_t ticks);

In this policy the application is free to decide which power state the system should transition to based on the remaining time for the next scheduled timeout.

An example of an application that defines its own policy can be found in tests/subsys/pm/power_mgmt/.

Device Power Management Infrastructure

The device power management infrastructure consists of interfaces to the Device Driver Model. These APIs send control commands to the device driver to update its power state or to get its current power state.

Zephyr RTOS supports two methods of doing device power management.

  • Runtime Device Power Management

  • System Power Management

Runtime Device Power Management

In this method, the application or any component that deals with devices directly and has the best knowledge of their use, performs the device power management. This saves power if some devices that are not in use can be turned off or put in power saving mode. This method allows saving power even when the CPU is active. The components that use the devices need to be power aware and should be able to make decisions related to managing device power.

In this method, the SOC interface can enter CPU or SOC power states quickly when pm_system_suspend() gets called. This is because it does not need to spend time doing device power management if the devices are already put in the appropriate power state by the application or component managing the devices.

System Power Management

In this method device power management is mostly done inside pm_system_suspend() along with entering a CPU or SOC power state.

If a decision to enter a lower power state is made, the implementation would enter it only after checking if the devices are not in the middle of a hardware transaction that cannot be interrupted. This method can be used in implementations where the applications and components using devices are not expected to be power aware and do not implement runtime device power management.

../../_images/central_method.svg

This method can also be used to emulate a hardware feature supported by some SOCs which triggers automatic entry to a lower power state when all devices are idle. Refer to Busy Status Indication to see how to indicate whether a device is busy or idle.

Device Power Management States

The power management subsystem defines four device states. These states are classified based on the degree of device context that gets lost in those states, kind of operations done to save power, and the impact on the device behavior due to the state transition. Device context includes device registers, clocks, memory etc.

The four device power states:

PM_DEVICE_STATE_ACTIVE

Normal operation of the device. All device context is retained.

PM_DEVICE_STATE_LOW_POWER

Device context is preserved by the HW and need not be restored by the driver.

PM_DEVICE_STATE_SUSPENDED

Most device context is lost by the hardware. Device drivers must save and restore or reinitialize any context lost by the hardware.

PM_DEVICE_STATE_OFF

Power has been fully removed from the device. The device context is lost when this state is entered. Need to reinitialize the device when powering it back on.

Device Power Management Operations

Zephyr RTOS power management subsystem provides a control function interface to device drivers to indicate power management operations to perform. Each device driver defines:

  • The device’s supported power states.

  • The device’s supported transitions between power states.

  • The device’s necessary operations to handle the transition between power states.

The following are some examples of operations that the device driver may perform in transition between power states:

  • Save/Restore device states.

  • Gate/Un-gate clocks.

  • Gate/Un-gate power.

  • Mask/Un-mask interrupts.

Device Model with Power Management Support

Drivers initialize the devices using macros. See Device Driver Model for details on how these macros are used. Use the DEVICE_DEFINE macro to initialize drivers providing power management support via the PM control function. One of the macro parameters is the pointer to the pm_control handler function. If the driver doesn’t implement any power control operations, it can initialize the corresponding pointer with NULL.

Device Power Management API

The SOC interface and application use these APIs to perform power management operations on the devices.

Get Device List

size_t z_device_get_all_static(struct device const **device_list);

The Zephyr RTOS kernel internally maintains a list of all devices in the system. The SOC interface uses this API to get the device list. The SOC interface can use the list to identify the devices on which to execute power management operations.

Note

Ensure that the SOC interface does not alter the original list. Since the kernel uses the original list, it must remain unchanged.

Device Set Power State

int pm_device_state_set(const struct device *dev, enum pm_device_state state);

Calls the pm_control() handler function implemented by the device driver with the provided state.

Device Get Power State

int pm_device_state_get(const struct device *dev, enum pm_device_state *state);

Busy Status Indication

The SOC interface executes some power policies that can turn off power to devices, causing them to lose their state. If the devices are in the middle of some hardware transaction, like writing to flash memory when the power is turned off, then such transactions would be left in an inconsistent state. This infrastructure guards such transactions by indicating to the SOC interface that the device is in the middle of a hardware transaction.

When the pm_system_suspend() is called, depending on the power state returned by the policy manager, the system may suspend or put devices in low power if they are not marked as busy.

Here are the APIs used to set, clear, and check the busy status of devices.

Indicate Busy Status API

void device_busy_set(const struct device *busy_dev);

Sets a bit corresponding to the device, in a data structure maintained by the kernel, to indicate whether or not it is in the middle of a transaction.

Clear Busy Status API

void device_busy_clear(const struct device *busy_dev);

Clears the bit corresponding to the device in a data structure maintained by the kernel to indicate that the device is not in the middle of a transaction.

Check Busy Status of Single Device API

int device_busy_check(const struct device *chk_dev);

Checks whether a device is busy. The API returns 0 if the device is not busy.

This API is used by the system power management.

Check Busy Status of All Devices API

int device_any_busy_check(void);

Checks if any device is busy. The API returns 0 if no device in the system is busy.

Wakeup capability

Some devices are capable of waking the system up from a sleep state. When a device has such capability, applications can enable or disable this feature on a device dynamically using pm_device_wakeup_enable().

This property can be set on device declaring the property wakeup-source in the device node in devicetree. For example, this devicetree fragment sets the gpio0 device as a “wakeup” source:

gpio0: gpio@40022000 {
        compatible = "ti,cc13xx-cc26xx-gpio";
        reg = <0x40022000 0x400>;
        interrupts = <0 0>;
        status = "disabled";
        label = "GPIO_0";
        gpio-controller;
        wakeup-source;
        #gpio-cells = <2>;
};

By default, “wakeup” capable devices do not have this functionality enabled during the device initialization. Applications can enable this functionality later calling pm_device_wakeup_enable().

Note

This property is only used by the system power management to identify devices that should not be suspended. It is responsability of driver or the application to do any additional configuration required by the device to support it.

Device Runtime Power Management

The Device Runtime Power Management framework is an Active Power Management mechanism which reduces the overall system Power consumtion by suspending the devices which are idle or not being used while the System is active or running.

The framework uses pm_device_state_set() API set the device power state accordingly based on the usage count.

The interfaces and APIs provided by the Device Runtime PM are designed to be generic and architecture independent.

Device Runtime Power Management API

The Device Drivers use these APIs to perform device runtime power management operations on the devices.

Enable Device Runtime Power Management of a Device API

void pm_device_enable(const struct device *dev);

Enables Runtime Power Management of the device.

Disable Device Runtime Power Management of a Device API

void pm_device_disable(const struct device *dev);

Disables Runtime Power Management of the device.

Resume Device asynchronously API

int pm_device_get_async(const struct device *dev);

Marks the device as being used. This API will asynchronously bring the device to resume state if it was suspended. If the device was already active, it just increments the device usage count. The API returns 0 on success.

Device drivers can monitor this operation to finish calling pm_device_wait().

Resume Device synchronously API

int pm_device_get(const struct device *dev);

Marks the device as being used. It will bring up or resume the device if it is in suspended state based on the device usage count. This call is blocked until the device PM state is changed to active. The API returns 0 on success.

Suspend Device asynchronously API

int pm_device_put_async(const struct device *dev);

Releases a device. This API asynchronously puts the device to suspend state if not already in suspend state if the usage count of this device reaches 0.

Device drivers can monitor this operation to finish calling pm_device_wait().

Suspend Device synchronously API

int pm_device_put(const struct device *dev);

Marks the device as being released. It will put the device to suspended state if is is in active state based on the device usage count. This call is blocked until the device PM state is changed to resume. The API returns 0 on success. This call is blocked until the device is suspended.

Power Management Configuration Flags

The Power Management features can be individually enabled and disabled using the following configuration flags.

CONFIG_PM

This flag enables the power management subsystem.

CONFIG_PM_DEVICE

This flag is enabled if the SOC interface and the devices support device power management.

CONFIG_PM_DEVICE_RUNTIME

This flag enables the Runtime Power Management.

API Reference

Power Management Hook Interface

group power_management_hook_interface

Power Management Hooks.

Functions

void pm_power_state_set(struct pm_state_info info)

Put processor into a power state.

This function implements the SoC specific details necessary to put the processor into available power states.

Parameters
  • info – Power state which should be used in the ongoing suspend operation.

void pm_power_state_exit_post_ops(struct pm_state_info info)

Do any SoC or architecture specific post ops after sleep state exits.

This function is a place holder to do any operations that may be needed to be done after sleep state exits. Currently it enables interrupts after resuming from sleep state. In future, the enabling of interrupts may be moved into the kernel.

System Power Management APIs

group system_power_management_api

System Power Management API.

Functions

void pm_power_state_force(struct pm_state_info info)

Force usage of given power state.

This function overrides decision made by PM policy forcing usage of given power state immediately.

Note

This function can only run in thread context

Parameters
  • info – Power state which should be used in the ongoing suspend operation.

void pm_notifier_register(struct pm_notifier *notifier)

Register a power management notifier.

Register the given notifier from the power management notification list.

Parameters
int pm_notifier_unregister(struct pm_notifier *notifier)

Unregister a power management notifier.

Remove the given notifier from the power management notification list. After that this object callbacks will not be called.

Parameters
Returns

0 if the notifier was successfully removed, a negative value otherwise.

struct pm_notifier
#include <pm.h>

Power management notifier struct

This struct contains callbacks that are called when the target enters and exits power states.

As currently implemented the entry callback is invoked when transitioning from PM_STATE_ACTIVE to another state, and the exit callback is invoked when transitioning from a non-active state to PM_STATE_ACTIVE. This behavior may change in the future.

Note

These callbacks can be called from the ISR of the event that caused the kernel exit from idling.

Note

It is not allowed to call pm_notifier_unregister or pm_notifier_register from these callbacks because they are called with the spin locked in those functions.

Public Members

void (*state_entry)(enum pm_state state)

Application defined function for doing any target specific operations for power state entry.

void (*state_exit)(enum pm_state state)

Application defined function for doing any target specific operations for power state exit.

Device Power Management APIs

group device_power_management_api

Device Power Management API.

Defines

INIT_PM_DEVICE_RUNTIME(obj)
device_pm_control_nop

Alias for legacy use of device_pm_control_nop

Typedefs

typedef int (*pm_device_action_cb_t)(const struct device *dev, enum pm_device_action action)

Device PM action callback.

Parameters
  • dev – Device instance.

  • action – Requested action.

Returns

  • 0 – If successful.

  • -ENOTSUP – If the requested action is not supported.

  • Errno – Other negative errno on failure.

Enums

enum pm_device_state

Device power states.

Values:

enumerator PM_DEVICE_STATE_ACTIVE

Device is in active or regular state.

enumerator PM_DEVICE_STATE_LOW_POWER

Device is in low power state.

Note

Device context is preserved.

enumerator PM_DEVICE_STATE_SUSPENDED

Device is suspended.

Note

Device context may be lost.

enumerator PM_DEVICE_STATE_OFF

Device is turned off (power removed).

Note

Device context is lost.

enum pm_device_flag

Device PM flags.

Values:

enumerator PM_DEVICE_FLAG_BUSY

Indicate if the device is busy or not.

enumerator PM_DEVICE_FLAGS_WS_CAPABLE

Indicates whether or not the device is capable of waking the system up.

enumerator PM_DEVICE_FLAGS_WS_ENABLED

Indicates if the device is being used as wakeup source.

enumerator PM_DEVICE_FLAG_TRANSITIONING

Indicates that the device is changing its state

enumerator PM_DEVICE_FLAG_COUNT

Number of flags (internal use only).

enum pm_device_action

Device PM actions.

Values:

enumerator PM_DEVICE_ACTION_SUSPEND

Suspend.

enumerator PM_DEVICE_ACTION_RESUME

Resume.

enumerator PM_DEVICE_ACTION_TURN_OFF

Turn off.

enumerator PM_DEVICE_ACTION_FORCE_SUSPEND

Force suspend.

enumerator PM_DEVICE_ACTION_LOW_POWER

Low power.

Functions

const char *pm_device_state_str(enum pm_device_state state)

Get name of device PM state.

Parameters
  • state – State id which name should be returned

int pm_device_state_set(const struct device *dev, enum pm_device_state state)

Set the power state of a device.

This function calls the device PM control callback so that the device does the necessary operations to put the device into the given state.

Note

Some devices may not support all device power states.

Parameters
  • dev – Device instance.

  • state – Device power state to be set.

Returns

  • 0 – If successful.

  • -ENOTSUP – If requested state is not supported.

  • -EALREADY – If device is already at the requested state.

  • -EBUSY – If device is changing its state.

  • Errno – Other negative errno on failure.

int pm_device_state_get(const struct device *dev, enum pm_device_state *state)

Obtain the power state of a device.

Parameters
  • dev – Device instance.

  • state – Pointer where device power state will be stored.

Returns

  • 0 – If successful.

  • -ENOSYS – If device does not implement power management.

void pm_device_busy_set(const struct device *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
  • dev – Pointer to device structure of the driver instance.

void pm_device_busy_clear(const struct device *dev)

Indicate that the device has completed its transaction.

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

Parameters
  • dev – Pointer to device structure of the driver instance.

bool pm_device_is_any_busy(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.

Returns

  • false – if no device is busy

  • true – if any device is busy

bool pm_device_is_busy(const struct device *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
  • dev – Pointer to device structure of the specific device driver the caller is interested in.

Returns

  • false – if the device is not busy

  • true – if the device is busy

static inline void device_busy_set(const struct device *dev)
static inline void device_busy_clear(const struct device *dev)
static inline int device_any_busy_check(void)
static inline int device_busy_check(const struct device *dev)
bool pm_device_wakeup_enable(struct device *dev, bool enable)

Enable a power management wakeup source.

Enable a wakeup source. This will keep the current device active when the system is suspended, allowing it to be used to wake up the system.

Parameters
  • dev – device object to enable.

  • enabletrue to enable or false to disable

Returns

  • true – if the wakeup source was successfully enabled.

  • false – if the wakeup source was not successfully enabled.

bool pm_device_wakeup_is_enabled(const struct device *dev)

Check if a power management wakeup source is enabled.

Checks if a wake up source is enabled.

Parameters
  • dev – device object to check.

Returns

  • true – if the wakeup source is enabled.

  • false – if the wakeup source is not enabled.

bool pm_device_wakeup_is_capable(const struct device *dev)

Check if a device is wake up capable.

Parameters
  • dev – device object to check.

Returns

  • true – if the device is wake up capable.

  • false – if the device is not wake up capable.

struct pm_device
#include <device.h>

Device PM info.

Public Members

const struct device *dev

Pointer to the device

struct k_mutex lock

Lock to synchronize the get/put operations

bool enable

Device pm enable flag

uint32_t usage

Device usage count

struct k_work_delayable work

Work object for asynchronous calls

struct k_condvar condvar

Event conditional var to listen to the sync request events

enum pm_device_state state

Device power state

pm_device_action_cb_t action_cb

Device PM action callback