1 /* 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 <sys/util.h> 11 #include <devicetree.h> 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 /** 18 * @defgroup pm_states Power Management States 19 * @ingroup power_management_api 20 * @{ 21 */ 22 23 /** 24 * @enum pm_state Power management state 25 */ 26 enum pm_state { 27 /** 28 * @brief Runtime active state 29 * 30 * The system is fully powered and active. 31 * 32 * @note This state is correlated with ACPI G0/S0 state 33 */ 34 PM_STATE_ACTIVE, 35 /** 36 * @brief Runtime idle state 37 * 38 * Runtime idle is a system sleep state in which all of the cores 39 * enter deepest possible idle state and wait for interrupts, no 40 * requirements for the devices, leaving them at the states where 41 * they are. 42 * 43 * @note This state is correlated with ACPI S0ix state 44 */ 45 PM_STATE_RUNTIME_IDLE, 46 /** 47 * @brief Suspend to idle state 48 * 49 * The system goes through a normal platform suspend where it puts 50 * all of the cores in deepest possible idle state and *may* puts peripherals 51 * into low-power states. No operating state is lost (ie. the cpu core 52 * does not lose execution context), so the system can go back to where 53 * it left off easily enough. 54 * 55 * @note This state is correlated with ACPI S1 state 56 */ 57 PM_STATE_SUSPEND_TO_IDLE, 58 /** 59 * @brief Standby state 60 * 61 * In addition to putting peripherals into low-power states all 62 * non-boot CPUs are powered off. It should allow more energy to be 63 * saved relative to suspend to idle, but the resume latency will 64 * generally be greater than for that state. But it should be the same 65 * state with suspend to idle state on uniprocesser system. 66 * 67 * @note This state is correlated with ACPI S2 state 68 */ 69 PM_STATE_STANDBY, 70 /** 71 * @brief Suspend to ram state 72 * 73 * This state offers significant energy savings by powering off as much 74 * of the system as possible, where memory should be placed into the 75 * self-refresh mode to retain its contents. The state of devices and 76 * CPUs is saved and held in memory, and it may require some boot- 77 * strapping code in ROM to resume the system from it. 78 * 79 * @note This state is correlated with ACPI S3 state 80 */ 81 PM_STATE_SUSPEND_TO_RAM, 82 /** 83 * @brief Suspend to disk state 84 * 85 * This state offers significant energy savings by powering off as much 86 * of the system as possible, including the memory. The contents of 87 * memory are written to disk or other non-volatile storage, and on resume 88 * it's read back into memory with the help of boot-strapping code, 89 * restores the system to the same point of execution where it went to 90 * suspend to disk. 91 * 92 * @note This state is correlated with ACPI S4 state 93 */ 94 PM_STATE_SUSPEND_TO_DISK, 95 /** 96 * @brief Soft off state 97 * 98 * This state consumes a minimal amount of power and requires a large 99 * latency in order to return to runtime active state. The contents of 100 * system(CPU and memory) will not be preserved, so the system will be 101 * restarted as if from initial power-up and kernel boot. 102 * 103 * @note This state is correlated with ACPI G2/S5 state 104 */ 105 PM_STATE_SOFT_OFF 106 }; 107 108 /** 109 * Information about a power management state 110 */ 111 struct pm_state_info { 112 enum pm_state state; 113 114 /** 115 * Some platforms have multiple states that map to 116 * one Zephyr power state. This property allows the platform 117 * distinguish them. e.g: 118 * 119 * power-states { 120 * state0: state0 { 121 * compatible = "zephyr,power-state"; 122 * power-state-name = "suspend-to-idle"; 123 * substate-id = <1>; 124 * min-residency-us = <10000>; 125 * exit-latency-us = <100>; 126 * }; 127 * state1: state1 { 128 * compatible = "zephyr,power-state"; 129 * power-state-name = "suspend-to-idle"; 130 * substate-id = <2>; 131 * min-residency-us = <20000>; 132 * exit-latency-us = <200>; 133 * }; 134 * } 135 */ 136 uint8_t substate_id; 137 138 /** 139 * Minimum residency duration in microseconds. It is the minimum 140 * time for a given idle state to be worthwhile energywise. 141 * 142 * @note 0 means that this property is not available for this state. 143 */ 144 uint32_t min_residency_us; 145 146 /** 147 * Worst case latency in microseconds required to exit the idle state. 148 * 149 * @note 0 means that this property is not available for this state. 150 */ 151 uint32_t exit_latency_us; 152 }; 153 154 /** 155 * @brief Construct a pm_state_info from 'cpu-power-states' property at index 'i' 156 * 157 * @param node_id A node identifier with compatible zephyr,power-state 158 * @param i index into cpu-power-states property 159 * @return pm_state_info item from 'cpu-power-states' property at index 'i' 160 */ 161 #define PM_STATE_INFO_DT_ITEM_BY_IDX(node_id, i) \ 162 { \ 163 .state = DT_ENUM_IDX(DT_PHANDLE_BY_IDX(node_id, \ 164 cpu_power_states, i), power_state_name), \ 165 .substate_id = DT_PROP_BY_PHANDLE_IDX_OR(node_id, \ 166 cpu_power_states, i, substate_id, 0), \ 167 .min_residency_us = DT_PROP_BY_PHANDLE_IDX_OR(node_id, \ 168 cpu_power_states, i, min_residency_us, 0),\ 169 .exit_latency_us = DT_PROP_BY_PHANDLE_IDX_OR(node_id, \ 170 cpu_power_states, i, exit_latency_us, 0),\ 171 }, 172 173 /** 174 * @brief Length of 'cpu-power-states' property 175 * 176 * @param node_id A node identifier with compatible zephyr,power-state 177 * @return length of 'cpu-power-states' property 178 */ 179 #define PM_STATE_DT_ITEMS_LEN(node_id) \ 180 DT_PROP_LEN_OR(node_id, cpu_power_states, 0) 181 182 /** 183 * @brief Macro function to construct enum pm_state item in UTIL_LISTIFY 184 * extension. 185 * 186 * @param child child index in UTIL_LISTIFY extension. 187 * @param node_id A node identifier with compatible zephyr,power-state 188 * @return macro function to construct a pm_state_info 189 */ 190 #define PM_STATE_INFO_DT_ITEMS_LISTIFY_FUNC(child, node_id) \ 191 PM_STATE_INFO_DT_ITEM_BY_IDX(node_id, child) 192 193 /** 194 * @brief Macro function to construct a list of 'pm_state_info' items by 195 * UTIL_LISTIFY func 196 * 197 * Example devicetree fragment: 198 * cpus { 199 * ... 200 * cpu0: cpu@0 { 201 * device_type = "cpu"; 202 * ... 203 * cpu-power-states = <&state0 &state1>; 204 * }; 205 * }; 206 * 207 * ... 208 * power-states { 209 * state0: state0 { 210 * compatible = "zephyr,power-state"; 211 * power-state-name = "suspend-to-idle"; 212 * min-residency-us = <10000>; 213 * exit-latency-us = <100>; 214 * }; 215 * 216 * state1: state1 { 217 * compatible = "zephyr,power-state"; 218 * power-state-name = "suspend-to-ram"; 219 * min-residency-us = <50000>; 220 * exit-latency-us = <500>; 221 * }; 222 * }; 223 * 224 * Example usage: * 225 * const struct pm_state_info states[] = 226 * PM_STATE_INFO_DT_ITEMS_LIST(DT_NODELABEL(cpu0)); 227 * 228 * @param node_id A node identifier with compatible zephyr,power-state 229 * @return an array of struct pm_state_info. 230 */ 231 #define PM_STATE_INFO_DT_ITEMS_LIST(node_id) { \ 232 UTIL_LISTIFY(PM_STATE_DT_ITEMS_LEN(node_id), \ 233 PM_STATE_INFO_DT_ITEMS_LISTIFY_FUNC,\ 234 node_id) \ 235 } 236 237 /** 238 * @brief Construct a pm_state enum from 'cpu-power-states' property 239 * at index 'i' 240 * 241 * @param node_id A node identifier with compatible zephyr,power-state 242 * @param i index into cpu-power-states property 243 * @return pm_state item from 'cpu-power-states' property at index 'i' 244 */ 245 #define PM_STATE_DT_ITEM_BY_IDX(node_id, i) \ 246 DT_ENUM_IDX(DT_PHANDLE_BY_IDX(node_id, \ 247 cpu_power_states, i), power_state_name), 248 249 250 /** 251 * @brief Macro function to construct enum pm_state item in UTIL_LISTIFY 252 * extension. 253 * 254 * @param child child index in UTIL_LISTIFY extension. 255 * @param node_id A node identifier with compatible zephyr,power-state 256 * @return macro function to construct a pm_state enum 257 */ 258 #define PM_STATE_DT_ITEMS_LISTIFY_FUNC(child, node_id) \ 259 PM_STATE_DT_ITEM_BY_IDX(node_id, child) 260 261 /** 262 * @brief Macro function to construct a list of enum pm_state items by 263 * UTIL_LISTIFY func 264 * 265 * Example devicetree fragment: 266 * cpus { 267 * ... 268 * cpu0: cpu@0 { 269 * device_type = "cpu"; 270 * ... 271 * cpu-power-states = <&state0 &state1>; 272 * }; 273 * }; 274 * 275 * ... 276 * state0: state0 { 277 * compatible = "zephyr,power-state"; 278 * power-state-name = "suspend-to-idle"; 279 * min-residency-us = <10000>; 280 * exit-latency-us = <100>; 281 * }; 282 * 283 * state1: state1 { 284 * compatible = "zephyr,power-state"; 285 * power-state-name = "suspend-to-ram"; 286 * min-residency-us = <50000>; 287 * exit-latency-us = <500>; 288 * }; 289 * 290 * Example usage: * 291 * const enum pm_state states[] = PM_STATE_DT_ITEMS_LIST(DT_NODELABEL(cpu0)); 292 * 293 * @param node_id A node identifier with compatible zephyr,power-state 294 * @return an array of enum pm_state items. 295 */ 296 #define PM_STATE_DT_ITEMS_LIST(node_id) { \ 297 UTIL_LISTIFY(PM_STATE_DT_ITEMS_LEN(node_id),\ 298 PM_STATE_DT_ITEMS_LISTIFY_FUNC,\ 299 node_id) \ 300 } 301 302 /** 303 * @} 304 */ 305 306 #ifdef __cplusplus 307 } 308 #endif 309 310 #endif 311