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