1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2018, Linaro Limited 4 */ 5 6 #ifndef __KERNEL_PM_H 7 #define __KERNEL_PM_H 8 9 #include <stdbool.h> 10 #include <stdint.h> 11 #include <tee_api_types.h> 12 13 /* 14 * Platform hints on targeted power state. Hints are stored in a 32bit 15 * unsigned value. Lower bits defines generic resource bit flags. Higher 16 * bits stores a platform specific value specific platform driver may 17 * understand. Registered callbacks may choose to use or ignore these hints. 18 * 19 * PM_HINT_CLOCK_STATE - When set clock shall be suspended/restored 20 * PM_HINT_POWER_STATE - When set device power shall be suspended/restored 21 * PM_HINT_IO_STATE - When set IO pins shall be suspended/restored 22 * PM_HINT_CONTEXT_STATE - When set the full context be suspended/restored 23 * PM_HINT_SUSPEND_TYPE - Contains the type of suspend operation 24 * PM_HINT_PLATFORM_STATE_MASK - Bit mask reserved for platform specific hints 25 * PM_HINT_PLATFORM_STATE_SHIFT - LSBit position of platform specific hints mask 26 */ 27 #define PM_HINT_CLOCK_STATE BIT(0) 28 #define PM_HINT_POWER_STATE BIT(1) 29 #define PM_HINT_IO_STATE BIT(2) 30 #define PM_HINT_CONTEXT_STATE BIT(3) 31 #define PM_HINT_SUSPEND_TYPE_MASK GENMASK_32(5, 4) 32 #define PM_HINT_SUSPEND_TYPE_SHIFT U(4) 33 #define PM_HINT_PLATFORM_STATE_MASK GENMASK_32(31, 16) 34 #define PM_HINT_PLATFORM_STATE_SHIFT U(16) 35 36 enum pm_suspend_type { 37 PM_SUSPEND_STANDBY, 38 PM_SUSPEND_TO_MEM, 39 }; 40 41 #define PM_HINT_SUSPEND_TYPE(__hint) \ 42 (((__hint) & PM_HINT_SUSPEND_TYPE_MASK) >> PM_HINT_SUSPEND_TYPE_SHIFT) 43 44 #define PM_HINT_STATE(_x) ((_x) & ~PM_HINT_PLATFORM_STATE_MASK) 45 #define PM_HINT_PLATFORM_STATE(_x) \ 46 (((_x) & PM_HINT_PLATFORM_STATE_MASK) >> PM_HINT_PLATFORM_STATE_SHIFT) 47 48 #define PM_HINT_IS_STATE(_x, _name) ((_x) & PM_HINT_ ## _name ## _STATE) 49 50 /* 51 * PM_OP_SUSPEND: platform is suspending to a target low power state 52 * PM_OP_RESUME: platform is resuming from low power state 53 */ 54 enum pm_op { 55 PM_OP_SUSPEND = 0, 56 PM_OP_RESUME = 1, 57 }; 58 59 /* 60 * Registered callbacks are called the ordering directives specified 61 * by the PM_CB_ORDER_* value. Driver ordered callbacks at suspended 62 * first/resumed last. Core service ordered callbacks are suspended 63 * last/resumed first. 64 */ 65 enum pm_callback_order { 66 PM_CB_ORDER_DRIVER = 0, 67 PM_CB_ORDER_CORE_SERVICE, 68 PM_CB_ORDER_MAX 69 }; 70 71 #define PM_CALLBACK_HANDLE_INITIALIZER(_callback, _handle, _order, _name)\ 72 ((struct pm_callback_handle){ \ 73 .callback = (_callback), \ 74 .handle = (_handle), \ 75 .order = (_order), \ 76 .name = (_name), \ 77 }) 78 79 #define PM_CALLBACK_GET_HANDLE(pm_handle) ((pm_handle)->handle) 80 81 struct pm_callback_handle; 82 typedef TEE_Result (*pm_callback)(enum pm_op op, uint32_t pm_hint, 83 const struct pm_callback_handle *pm_handle); 84 85 /* 86 * Drivers and services can register a callback function for the platform 87 * suspend and resume sequences. A private address handle can be registered 88 * with the callback and retrieved from the callback. Callback can be 89 * registered with a specific call order as defined per PM_CB_ORDER_*. 90 * 91 * Callback shall return an error if failing to complete target transition. 92 * This information may be used by the platform to resume a platform on 93 * non-fatal failure to suspend. 94 * 95 * Callback implementations should ensure their functions belong to unpaged 96 * memory sections (see DECLARE_KEEP_PAGER()) since the callback is likely to 97 * be called from an unpaged execution context. 98 * 99 * Power Mamagement callback functions API: 100 * 101 * TEE_Result (*callback)(enum pm_op op, 102 * unsigned int pm_hint, 103 * const struct pm_callback_handle *pm_handle); 104 * 105 * @op - Target operation: either PM_SUSPEND or PM_RESUME 106 * @pm_hint - Hints on power state platform suspends to /resumes from. 107 * PM_STATE_HINT_* defines the supported values. 108 * @pm_handle - Reference to the struct pm_callback_handle related to to 109 * registered callback. Callback can retrieve the registered 110 * private handle with PM_CALLBACK_GET_HANDLE(). 111 * 112 * Return a TEE_Result compliant return code 113 */ 114 /* 115 * struct pm_callback_handle store the callback registration directives. 116 * 117 * @callback - Registered callback function 118 * @handle - Registered private handler for the callback 119 * @order - Registered callback call order priority (PM_CB_ORDER_*) 120 * @flags - Flags set by pm core to keep track of execution 121 * @name - Registered callback name 122 */ 123 struct pm_callback_handle { 124 /* Set by the caller when registering a callback */ 125 pm_callback callback; 126 void *handle; 127 uint8_t order; 128 /* Set by the system according to execution context */ 129 uint8_t flags; 130 const char *name; 131 }; 132 133 /* 134 * Register a callback for suspend/resume sequence 135 * Refer to struct pm_callback_handle for description of the callbacks 136 * API and the registration directives. 137 * 138 * @pm_handle: Reference callback registration directives 139 */ 140 void register_pm_cb(struct pm_callback_handle *pm_handle); 141 142 /* 143 * Unregister a previously registered PM callback handle 144 * Refer to struct pm_callback_handle for description of the callbacks 145 * API and the registration directives. 146 * 147 * @pm_handle: Reference previously registered 148 * 149 * This function removes from the list of the PM called callbacks the 150 * entry that match callback function reference and private handle and 151 * PM order (PM_CB_ORDER_*). 152 */ 153 void unregister_pm_cb(struct pm_callback_handle *pm_handle); 154 155 /* 156 * Register a driver callback for generic suspend/resume. 157 * Refer to struct pm_callback_handle for description of the callbacks 158 * API. 159 * 160 * @callback: Registered callback function 161 * @handle: Registered private handle argument for the callback 162 * @name: Registered callback name 163 */ 164 static inline void register_pm_driver_cb(pm_callback callback, void *handle, 165 const char *name) 166 { 167 register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, 168 PM_CB_ORDER_DRIVER, 169 name)); 170 } 171 172 /* 173 * Unregister a driver callback from generic suspend/resume sequence. 174 * 175 * @callback: Callback function that what registered 176 * @handle: Private handle argument that was registered for the callback 177 */ 178 static inline void unregister_pm_driver_cb(pm_callback callback, void *handle) 179 { 180 unregister_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, 181 PM_CB_ORDER_DRIVER, 182 NULL)); 183 } 184 185 /* 186 * Register a core service callback for generic suspend/resume. 187 * Refer to struct pm_callback_handle for description of the callbacks 188 * API. 189 * 190 * @callback: Registered callback function 191 * @handle: Registered private handle argument for the callback 192 * @name: Registered callback name 193 */ 194 static inline void register_pm_core_service_cb(pm_callback callback, 195 void *handle, const char *name) 196 { 197 register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, 198 PM_CB_ORDER_CORE_SERVICE, 199 name)); 200 } 201 202 /* 203 * Unregister a core service callback from generic suspend/resume sequences 204 * 205 * @callback: Registered callback function 206 * @handle: Private handle argument that was registered for the callback 207 */ 208 static inline void unregister_pm_core_service_cb(pm_callback callback, 209 void *handle) 210 { 211 enum pm_callback_order order = PM_CB_ORDER_CORE_SERVICE; 212 213 unregister_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, 214 order, NULL)); 215 } 216 217 /* 218 * Request call to registered PM callbacks 219 * 220 * @op: Either PM_OP_SUSPEND or PM_OP_RESUME 221 * @pm_hint: Hint (PM_HINT_*) on state the platform suspends to/resumes from. 222 * 223 * Return a TEE_Result compliant status 224 */ 225 TEE_Result pm_change_state(enum pm_op op, uint32_t pm_hint); 226 227 #endif /*__KERNEL_PM_H*/ 228