1 /*
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 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 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 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 struct pm_policy_event {
68 /** @cond INTERNAL_HIDDEN */
69 sys_snode_t node;
70 uint32_t value_cyc;
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 #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 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 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 bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id);
139
140 /**
141 * @brief Add a new latency requirement.
142 *
143 * The system will not enter any power state that would make the system to
144 * exceed the given latency value.
145 *
146 * @param req Latency request.
147 * @param value_us Maximum allowed latency in microseconds.
148 */
149 void pm_policy_latency_request_add(struct pm_policy_latency_request *req,
150 uint32_t value_us);
151
152 /**
153 * @brief Update a latency requirement.
154 *
155 * @param req Latency request.
156 * @param value_us New maximum allowed latency in microseconds.
157 */
158 void pm_policy_latency_request_update(struct pm_policy_latency_request *req,
159 uint32_t value_us);
160
161 /**
162 * @brief Remove a latency requirement.
163 *
164 * @param req Latency request.
165 */
166 void pm_policy_latency_request_remove(struct pm_policy_latency_request *req);
167
168 /**
169 * @brief Subscribe to maximum latency changes.
170 *
171 * @param req Subscription request.
172 * @param cb Callback function (NULL to disable).
173 */
174 void pm_policy_latency_changed_subscribe(struct pm_policy_latency_subscription *req,
175 pm_policy_latency_changed_cb_t cb);
176
177 /**
178 * @brief Unsubscribe to maximum latency changes.
179 *
180 * @param req Subscription request.
181 */
182 void pm_policy_latency_changed_unsubscribe(struct pm_policy_latency_subscription *req);
183
184 /**
185 * @brief Register an event.
186 *
187 * Events in the power-management policy context are defined as any source that
188 * will wake up the system at a known time in the future. By registering such
189 * event, the policy manager will be able to decide whether certain power states
190 * are worth entering or not.
191 *
192 * @note It is mandatory to unregister events once they have happened by using
193 * pm_policy_event_unregister(). Not doing so is an API contract violation,
194 * because the system would continue to consider them as valid events in the
195 * *far* future, that is, after the cycle counter rollover.
196 *
197 * @param evt Event.
198 * @param time_us When the event will occur, in microseconds from now.
199 *
200 * @see pm_policy_event_unregister
201 */
202 void pm_policy_event_register(struct pm_policy_event *evt, uint32_t time_us);
203
204 /**
205 * @brief Update an event.
206 *
207 * @param evt Event.
208 * @param time_us When the event will occur, in microseconds from now.
209 *
210 * @see pm_policy_event_register
211 */
212 void pm_policy_event_update(struct pm_policy_event *evt, uint32_t time_us);
213
214 /**
215 * @brief Unregister an event.
216 *
217 * @param evt Event.
218 *
219 * @see pm_policy_event_register
220 */
221 void pm_policy_event_unregister(struct pm_policy_event *evt);
222
223 /**
224 * @brief Increase power state locks.
225 *
226 * Set power state locks in all power states that disable power in the given
227 * device.
228 *
229 * @param dev Device reference.
230 *
231 * @see pm_policy_device_power_lock_put()
232 * @see pm_policy_state_lock_get()
233 */
234 void pm_policy_device_power_lock_get(const struct device *dev);
235
236 /**
237 * @brief Decrease power state locks.
238 *
239 * Remove power state locks in all power states that disable power in the given
240 * device.
241 *
242 * @param dev Device reference.
243 *
244 * @see pm_policy_device_power_lock_get()
245 * @see pm_policy_state_lock_put()
246 */
247 void pm_policy_device_power_lock_put(const struct device *dev);
248
249 #else
pm_policy_state_lock_get(enum pm_state state,uint8_t substate_id)250 static inline void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id)
251 {
252 ARG_UNUSED(state);
253 ARG_UNUSED(substate_id);
254 }
255
pm_policy_state_lock_put(enum pm_state state,uint8_t substate_id)256 static inline void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id)
257 {
258 ARG_UNUSED(state);
259 ARG_UNUSED(substate_id);
260 }
261
pm_policy_state_lock_is_active(enum pm_state state,uint8_t substate_id)262 static inline bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id)
263 {
264 ARG_UNUSED(state);
265 ARG_UNUSED(substate_id);
266
267 return false;
268 }
269
pm_policy_latency_request_add(struct pm_policy_latency_request * req,uint32_t value_us)270 static inline void pm_policy_latency_request_add(
271 struct pm_policy_latency_request *req, uint32_t value_us)
272 {
273 ARG_UNUSED(req);
274 ARG_UNUSED(value_us);
275 }
276
pm_policy_latency_request_update(struct pm_policy_latency_request * req,uint32_t value_us)277 static inline void pm_policy_latency_request_update(
278 struct pm_policy_latency_request *req, uint32_t value_us)
279 {
280 ARG_UNUSED(req);
281 ARG_UNUSED(value_us);
282 }
283
pm_policy_latency_request_remove(struct pm_policy_latency_request * req)284 static inline void pm_policy_latency_request_remove(
285 struct pm_policy_latency_request *req)
286 {
287 ARG_UNUSED(req);
288 }
289
pm_policy_event_register(struct pm_policy_event * evt,uint32_t time_us)290 static inline void pm_policy_event_register(struct pm_policy_event *evt,
291 uint32_t time_us)
292 {
293 ARG_UNUSED(evt);
294 ARG_UNUSED(time_us);
295 }
296
pm_policy_event_update(struct pm_policy_event * evt,uint32_t time_us)297 static inline void pm_policy_event_update(struct pm_policy_event *evt,
298 uint32_t time_us)
299 {
300 ARG_UNUSED(evt);
301 ARG_UNUSED(time_us);
302 }
303
pm_policy_event_unregister(struct pm_policy_event * evt)304 static inline void pm_policy_event_unregister(struct pm_policy_event *evt)
305 {
306 ARG_UNUSED(evt);
307 }
308
pm_policy_device_power_lock_get(const struct device * dev)309 static inline void pm_policy_device_power_lock_get(const struct device *dev)
310 {
311 ARG_UNUSED(dev);
312 }
313
pm_policy_device_power_lock_put(const struct device * dev)314 static inline void pm_policy_device_power_lock_put(const struct device *dev)
315 {
316 ARG_UNUSED(dev);
317 }
318
319 #endif /* CONFIG_PM */
320
321 /**
322 * @}
323 */
324
325 #ifdef __cplusplus
326 }
327 #endif
328
329 #endif /* ZEPHYR_INCLUDE_PM_POLICY_H_ */
330