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 Check if a power state lock is active (not allowed).
130 : *
131 : * @param state Power state.
132 : * @param substate_id Power substate ID. Use PM_ALL_SUBSTATES to affect all the
133 : * substates in the given power state.
134 : *
135 : * @retval true if power state lock is active.
136 : * @retval false if power state lock is not active.
137 : */
138 1 : bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id);
139 :
140 : /**
141 : * @brief Check if a power state is available.
142 : *
143 : * It is unavailable if locked or latency requirement cannot be fulfilled in that state.
144 : *
145 : * @param state Power state.
146 : * @param substate_id Power substate ID. Use PM_ALL_SUBSTATES to affect all the
147 : * substates in the given power state.
148 : *
149 : * @retval true if power state is active.
150 : * @retval false if power state is not active.
151 : */
152 1 : bool pm_policy_state_is_available(enum pm_state state, uint8_t substate_id);
153 :
154 : /**
155 : * @brief Check if any power state can be used.
156 : *
157 : * Function allows to quickly check if any power state is available and exit
158 : * suspend operation early.
159 : *
160 : * @retval true if any power state is active.
161 : * @retval false if all power states are unavailable.
162 : */
163 1 : bool pm_policy_state_any_active(void);
164 :
165 : /**
166 : * @brief Register an event.
167 : *
168 : * Events in the power-management policy context are defined as any source that
169 : * will wake up the system at a known time in the future. By registering such
170 : * event, the policy manager will be able to decide whether certain power states
171 : * are worth entering or not.
172 : *
173 : * CPU is woken up before the time passed in cycle to minimize event handling
174 : * latency. Once woken up, the CPU will be kept awake until the event has been
175 : * handled, which is signaled by pm_policy_event_unregister() or moving event
176 : * into the future using pm_policy_event_update().
177 : *
178 : * @param evt Event.
179 : * @param uptime_ticks When the event will occur, in uptime ticks.
180 : *
181 : * @see pm_policy_event_unregister()
182 : */
183 1 : void pm_policy_event_register(struct pm_policy_event *evt, int64_t uptime_ticks);
184 :
185 : /**
186 : * @brief Update an event.
187 : *
188 : * This shortcut allows for moving the time an event will occur without the
189 : * need for an unregister + register cycle.
190 : *
191 : * @param evt Event.
192 : * @param uptime_ticks When the event will occur, in uptime ticks.
193 : *
194 : * @see pm_policy_event_register
195 : */
196 1 : void pm_policy_event_update(struct pm_policy_event *evt, int64_t uptime_ticks);
197 :
198 : /**
199 : * @brief Unregister an event.
200 : *
201 : * @param evt Event.
202 : *
203 : * @see pm_policy_event_register
204 : */
205 1 : void pm_policy_event_unregister(struct pm_policy_event *evt);
206 :
207 : /**
208 : * @brief Check if a state will disable a device
209 : *
210 : * This function allows client code to check if a state will disable a device.
211 : *
212 : * @param dev Device reference.
213 : * @param state The state to check on whether it disables the device.
214 : * @param substate_id The substate to check on whether it disables the device.
215 : *
216 : * @retval true if the state disables the device
217 : * @retval false if the state does not disable the device
218 : */
219 1 : bool pm_policy_device_is_disabling_state(const struct device *dev,
220 : enum pm_state state, uint8_t substate_id);
221 :
222 : /**
223 : * @brief Returns the ticks until the next event
224 : *
225 : * If an event is registred, it will return the number of ticks until the next event, if the
226 : * "next"/"oldest" registered event is in the past, it will return 0. Otherwise it returns -1.
227 : *
228 : * @retval >0 If next registered event is in the future
229 : * @retval 0 If next registered event is now or in the past
230 : * @retval -1 Otherwise
231 : */
232 1 : int64_t pm_policy_next_event_ticks(void);
233 :
234 : #else
235 : static inline void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id)
236 : {
237 : ARG_UNUSED(state);
238 : ARG_UNUSED(substate_id);
239 : }
240 :
241 : static inline void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id)
242 : {
243 : ARG_UNUSED(state);
244 : ARG_UNUSED(substate_id);
245 : }
246 :
247 : static inline bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id)
248 : {
249 : ARG_UNUSED(state);
250 : ARG_UNUSED(substate_id);
251 :
252 : return false;
253 : }
254 :
255 : static inline void pm_policy_event_register(struct pm_policy_event *evt, uint32_t cycle)
256 : {
257 : ARG_UNUSED(evt);
258 : ARG_UNUSED(cycle);
259 : }
260 :
261 : static inline void pm_policy_event_update(struct pm_policy_event *evt, uint32_t cycle)
262 : {
263 : ARG_UNUSED(evt);
264 : ARG_UNUSED(cycle);
265 : }
266 :
267 : static inline void pm_policy_event_unregister(struct pm_policy_event *evt)
268 : {
269 : ARG_UNUSED(evt);
270 : }
271 :
272 : static inline int64_t pm_policy_next_event_ticks(void)
273 : {
274 : return -1;
275 : }
276 :
277 : #endif /* CONFIG_PM */
278 :
279 : #if defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) || defined(__DOXYGEN__)
280 : /**
281 : * @brief Increase power state locks.
282 : *
283 : * Set power state locks in all power states that disable power in the given
284 : * device.
285 : *
286 : * @param dev Device reference.
287 : *
288 : * @see pm_policy_device_power_lock_put()
289 : * @see pm_policy_state_lock_get()
290 : */
291 1 : void pm_policy_device_power_lock_get(const struct device *dev);
292 :
293 : /**
294 : * @brief Decrease power state locks.
295 : *
296 : * Remove power state locks in all power states that disable power in the given
297 : * device.
298 : *
299 : * @param dev Device reference.
300 : *
301 : * @see pm_policy_device_power_lock_get()
302 : * @see pm_policy_state_lock_put()
303 : */
304 1 : void pm_policy_device_power_lock_put(const struct device *dev);
305 :
306 : #else
307 :
308 : static inline void pm_policy_device_power_lock_get(const struct device *dev)
309 : {
310 : ARG_UNUSED(dev);
311 : }
312 :
313 : static inline void pm_policy_device_power_lock_put(const struct device *dev)
314 : {
315 : ARG_UNUSED(dev);
316 : }
317 : #endif /* CONFIG_PM_POLICY_DEVICE_CONSTRAINTS */
318 :
319 : #if defined(CONFIG_PM) || defined(CONFIG_PM_POLICY_LATENCY_STANDALONE) || defined(__DOXYGEN__)
320 : /**
321 : * @brief Add a new latency requirement.
322 : *
323 : * The system will not enter any power state that would make the system to
324 : * exceed the given latency value.
325 : *
326 : * @param req Latency request.
327 : * @param value_us Maximum allowed latency in microseconds.
328 : */
329 1 : void pm_policy_latency_request_add(struct pm_policy_latency_request *req,
330 : uint32_t value_us);
331 :
332 : /**
333 : * @brief Update a latency requirement.
334 : *
335 : * @param req Latency request.
336 : * @param value_us New maximum allowed latency in microseconds.
337 : */
338 1 : void pm_policy_latency_request_update(struct pm_policy_latency_request *req,
339 : uint32_t value_us);
340 :
341 : /**
342 : * @brief Remove a latency requirement.
343 : *
344 : * @param req Latency request.
345 : */
346 1 : void pm_policy_latency_request_remove(struct pm_policy_latency_request *req);
347 :
348 : /**
349 : * @brief Subscribe to maximum latency changes.
350 : *
351 : * @param req Subscription request.
352 : * @param cb Callback function (NULL to disable).
353 : */
354 1 : void pm_policy_latency_changed_subscribe(struct pm_policy_latency_subscription *req,
355 : pm_policy_latency_changed_cb_t cb);
356 :
357 : /**
358 : * @brief Unsubscribe to maximum latency changes.
359 : *
360 : * @param req Subscription request.
361 : */
362 1 : void pm_policy_latency_changed_unsubscribe(struct pm_policy_latency_subscription *req);
363 : #else
364 : static inline void pm_policy_latency_request_add(
365 : struct pm_policy_latency_request *req, uint32_t value_us)
366 : {
367 : ARG_UNUSED(req);
368 : ARG_UNUSED(value_us);
369 : }
370 :
371 : static inline void pm_policy_latency_request_update(
372 : struct pm_policy_latency_request *req, uint32_t value_us)
373 : {
374 : ARG_UNUSED(req);
375 : ARG_UNUSED(value_us);
376 : }
377 :
378 : static inline void pm_policy_latency_request_remove(
379 : struct pm_policy_latency_request *req)
380 : {
381 : ARG_UNUSED(req);
382 : }
383 : #endif /* CONFIG_PM CONFIG_PM_POLICY_LATENCY_STANDALONE */
384 :
385 : /**
386 : * @}
387 : */
388 :
389 : #ifdef __cplusplus
390 : }
391 : #endif
392 :
393 : #endif /* ZEPHYR_INCLUDE_PM_POLICY_H_ */
|