UTIL_LISTIFY is deprecated. Replacing it with LISTIFY. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
333 lines
8.6 KiB
C
333 lines
8.6 KiB
C
/*
|
|
* 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
|
|
|
|
/**
|
|
* @brief System Power Management States
|
|
* @defgroup subsys_pm_states States
|
|
* @ingroup subsys_pm
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @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,
|
|
/** Number of power management states (internal use) */
|
|
PM_STATE_COUNT,
|
|
};
|
|
|
|
/**
|
|
* 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:
|
|
*
|
|
* @code{.dts}
|
|
* 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>;
|
|
* };
|
|
* };
|
|
* @endcode
|
|
*/
|
|
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;
|
|
};
|
|
|
|
/** @cond INTERNAL_HIDDEN */
|
|
|
|
/**
|
|
* @brief Helper macro to initialize an entry of a struct pm_state_info array
|
|
* when using UTIL_LISTIFY in PM_STATE_INFO_LIST_FROM_DT_CPU.
|
|
*
|
|
* @param i UTIL_LISTIFY entry index.
|
|
* @param node_id A node identifier with compatible zephyr,power-state
|
|
*/
|
|
#define Z_PM_STATE_INFO_FROM_DT_CPU(i, node_id) \
|
|
PM_STATE_INFO_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i))
|
|
|
|
/**
|
|
* @brief Helper macro to initialize an entry of a struct pm_state array when
|
|
* using UTIL_LISTIFY in PM_STATE_LIST_FROM_DT_CPU.
|
|
*
|
|
* @param i UTIL_LISTIFY entry index.
|
|
* @param node_id A node identifier with compatible zephyr,power-state
|
|
*/
|
|
#define Z_PM_STATE_FROM_DT_CPU(i, node_id) \
|
|
PM_STATE_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i))
|
|
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @brief Initializer for struct pm_state_info given a DT node identifier with
|
|
* zephyr,power-state compatible.
|
|
*
|
|
* @param node_id A node identifier with compatible zephyr,power-state
|
|
*/
|
|
#define PM_STATE_INFO_DT_INIT(node_id) \
|
|
{ \
|
|
.state = PM_STATE_DT_INIT(node_id), \
|
|
.substate_id = DT_PROP_OR(node_id, substate_id, 0), \
|
|
.min_residency_us = DT_PROP_OR(node_id, min_residency_us, 0), \
|
|
.exit_latency_us = DT_PROP_OR(node_id, exit_latency_us, 0), \
|
|
}
|
|
|
|
/**
|
|
* @brief Initializer for enum pm_state given a DT node identifier with
|
|
* zephyr,power-state compatible.
|
|
*
|
|
* @param node_id A node identifier with compatible zephyr,power-state
|
|
*/
|
|
#define PM_STATE_DT_INIT(node_id) \
|
|
DT_ENUM_IDX(node_id, power_state_name)
|
|
|
|
/**
|
|
* @brief Obtain number of CPU power states supported by the given CPU node
|
|
* identifier.
|
|
*
|
|
* @param node_id A CPU node identifier.
|
|
* @return Number of supported CPU power states.
|
|
*/
|
|
#define DT_NUM_CPU_POWER_STATES(node_id) \
|
|
DT_PROP_LEN_OR(node_id, cpu_power_states, 0)
|
|
|
|
/**
|
|
* @brief Initialize an array of struct pm_state_info with information from all
|
|
* the states present in the given CPU node identifier.
|
|
*
|
|
* Example devicetree fragment:
|
|
*
|
|
* @code{.dts}
|
|
* 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>;
|
|
* };
|
|
* };
|
|
* @endcode
|
|
*
|
|
* Example usage:
|
|
*
|
|
* @code{.c}
|
|
* const struct pm_state_info states[] =
|
|
* PM_STATE_INFO_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0));
|
|
* @endcode
|
|
*
|
|
* @param node_id A CPU node identifier.
|
|
*/
|
|
#define PM_STATE_INFO_LIST_FROM_DT_CPU(node_id) \
|
|
{ \
|
|
LISTIFY(DT_NUM_CPU_POWER_STATES(node_id), \
|
|
Z_PM_STATE_INFO_FROM_DT_CPU, (,), node_id) \
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize an array of struct pm_state with information from all the
|
|
* states present in the given CPU node identifier.
|
|
*
|
|
* Example devicetree fragment:
|
|
*
|
|
* @code{.dts}
|
|
* 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>;
|
|
* };
|
|
* };
|
|
* @endcode
|
|
*
|
|
* Example usage:
|
|
*
|
|
* @code{.c}
|
|
* const enum pm_state states[] = PM_STATE_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0));
|
|
* @endcode
|
|
*
|
|
* @param node_id A CPU node identifier.
|
|
*/
|
|
#define PM_STATE_LIST_FROM_DT_CPU(node_id) \
|
|
{ \
|
|
LISTIFY(DT_NUM_CPU_POWER_STATES(node_id), \
|
|
Z_PM_STATE_FROM_DT_CPU, (,), node_id) \
|
|
}
|
|
|
|
|
|
/**
|
|
* Obtain information about all supported states by a CPU.
|
|
*
|
|
* @param cpu CPU index.
|
|
* @param states Where to store the list of supported states.
|
|
*
|
|
* @return Number of supported states.
|
|
*/
|
|
uint8_t pm_state_cpu_get_all(uint8_t cpu, const struct pm_state_info **states);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|