Line data Source code
1 0 : /*
2 : * Copyright (c) 2018 Intel Corporation.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_PM_POLICY_H_
8 : #define ZEPHYR_INCLUDE_PM_POLICY_H_
9 :
10 : #include <stdbool.h>
11 : #include <stdint.h>
12 :
13 : #include <zephyr/device.h>
14 : #include <zephyr/pm/state.h>
15 : #include <zephyr/sys/slist.h>
16 : #include <zephyr/toolchain.h>
17 :
18 : #ifdef __cplusplus
19 : extern "C" {
20 : #endif
21 :
22 : /**
23 : * @brief System Power Management Policy API
24 : * @defgroup subsys_pm_sys_policy Policy
25 : * @ingroup subsys_pm_sys
26 : * @{
27 : */
28 :
29 : /**
30 : * @brief Callback to notify when maximum latency changes.
31 : *
32 : * @param latency New maximum latency. Positive value represents latency in
33 : * microseconds. SYS_FOREVER_US value lifts the latency constraint. Other values
34 : * are forbidden.
35 : */
36 1 : typedef void (*pm_policy_latency_changed_cb_t)(int32_t latency);
37 :
38 : /**
39 : * @brief Latency change subscription.
40 : *
41 : * @note All fields in this structure are meant for private usage.
42 : */
43 1 : struct pm_policy_latency_subscription {
44 : /** @cond INTERNAL_HIDDEN */
45 : sys_snode_t node;
46 : pm_policy_latency_changed_cb_t cb;
47 : /** @endcond */
48 : };
49 :
50 : /**
51 : * @brief Latency request.
52 : *
53 : * @note All fields in this structure are meant for private usage.
54 : */
55 1 : struct pm_policy_latency_request {
56 : /** @cond INTERNAL_HIDDEN */
57 : sys_snode_t node;
58 : uint32_t value_us;
59 : /** @endcond */
60 : };
61 :
62 : /**
63 : * @brief Event.
64 : *
65 : * @note All fields in this structure are meant for private usage.
66 : */
67 1 : struct pm_policy_event {
68 : /** @cond INTERNAL_HIDDEN */
69 : sys_snode_t node;
70 : int64_t uptime_ticks;
71 : /** @endcond */
72 : };
73 :
74 : /** @cond INTERNAL_HIDDEN */
75 :
76 : /**
77 : * @brief Function to get the next PM state
78 : *
79 : * This function is called by the power subsystem when the system is
80 : * idle and returns the most appropriate state based on the number of
81 : * ticks to the next event.
82 : *
83 : * @param cpu CPU index.
84 : * @param ticks The number of ticks to the next scheduled event.
85 : *
86 : * @return The power state the system should use for the given cpu. The function
87 : * will return NULL if system should remain into PM_STATE_ACTIVE.
88 : */
89 : const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks);
90 :
91 : /** @endcond */
92 :
93 : /** Special value for 'all substates'. */
94 1 : #define PM_ALL_SUBSTATES (UINT8_MAX)
95 :
96 : #if defined(CONFIG_PM) || defined(__DOXYGEN__)
97 : /**
98 : * @brief Increase a power state lock counter.
99 : *
100 : * A power state will not be allowed on the first call of
101 : * pm_policy_state_lock_get(). Subsequent calls will just increase a reference
102 : * count, thus meaning this API can be safely used concurrently. A state will
103 : * be allowed again after pm_policy_state_lock_put() is called as many times as
104 : * pm_policy_state_lock_get().
105 : *
106 : * Note that the PM_STATE_ACTIVE state is always allowed, so calling this API
107 : * with PM_STATE_ACTIVE will have no effect.
108 : *
109 : * @param state Power state.
110 : * @param substate_id Power substate ID. Use PM_ALL_SUBSTATES to affect all the
111 : * substates in the given power state.
112 : *
113 : * @see pm_policy_state_lock_put()
114 : */
115 1 : void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id);
116 :
117 : /**
118 : * @brief Decrease a power state lock counter.
119 : *
120 : * @param state Power state.
121 : * @param substate_id Power substate ID. Use PM_ALL_SUBSTATES to affect all the
122 : * substates in the given power state.
123 : *
124 : * @see pm_policy_state_lock_get()
125 : */
126 1 : void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id);
127 :
128 : /**
129 : * @brief Request to lock all power states.
130 : *
131 : * Requests use a reference counter.
132 : */
133 1 : void pm_policy_state_all_lock_get(void);
134 :
135 : /**
136 : * @brief Release locking of all power states.
137 : */
138 1 : void pm_policy_state_all_lock_put(void);
139 :
140 : /**
141 : * @brief Apply power state constraints by locking the specified states.
142 : *
143 : * This function locks all power states specified in the union of all constraints
144 : * in the provided constraint list. Each constraint in the set contributes to
145 : * determining which power states should be locked (not allowed), by increasing
146 : * a reference count just as if pm_policy_state_lock_get was called on each constraints'
147 : * states individually.
148 : *
149 : * @param constraints Pointer to the power state constraints set to apply.
150 : *
151 : * @see pm_policy_state_constraints_put()
152 : */
153 1 : void pm_policy_state_constraints_get(struct pm_state_constraints *constraints);
154 :
155 : /**
156 : * @brief Remove power state constraints by unlocking the specified states.
157 : *
158 : * This function unlocks all power states that were previously locked by a
159 : * corresponding call to pm_policy_state_constraints_get() with the same
160 : * constraint set. The function decreases the lock counter for each affected
161 : * power state specified in the union of all constraints in the list, just as
162 : * if pm_policy_state_put was called on all the constraints' states individually.
163 : *
164 : * @param constraints Pointer to the power state constraints set to remove.
165 : *
166 : * @see pm_policy_state_constraints_get()
167 : */
168 1 : void pm_policy_state_constraints_put(struct pm_state_constraints *constraints);
169 :
170 : /**
171 : * @brief Check if a power state lock is active (not allowed).
172 : *
173 : * @param state Power state.
174 : * @param substate_id Power substate ID. Use PM_ALL_SUBSTATES to affect all the
175 : * substates in the given power state.
176 : *
177 : * @retval true if power state lock is active.
178 : * @retval false if power state lock is not active.
179 : */
180 1 : bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id);
181 :
182 : /**
183 : * @brief Check if a power state is available.
184 : *
185 : * It is unavailable if locked or latency requirement cannot be fulfilled in that state.
186 : *
187 : * @param state Power state.
188 : * @param substate_id Power substate ID. Use PM_ALL_SUBSTATES to affect all the
189 : * substates in the given power state.
190 : *
191 : * @retval true if power state is active.
192 : * @retval false if power state is not active.
193 : */
194 1 : bool pm_policy_state_is_available(enum pm_state state, uint8_t substate_id);
195 :
196 : /**
197 : * @brief Check if any power state can be used.
198 : *
199 : * Function allows to quickly check if any power state is available and exit
200 : * suspend operation early.
201 : *
202 : * @retval true if any power state is active.
203 : * @retval false if all power states are unavailable.
204 : */
205 1 : bool pm_policy_state_any_active(void);
206 :
207 : /**
208 : * @brief Register an event.
209 : *
210 : * Events in the power-management policy context are defined as any source that
211 : * will wake up the system at a known time in the future. By registering such
212 : * event, the policy manager will be able to decide whether certain power states
213 : * are worth entering or not.
214 : *
215 : * CPU is woken up before the time passed in cycle to minimize event handling
216 : * latency. Once woken up, the CPU will be kept awake until the event has been
217 : * handled, which is signaled by pm_policy_event_unregister() or moving event
218 : * into the future using pm_policy_event_update().
219 : *
220 : * @param evt Event.
221 : * @param uptime_ticks When the event will occur, in uptime ticks.
222 : *
223 : * @see pm_policy_event_unregister()
224 : */
225 1 : void pm_policy_event_register(struct pm_policy_event *evt, int64_t uptime_ticks);
226 :
227 : /**
228 : * @brief Update an event.
229 : *
230 : * This shortcut allows for moving the time an event will occur without the
231 : * need for an unregister + register cycle.
232 : *
233 : * @param evt Event.
234 : * @param uptime_ticks When the event will occur, in uptime ticks.
235 : *
236 : * @see pm_policy_event_register
237 : */
238 1 : void pm_policy_event_update(struct pm_policy_event *evt, int64_t uptime_ticks);
239 :
240 : /**
241 : * @brief Unregister an event.
242 : *
243 : * @param evt Event.
244 : *
245 : * @see pm_policy_event_register
246 : */
247 1 : void pm_policy_event_unregister(struct pm_policy_event *evt);
248 :
249 : /**
250 : * @brief Check if a state will disable a device
251 : *
252 : * This function allows client code to check if a state will disable a device.
253 : *
254 : * @param dev Device reference.
255 : * @param state The state to check on whether it disables the device.
256 : * @param substate_id The substate to check on whether it disables the device.
257 : *
258 : * @retval true if the state disables the device
259 : * @retval false if the state does not disable the device
260 : */
261 1 : bool pm_policy_device_is_disabling_state(const struct device *dev,
262 : enum pm_state state, uint8_t substate_id);
263 :
264 : /**
265 : * @brief Returns the ticks until the next event
266 : *
267 : * If an event is registred, it will return the number of ticks until the next event, if the
268 : * "next"/"oldest" registered event is in the past, it will return 0. Otherwise it returns -1.
269 : *
270 : * @retval >0 If next registered event is in the future
271 : * @retval 0 If next registered event is now or in the past
272 : * @retval -1 Otherwise
273 : */
274 1 : int64_t pm_policy_next_event_ticks(void);
275 :
276 : #else
277 : static inline void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id)
278 : {
279 : ARG_UNUSED(state);
280 : ARG_UNUSED(substate_id);
281 : }
282 :
283 : static inline void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id)
284 : {
285 : ARG_UNUSED(state);
286 : ARG_UNUSED(substate_id);
287 : }
288 :
289 : static inline void pm_policy_state_all_lock_get(void)
290 : {
291 : }
292 :
293 : static inline void pm_policy_state_all_lock_put(void)
294 : {
295 : }
296 :
297 : static inline bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id)
298 : {
299 : ARG_UNUSED(state);
300 : ARG_UNUSED(substate_id);
301 :
302 : return false;
303 : }
304 :
305 : static inline void pm_policy_event_register(struct pm_policy_event *evt, uint32_t cycle)
306 : {
307 : ARG_UNUSED(evt);
308 : ARG_UNUSED(cycle);
309 : }
310 :
311 : static inline void pm_policy_event_update(struct pm_policy_event *evt, uint32_t cycle)
312 : {
313 : ARG_UNUSED(evt);
314 : ARG_UNUSED(cycle);
315 : }
316 :
317 : static inline void pm_policy_event_unregister(struct pm_policy_event *evt)
318 : {
319 : ARG_UNUSED(evt);
320 : }
321 :
322 : static inline int64_t pm_policy_next_event_ticks(void)
323 : {
324 : return -1;
325 : }
326 :
327 : #endif /* CONFIG_PM */
328 :
329 : #if defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) || defined(__DOXYGEN__)
330 : /**
331 : * @brief Increase power state locks.
332 : *
333 : * Set power state locks in all power states that disable power in the given
334 : * device.
335 : *
336 : * @param dev Device reference.
337 : *
338 : * @see pm_policy_device_power_lock_put()
339 : * @see pm_policy_state_lock_get()
340 : */
341 1 : void pm_policy_device_power_lock_get(const struct device *dev);
342 :
343 : /**
344 : * @brief Decrease power state locks.
345 : *
346 : * Remove power state locks in all power states that disable power in the given
347 : * device.
348 : *
349 : * @param dev Device reference.
350 : *
351 : * @see pm_policy_device_power_lock_get()
352 : * @see pm_policy_state_lock_put()
353 : */
354 1 : void pm_policy_device_power_lock_put(const struct device *dev);
355 :
356 : #else
357 :
358 : static inline void pm_policy_device_power_lock_get(const struct device *dev)
359 : {
360 : ARG_UNUSED(dev);
361 : }
362 :
363 : static inline void pm_policy_device_power_lock_put(const struct device *dev)
364 : {
365 : ARG_UNUSED(dev);
366 : }
367 : #endif /* CONFIG_PM_POLICY_DEVICE_CONSTRAINTS */
368 :
369 : #if defined(CONFIG_PM) || defined(CONFIG_PM_POLICY_LATENCY_STANDALONE) || defined(__DOXYGEN__)
370 : /**
371 : * @brief Add a new latency requirement.
372 : *
373 : * The system will not enter any power state that would make the system to
374 : * exceed the given latency value.
375 : *
376 : * @param req Latency request.
377 : * @param value_us Maximum allowed latency in microseconds.
378 : */
379 1 : void pm_policy_latency_request_add(struct pm_policy_latency_request *req,
380 : uint32_t value_us);
381 :
382 : /**
383 : * @brief Update a latency requirement.
384 : *
385 : * @param req Latency request.
386 : * @param value_us New maximum allowed latency in microseconds.
387 : */
388 1 : void pm_policy_latency_request_update(struct pm_policy_latency_request *req,
389 : uint32_t value_us);
390 :
391 : /**
392 : * @brief Remove a latency requirement.
393 : *
394 : * @param req Latency request.
395 : */
396 1 : void pm_policy_latency_request_remove(struct pm_policy_latency_request *req);
397 :
398 : /**
399 : * @brief Subscribe to maximum latency changes.
400 : *
401 : * @param req Subscription request.
402 : * @param cb Callback function (NULL to disable).
403 : */
404 1 : void pm_policy_latency_changed_subscribe(struct pm_policy_latency_subscription *req,
405 : pm_policy_latency_changed_cb_t cb);
406 :
407 : /**
408 : * @brief Unsubscribe to maximum latency changes.
409 : *
410 : * @param req Subscription request.
411 : */
412 1 : void pm_policy_latency_changed_unsubscribe(struct pm_policy_latency_subscription *req);
413 : #else
414 : static inline void pm_policy_latency_request_add(
415 : struct pm_policy_latency_request *req, uint32_t value_us)
416 : {
417 : ARG_UNUSED(req);
418 : ARG_UNUSED(value_us);
419 : }
420 :
421 : static inline void pm_policy_latency_request_update(
422 : struct pm_policy_latency_request *req, uint32_t value_us)
423 : {
424 : ARG_UNUSED(req);
425 : ARG_UNUSED(value_us);
426 : }
427 :
428 : static inline void pm_policy_latency_request_remove(
429 : struct pm_policy_latency_request *req)
430 : {
431 : ARG_UNUSED(req);
432 : }
433 : #endif /* CONFIG_PM CONFIG_PM_POLICY_LATENCY_STANDALONE */
434 :
435 : /**
436 : * @}
437 : */
438 :
439 : #ifdef __cplusplus
440 : }
441 : #endif
442 :
443 : #endif /* ZEPHYR_INCLUDE_PM_POLICY_H_ */
|