blob: f90dee945785717293b1f14067f95985d0e87109 [file] [log] [blame]
/*
* Copyright (c) 2020 Intel corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_PM_STATE_H_
#define ZEPHYR_INCLUDE_PM_STATE_H_
#include <sys/util.h>
#include <devicetree.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup pm_states Power Management States
* @ingroup power_management_api
* @{
*/
/**
* @enum pm_state Power management state
*/
enum pm_state {
/**
* @brief Runtime active state
*
* The system is fully powered and active.
*
* @note This state is correlated with ACPI G0/S0 state
*/
PM_STATE_ACTIVE,
/**
* @brief 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
*/
PM_STATE_RUNTIME_IDLE,
/**
* @brief 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
*/
PM_STATE_SUSPEND_TO_IDLE,
/**
* @brief 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
*/
PM_STATE_STANDBY,
/**
* @brief 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
*/
PM_STATE_SUSPEND_TO_RAM,
/**
* @brief 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
*/
PM_STATE_SUSPEND_TO_DISK,
/**
* @brief 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
*/
PM_STATE_SOFT_OFF
};
/**
* Information about a power management state
*/
struct pm_state_info {
enum pm_state state;
/**
* Some platforms have multiple states that map to
* one Zephyr power state. This property allows the platform
* distinguish them. e.g:
*
* power-states {
* state0: state0 {
* compatible = "zephyr,power-state";
* power-state-name = "suspend-to-idle";
* substate-id = <1>;
* min-residency-us = <10000>;
* exit-latency-us = <100>;
* };
* state1: state1 {
* compatible = "zephyr,power-state";
* power-state-name = "suspend-to-idle";
* substate-id = <2>;
* min-residency-us = <20000>;
* exit-latency-us = <200>;
* };
* }
*/
uint8_t substate_id;
/**
* Minimum residency duration in microseconds. It is the minimum
* time for a given idle state to be worthwhile energywise.
*
* @note 0 means that this property is not available for this state.
*/
uint32_t min_residency_us;
/**
* Worst case latency in microseconds required to exit the idle state.
*
* @note 0 means that this property is not available for this state.
*/
uint32_t exit_latency_us;
};
/**
* @brief Construct a pm_state_info from 'cpu-power-states' property at index 'i'
*
* @param node_id A node identifier with compatible zephyr,power-state
* @param i index into cpu-power-states property
* @return pm_state_info item from 'cpu-power-states' property at index 'i'
*/
#define PM_STATE_INFO_DT_ITEM_BY_IDX(node_id, i) \
{ \
.state = DT_ENUM_IDX(DT_PHANDLE_BY_IDX(node_id, \
cpu_power_states, i), power_state_name), \
.substate_id = DT_PROP_BY_PHANDLE_IDX_OR(node_id, \
cpu_power_states, i, substate_id, 0), \
.min_residency_us = DT_PROP_BY_PHANDLE_IDX_OR(node_id, \
cpu_power_states, i, min_residency_us, 0),\
.exit_latency_us = DT_PROP_BY_PHANDLE_IDX_OR(node_id, \
cpu_power_states, i, exit_latency_us, 0),\
},
/**
* @brief Length of 'cpu-power-states' property
*
* @param node_id A node identifier with compatible zephyr,power-state
* @return length of 'cpu-power-states' property
*/
#define PM_STATE_DT_ITEMS_LEN(node_id) \
DT_PROP_LEN_OR(node_id, cpu_power_states, 0)
/**
* @brief Macro function to construct enum pm_state item in UTIL_LISTIFY
* extension.
*
* @param child child index in UTIL_LISTIFY extension.
* @param node_id A node identifier with compatible zephyr,power-state
* @return macro function to construct a pm_state_info
*/
#define PM_STATE_INFO_DT_ITEMS_LISTIFY_FUNC(child, node_id) \
PM_STATE_INFO_DT_ITEM_BY_IDX(node_id, child)
/**
* @brief Macro function to construct a list of 'pm_state_info' items by
* UTIL_LISTIFY func
*
* Example devicetree fragment:
* cpus {
* ...
* cpu0: cpu@0 {
* device_type = "cpu";
* ...
* cpu-power-states = <&state0 &state1>;
* };
* };
*
* ...
* power-states {
* state0: state0 {
* compatible = "zephyr,power-state";
* power-state-name = "suspend-to-idle";
* min-residency-us = <10000>;
* exit-latency-us = <100>;
* };
*
* state1: state1 {
* compatible = "zephyr,power-state";
* power-state-name = "suspend-to-ram";
* min-residency-us = <50000>;
* exit-latency-us = <500>;
* };
* };
*
* Example usage: *
* const struct pm_state_info states[] =
* PM_STATE_INFO_DT_ITEMS_LIST(DT_NODELABEL(cpu0));
*
* @param node_id A node identifier with compatible zephyr,power-state
* @return an array of struct pm_state_info.
*/
#define PM_STATE_INFO_DT_ITEMS_LIST(node_id) { \
UTIL_LISTIFY(PM_STATE_DT_ITEMS_LEN(node_id), \
PM_STATE_INFO_DT_ITEMS_LISTIFY_FUNC,\
node_id) \
}
/**
* @brief Construct a pm_state enum from 'cpu-power-states' property
* at index 'i'
*
* @param node_id A node identifier with compatible zephyr,power-state
* @param i index into cpu-power-states property
* @return pm_state item from 'cpu-power-states' property at index 'i'
*/
#define PM_STATE_DT_ITEM_BY_IDX(node_id, i) \
DT_ENUM_IDX(DT_PHANDLE_BY_IDX(node_id, \
cpu_power_states, i), power_state_name),
/**
* @brief Macro function to construct enum pm_state item in UTIL_LISTIFY
* extension.
*
* @param child child index in UTIL_LISTIFY extension.
* @param node_id A node identifier with compatible zephyr,power-state
* @return macro function to construct a pm_state enum
*/
#define PM_STATE_DT_ITEMS_LISTIFY_FUNC(child, node_id) \
PM_STATE_DT_ITEM_BY_IDX(node_id, child)
/**
* @brief Macro function to construct a list of enum pm_state items by
* UTIL_LISTIFY func
*
* Example devicetree fragment:
* cpus {
* ...
* cpu0: cpu@0 {
* device_type = "cpu";
* ...
* cpu-power-states = <&state0 &state1>;
* };
* };
*
* ...
* state0: state0 {
* compatible = "zephyr,power-state";
* power-state-name = "suspend-to-idle";
* min-residency-us = <10000>;
* exit-latency-us = <100>;
* };
*
* state1: state1 {
* compatible = "zephyr,power-state";
* power-state-name = "suspend-to-ram";
* min-residency-us = <50000>;
* exit-latency-us = <500>;
* };
*
* Example usage: *
* const enum pm_state states[] = PM_STATE_DT_ITEMS_LIST(DT_NODELABEL(cpu0));
*
* @param node_id A node identifier with compatible zephyr,power-state
* @return an array of enum pm_state items.
*/
#define PM_STATE_DT_ITEMS_LIST(node_id) { \
UTIL_LISTIFY(PM_STATE_DT_ITEMS_LEN(node_id),\
PM_STATE_DT_ITEMS_LISTIFY_FUNC,\
node_id) \
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif