LCOV - code coverage report
Current view: top level - zephyr/pm - state.h Coverage Total Hit
Test: new.info Lines: 92.6 % 27 25
Test Date: 2025-10-20 12:20:01

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2020 Intel corporation
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : #ifndef ZEPHYR_INCLUDE_PM_STATE_H_
       8              : #define ZEPHYR_INCLUDE_PM_STATE_H_
       9              : 
      10              : #include <zephyr/sys/util.h>
      11              : #include <zephyr/devicetree.h>
      12              : #include <errno.h>
      13              : 
      14              : #ifdef __cplusplus
      15              : extern "C" {
      16              : #endif
      17              : 
      18              : /**
      19              :  * @brief System Power Management States
      20              :  * @defgroup subsys_pm_states States
      21              :  * @ingroup subsys_pm
      22              :  * @{
      23              :  */
      24              : 
      25              : /**
      26              :  * @enum pm_state Power management state
      27              :  */
      28            1 : enum pm_state {
      29              :         /**
      30              :          * @brief Runtime active state
      31              :          *
      32              :          * The system is fully powered and active.
      33              :          *
      34              :          * @note This state is correlated with ACPI G0/S0 state
      35              :          */
      36              :         PM_STATE_ACTIVE,
      37              :         /**
      38              :          * @brief Runtime idle state
      39              :          *
      40              :          * Runtime idle is a system sleep state in which all of the cores
      41              :          * enter deepest possible idle state and wait for interrupts, no
      42              :          * requirements for the devices, leaving them at the states where
      43              :          * they are.
      44              :          *
      45              :          * @note This state is correlated with ACPI S0ix state
      46              :          */
      47              :         PM_STATE_RUNTIME_IDLE,
      48              :         /**
      49              :          * @brief Suspend to idle state
      50              :          *
      51              :          * The system goes through a normal platform suspend where it puts
      52              :          * all of the cores in deepest possible idle state and *may* puts
      53              :          * peripherals into low-power states. No operating state is lost (ie.
      54              :          * the cpu core does not lose execution context), so the system can go
      55              :          * back to where it left off easily enough.
      56              :          *
      57              :          * @note This state is correlated with ACPI S1 state
      58              :          */
      59              :         PM_STATE_SUSPEND_TO_IDLE,
      60              :         /**
      61              :          * @brief Standby state
      62              :          *
      63              :          * In addition to putting peripherals into low-power states all
      64              :          * non-boot CPUs are powered off. It should allow more energy to be
      65              :          * saved relative to suspend to idle, but the resume latency will
      66              :          * generally be greater than for that state. But it should be the same
      67              :          * state with suspend to idle state on uniprocessor system.
      68              :          *
      69              :          * @note This state is correlated with ACPI S2 state
      70              :          */
      71              :         PM_STATE_STANDBY,
      72              :         /**
      73              :          * @brief Suspend to ram state
      74              :          *
      75              :          * This state offers significant energy savings by powering off as much
      76              :          * of the system as possible, where memory should be placed into the
      77              :          * self-refresh mode to retain its contents. The state of devices and
      78              :          * CPUs is saved and held in memory, and it may require some boot-
      79              :          * strapping code in ROM to resume the system from it.
      80              :          *
      81              :          * @note This state is correlated with ACPI S3 state
      82              :          */
      83              :         PM_STATE_SUSPEND_TO_RAM,
      84              :         /**
      85              :          * @brief Suspend to disk state
      86              :          *
      87              :          * This state offers significant energy savings by powering off as much
      88              :          * of the system as possible, including the memory. The contents of
      89              :          * memory are written to disk or other non-volatile storage, and on
      90              :          * resume it's read back into memory with the help of boot-strapping
      91              :          * code, restores the system to the same point of execution where it
      92              :          * went to suspend to disk.
      93              :          *
      94              :          * @note This state is correlated with ACPI S4 state
      95              :          */
      96              :         PM_STATE_SUSPEND_TO_DISK,
      97              :         /**
      98              :          * @brief Soft off state
      99              :          *
     100              :          * This state consumes a minimal amount of power and requires a large
     101              :          * latency in order to return to runtime active state. The contents of
     102              :          * system(CPU and memory) will not be preserved, so the system will be
     103              :          * restarted as if from initial power-up and kernel boot.
     104              :          *
     105              :          * @note This state is correlated with ACPI G2/S5 state
     106              :          */
     107              :         PM_STATE_SOFT_OFF,
     108              :         /** Number of power management states (internal use) */
     109              :         PM_STATE_COUNT,
     110              : };
     111              : 
     112              : /**
     113              :  * Information about a power management state
     114              :  */
     115            1 : struct pm_state_info {
     116            0 :         enum pm_state state;
     117              : 
     118              :         /**
     119              :          * Some platforms have multiple states that map to
     120              :          * one Zephyr power state. This property allows the platform
     121              :          * distinguish them. e.g:
     122              :          *
     123              :          * @code{.dts}
     124              :          *      power-states {
     125              :          *              state0: state0 {
     126              :          *                      compatible = "zephyr,power-state";
     127              :          *                      power-state-name = "suspend-to-idle";
     128              :          *                      substate-id = <1>;
     129              :          *                      min-residency-us = <10000>;
     130              :          *                      exit-latency-us = <100>;
     131              :          *              };
     132              :          *              state1: state1 {
     133              :          *                      compatible = "zephyr,power-state";
     134              :          *                      power-state-name = "suspend-to-idle";
     135              :          *                      substate-id = <2>;
     136              :          *                      min-residency-us = <20000>;
     137              :          *                      exit-latency-us = <200>;
     138              :          *                      zephyr,pm-device-disabled;
     139              :          *              };
     140              :          *      };
     141              :          * @endcode
     142              :          */
     143            1 :         uint8_t substate_id;
     144              : 
     145              :         /**
     146              :          * Whether or not this state triggers device power management.
     147              :          *
     148              :          * When this property is false the power management subsystem
     149              :          * will suspend devices before entering this state and will
     150              :          * properly resume them when leaving it.
     151              :          */
     152            1 :         bool pm_device_disabled;
     153              : 
     154              :         /**
     155              :          * Minimum residency duration in microseconds. It is the minimum
     156              :          * time for a given idle state to be worthwhile energywise.
     157              :          *
     158              :          * @note 0 means that this property is not available for this state.
     159              :          */
     160            1 :         uint32_t min_residency_us;
     161              : 
     162              :         /**
     163              :          * Worst case latency in microseconds required to exit the idle state.
     164              :          *
     165              :          * @note 0 means that this property is not available for this state.
     166              :          */
     167            1 :         uint32_t exit_latency_us;
     168              : };
     169              : 
     170              : /**
     171              :  * Information needed to be able to reference a power state as a constraint
     172              :  * on some device or system functions.
     173              :  */
     174            1 : struct pm_state_constraint {
     175              :          /**
     176              :           * Power management state
     177              :           *
     178              :           * @see pm_state
     179              :           **/
     180            1 :         enum pm_state state;
     181              :          /**
     182              :           * Power management sub-state
     183              :           *
     184              :           * @see pm_state
     185              :           **/
     186            1 :         uint8_t substate_id;
     187              : };
     188              : 
     189              : /**
     190              :  * Collection of multiple power state constraints.
     191              :  */
     192            1 : struct pm_state_constraints {
     193              :         /** Array of power state constraints */
     194            1 :         struct pm_state_constraint *list;
     195              :         /** Number of constraints in the list */
     196            1 :         size_t count;
     197              : };
     198              : 
     199              : /** @cond INTERNAL_HIDDEN */
     200              : 
     201              : /**
     202              :  * @brief Helper macro that expands to 1 if a phandle node is enabled, 0 otherwise.
     203              :  *
     204              :  * @param node_id Node identifier.
     205              :  * @param prop Property holding phandle-array.
     206              :  * @param idx Index within the array.
     207              :  */
     208              : #define Z_DT_PHANDLE_01(node_id, prop, idx) \
     209              :         COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE_BY_IDX(node_id, prop, idx)), \
     210              :                     (1), (0))
     211              : 
     212              : /**
     213              :  * @brief Helper macro to initialize an entry of a struct pm_state_info array
     214              :  * when using UTIL_LISTIFY in PM_STATE_INFO_LIST_FROM_DT_CPU.
     215              :  *
     216              :  * @note Only enabled states are initialized.
     217              :  *
     218              :  * @param i UTIL_LISTIFY entry index.
     219              :  * @param node_id A node identifier with compatible zephyr,power-state
     220              :  */
     221              : #define Z_PM_STATE_INFO_FROM_DT_CPU(i, node_id)                                                   \
     222              :         COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)),     \
     223              :                     (PM_STATE_INFO_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)),), ())
     224              : 
     225              : /**
     226              :  * @brief Helper macro to initialize an entry of a struct pm_state array when
     227              :  * using UTIL_LISTIFY in PM_STATE_LIST_FROM_DT_CPU.
     228              :  *
     229              :  * @note Only enabled states are initialized.
     230              :  *
     231              :  * @param i UTIL_LISTIFY entry index.
     232              :  * @param node_id A node identifier with compatible zephyr,power-state
     233              :  */
     234              : #define Z_PM_STATE_FROM_DT_CPU(i, node_id)                                                        \
     235              :         COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)),     \
     236              :                     (PM_STATE_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)),), ())
     237              : 
     238              : /** @endcond */
     239              : 
     240              : /**
     241              :  * @brief Initializer for struct pm_state_info given a DT node identifier with
     242              :  * zephyr,power-state compatible.
     243              :  *
     244              :  * @param node_id A node identifier with compatible zephyr,power-state
     245              :  */
     246            1 : #define PM_STATE_INFO_DT_INIT(node_id)                                         \
     247              :         {                                                                      \
     248              :                 .state = PM_STATE_DT_INIT(node_id),                            \
     249              :                 .substate_id = DT_PROP_OR(node_id, substate_id, 0),            \
     250              :                 .min_residency_us = DT_PROP_OR(node_id, min_residency_us, 0),  \
     251              :                 .exit_latency_us = DT_PROP_OR(node_id, exit_latency_us, 0),    \
     252              :                 .pm_device_disabled = DT_PROP(node_id, zephyr_pm_device_disabled),    \
     253              :         }
     254              : 
     255              : /**
     256              :  * @brief Initializer for enum pm_state given a DT node identifier with
     257              :  * zephyr,power-state compatible.
     258              :  *
     259              :  * @param node_id A node identifier with compatible zephyr,power-state
     260              :  */
     261            1 : #define PM_STATE_DT_INIT(node_id) \
     262              :         DT_ENUM_IDX(node_id, power_state_name)
     263              : 
     264              : /**
     265              :  * @brief Obtain number of CPU power states supported and enabled by the given
     266              :  * CPU node identifier.
     267              :  *
     268              :  * @param node_id A CPU node identifier.
     269              :  * @return Number of supported and enabled CPU power states.
     270              :  */
     271            1 : #define DT_NUM_CPU_POWER_STATES(node_id)                                                           \
     272              :         COND_CODE_1(DT_NODE_HAS_PROP(node_id, cpu_power_states),                                   \
     273              :                     (DT_FOREACH_PROP_ELEM_SEP(node_id, cpu_power_states, Z_DT_PHANDLE_01, (+))),   \
     274              :                     (0))
     275              : 
     276              : /**
     277              :  * @brief Initialize an array of struct pm_state_info with information from all
     278              :  * the states present and enabled in the given CPU node identifier.
     279              :  *
     280              :  * Example devicetree fragment:
     281              :  *
     282              :  * @code{.dts}
     283              :  *      cpus {
     284              :  *              ...
     285              :  *              cpu0: cpu@0 {
     286              :  *                      device_type = "cpu";
     287              :  *                      ...
     288              :  *                      cpu-power-states = <&state0 &state1>;
     289              :  *              };
     290              :  *
     291              :  *              power-states {
     292              :  *                      state0: state0 {
     293              :  *                              compatible = "zephyr,power-state";
     294              :  *                              power-state-name = "suspend-to-idle";
     295              :  *                              min-residency-us = <10000>;
     296              :  *                              exit-latency-us = <100>;
     297              :  *                      };
     298              :  *
     299              :  *                      state1: state1 {
     300              :  *                              compatible = "zephyr,power-state";
     301              :  *                              power-state-name = "suspend-to-ram";
     302              :  *                              min-residency-us = <50000>;
     303              :  *                              exit-latency-us = <500>;
     304              :  *                              zephyr,pm-device-disabled;
     305              :  *                      };
     306              :  *              };
     307              :  *      };
     308              : 
     309              :  * @endcode
     310              :  *
     311              :  * Example usage:
     312              :  *
     313              :  * @code{.c}
     314              :  * const struct pm_state_info states[] =
     315              :  *      PM_STATE_INFO_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0));
     316              :  * @endcode
     317              :  *
     318              :  * @param node_id A CPU node identifier.
     319              :  */
     320            1 : #define PM_STATE_INFO_LIST_FROM_DT_CPU(node_id)                                \
     321              :         {                                                                      \
     322              :                 LISTIFY(DT_PROP_LEN_OR(node_id, cpu_power_states, 0),          \
     323              :                         Z_PM_STATE_INFO_FROM_DT_CPU, (), node_id)              \
     324              :         }
     325              : 
     326              : /**
     327              :  * @brief Initialize an array of struct pm_state with information from all the
     328              :  * states present and enabled in the given CPU node identifier.
     329              :  *
     330              :  * Example devicetree fragment:
     331              :  *
     332              :  * @code{.dts}
     333              :  *      cpus {
     334              :  *              ...
     335              :  *              cpu0: cpu@0 {
     336              :  *                      device_type = "cpu";
     337              :  *                      ...
     338              :  *                      cpu-power-states = <&state0 &state1>;
     339              :  *              };
     340              :  *
     341              :  *              power-states {
     342              :  *                      state0: state0 {
     343              :  *                              compatible = "zephyr,power-state";
     344              :  *                              power-state-name = "suspend-to-idle";
     345              :  *                              min-residency-us = <10000>;
     346              :  *                              exit-latency-us = <100>;
     347              :  *                      };
     348              :  *
     349              :  *                      state1: state1 {
     350              :  *                              compatible = "zephyr,power-state";
     351              :  *                              power-state-name = "suspend-to-ram";
     352              :  *                              min-residency-us = <50000>;
     353              :  *                              exit-latency-us = <500>;
     354              :  *                      };
     355              :  *              };
     356              :  *      };
     357              :  * @endcode
     358              :  *
     359              :  * Example usage:
     360              :  *
     361              :  * @code{.c}
     362              :  * const enum pm_state states[] = PM_STATE_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0));
     363              :  * @endcode
     364              :  *
     365              :  * @param node_id A CPU node identifier.
     366              :  */
     367            1 : #define PM_STATE_LIST_FROM_DT_CPU(node_id)                                     \
     368              :         {                                                                      \
     369              :                 LISTIFY(DT_PROP_LEN_OR(node_id, cpu_power_states, 0),          \
     370              :                         Z_PM_STATE_FROM_DT_CPU, (), node_id)                   \
     371              :         }
     372              : 
     373              : /**
     374              :  * @brief initialize a device pm constraint with information from devicetree.
     375              :  *
     376              :  * @param node_id Node identifier.
     377              :  */
     378            1 : #define PM_STATE_CONSTRAINT_INIT(node_id)                                     \
     379              :         {                                                                     \
     380              :                 .state = PM_STATE_DT_INIT(node_id),                           \
     381              :                 .substate_id = DT_PROP_OR(node_id, substate_id, 0),           \
     382              :         }
     383              : 
     384              : #define Z_PM_STATE_CONSTRAINT_REF(node_id, phandle, idx)                        \
     385              :         PM_STATE_CONSTRAINT_INIT(DT_PHANDLE_BY_IDX(node_id, phandle, idx))
     386              : 
     387              : #define Z_PM_STATE_CONSTRAINTS_LIST_NAME(node_id, phandles)                   \
     388              :         _CONCAT_4(node_id, _, phandles, _constraints)
     389              : 
     390              : /**
     391              :  * @brief Define a list of power state constraints from devicetree.
     392              :  *
     393              :  * This macro creates an array of pm_state_constraint structures initialized
     394              :  * with power state information from the specified devicetree property.
     395              :  *
     396              :  * @param node_id Devicetree node identifier.
     397              :  * @param prop Property name containing the list of power state phandles.
     398              :  */
     399            1 : #define PM_STATE_CONSTRAINTS_LIST_DEFINE(node_id, prop)                                    \
     400              :         struct pm_state_constraint Z_PM_STATE_CONSTRAINTS_LIST_NAME(node_id, prop)[] =     \
     401              :         {                                                                                  \
     402              :                 DT_FOREACH_PROP_ELEM_SEP(node_id, prop, Z_PM_STATE_CONSTRAINT_REF, (,))    \
     403              :         }
     404              : 
     405              : /**
     406              :  * @brief Get power state constraints structure from devicetree.
     407              :  *
     408              :  * This macro creates a structure containing a pointer to the constraints list
     409              :  * and the count of constraints, suitable for initializing a pm_state_constraints
     410              :  * structure. Must be used after the PM_STATE_CONSTRAINTS_LIST_DEFINE call for the same
     411              :  * @param prop to refer to the array of constraints.
     412              :  *
     413              :  * @param node_id Devicetree node identifier.
     414              :  * @param prop Property name containing the list of power state phandles.
     415              :  */
     416            1 : #define PM_STATE_CONSTRAINTS_GET(node_id, prop)                                            \
     417              :         {                                                                                  \
     418              :                 .list = Z_PM_STATE_CONSTRAINTS_LIST_NAME(node_id, prop),                   \
     419              :                 .count = DT_PROP_LEN(node_id, prop),                                       \
     420              :         }
     421              : 
     422              : #if defined(CONFIG_PM) || defined(__DOXYGEN__)
     423              : /**
     424              :  * Obtain information about all supported states by a CPU.
     425              :  *
     426              :  * @param cpu CPU index.
     427              :  * @param states Where to store the list of supported states.
     428              :  *
     429              :  * @return Number of supported states.
     430              :  */
     431            1 : uint8_t pm_state_cpu_get_all(uint8_t cpu, const struct pm_state_info **states);
     432              : 
     433              : /**
     434              :  * Get power state structure.
     435              :  *
     436              :  * Function searches in all states assigned to the CPU and in disabled states.
     437              :  *
     438              :  * @param cpu CPU index.
     439              :  * @param state Power state.
     440              :  * @param substate_id Substate.
     441              :  *
     442              :  * @return Pointer to the power state structure or NULL if state is not found.
     443              :  */
     444            1 : const struct pm_state_info *pm_state_get(uint8_t cpu, enum pm_state state, uint8_t substate_id);
     445              : 
     446              : /**
     447              :  * @brief Convert a pm_state enum value to its string representation.
     448              :  *
     449              :  * @param state Power state.
     450              :  *
     451              :  * @return A constant string representing the state.
     452              :  */
     453            1 : const char *pm_state_to_str(enum pm_state state);
     454              : 
     455              : 
     456              : /**
     457              :  * @brief Parse a string and convert it to a pm_state enum value.
     458              :  *
     459              :  * @param name Input string (e.g., "suspend-to-ram").
     460              :  * @param out Pointer to store the parsed pm_state value.
     461              :  *
     462              :  * @return 0 on success, -EINVAL if the string is invalid or NULL.
     463              :  */
     464            1 : int pm_state_from_str(const char *name, enum pm_state *out);
     465              : 
     466              : /**
     467              :  * @brief Check if a power management constraint matches any in a set of constraints.
     468              :  *
     469              :  * @param constraints Pointer to the power state constraints structure.
     470              :  * @param match The constraint to match against.
     471              :  *
     472              :  * @return true if the constraint matches, false otherwise.
     473              :  */
     474            1 : bool pm_state_in_constraints(const struct pm_state_constraints *constraints,
     475              :                              const struct pm_state_constraint match);
     476              : 
     477              : /**
     478              :  * @}
     479              :  */
     480              : 
     481              : #else  /* CONFIG_PM */
     482              : 
     483              : static inline uint8_t pm_state_cpu_get_all(uint8_t cpu, const struct pm_state_info **states)
     484              : {
     485              :         ARG_UNUSED(cpu);
     486              :         ARG_UNUSED(states);
     487              : 
     488              :         return 0;
     489              : }
     490              : 
     491              : static inline const struct pm_state_info *pm_state_get(uint8_t cpu,
     492              :                                                        enum pm_state state,
     493              :                                                        uint8_t substate_id)
     494              : {
     495              :         ARG_UNUSED(cpu);
     496              :         ARG_UNUSED(state);
     497              :         ARG_UNUSED(substate_id);
     498              : 
     499              :         return NULL;
     500              : }
     501              : 
     502              : static inline bool pm_state_in_constraints(struct pm_state_constraints *constraints,
     503              :                                            struct pm_state_constraint match)
     504              : {
     505              :         ARG_UNUSED(constraints);
     506              :         ARG_UNUSED(match);
     507              : 
     508              :         return false;
     509              : }
     510              : #endif /* CONFIG_PM */
     511              : 
     512              : #ifdef __cplusplus
     513              : }
     514              : #endif
     515              : 
     516              : #endif
        

Generated by: LCOV version 2.0-1