1 /*
2  * Copyright (c) 2015 Intel Corporation.
3  * Copyright (c) 2021 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_INCLUDE_PM_DEVICE_RUNTIME_H_
9 #define ZEPHYR_INCLUDE_PM_DEVICE_RUNTIME_H_
10 
11 #include <zephyr/device.h>
12 #include <zephyr/kernel.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Device Runtime Power Management API
20  * @defgroup subsys_pm_device_runtime Device Runtime
21  * @ingroup subsys_pm
22  * @{
23  */
24 
25 #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
26 /**
27  * @brief Automatically enable device runtime based on devicetree properties
28  *
29  * @note Must not be called from application code. See the
30  * zephyr,pm-device-runtime-auto property in pm.yaml and z_sys_init_run_level.
31  *
32  * @param dev Device instance.
33  *
34  * @retval 0 If the device runtime PM is enabled successfully or it has not
35  * been requested for this device in devicetree.
36  * @retval -errno Other negative errno, result of enabled device runtime PM.
37  */
38 int pm_device_runtime_auto_enable(const struct device *dev);
39 
40 /**
41  * @brief Enable device runtime PM
42  *
43  * This function will enable runtime PM on the given device. If the device is
44  * in #PM_DEVICE_STATE_ACTIVE state, the device will be suspended.
45  *
46  * @funcprops \pre_kernel_ok
47  *
48  * @param dev Device instance.
49  *
50  * @retval 0 If the device runtime PM is enabled successfully.
51  * @retval -EBUSY If device is busy.
52  * @retval -ENOTSUP If the device does not support PM.
53  * @retval -errno Other negative errno, result of suspending the device.
54  *
55  * @see pm_device_init_suspended()
56  */
57 int pm_device_runtime_enable(const struct device *dev);
58 
59 /**
60  * @brief Disable device runtime PM
61  *
62  * If the device is currently suspended it will be resumed.
63  *
64  * @funcprops \pre_kernel_ok
65  *
66  * @param dev Device instance.
67  *
68  * @retval 0 If the device runtime PM is disabled successfully.
69  * @retval -ENOTSUP If the device does not support PM.
70  * @retval -errno Other negative errno, result of resuming the device.
71  */
72 int pm_device_runtime_disable(const struct device *dev);
73 
74 /**
75  * @brief Resume a device based on usage count.
76  *
77  * This function will resume the device if the device is suspended (usage count
78  * equal to 0). In case of a resume failure, usage count and device state will
79  * be left unchanged. In all other cases, usage count will be incremented.
80  *
81  * If the device is still being suspended as a result of calling
82  * pm_device_runtime_put_async(), this function will wait for the operation to
83  * finish to then resume the device.
84  *
85  * @note It is safe to use this function in contexts where blocking is not
86  * allowed, e.g. ISR, provided the device PM implementation does not block.
87  *
88  * @funcprops \pre_kernel_ok
89  *
90  * @param dev Device instance.
91  *
92  * @retval 0 If it succeeds. In case device runtime PM is not enabled or not
93  * available this function will be a no-op and will also return 0.
94  * @retval -EWOUDBLOCK If call would block but it is not allowed (e.g. in ISR).
95  * @retval -errno Other negative errno, result of the PM action callback.
96  */
97 int pm_device_runtime_get(const struct device *dev);
98 
99 /**
100  * @brief Suspend a device based on usage count.
101  *
102  * This function will suspend the device if the device is no longer required
103  * (usage count equal to 0). In case of suspend failure, usage count and device
104  * state will be left unchanged. In all other cases, usage count will be
105  * decremented (down to 0).
106  *
107  * @funcprops \pre_kernel_ok
108  *
109  * @param dev Device instance.
110  *
111  * @retval 0 If it succeeds. In case device runtime PM is not enabled or not
112  * available this function will be a no-op and will also return 0.
113  * @retval -EALREADY If device is already suspended (can only happen if get/put
114  * calls are unbalanced).
115  * @retval -errno Other negative errno, result of the action callback.
116  *
117  * @see pm_device_runtime_put_async()
118  */
119 int pm_device_runtime_put(const struct device *dev);
120 
121 /**
122  * @brief Suspend a device based on usage count (asynchronously).
123  *
124  * This function will schedule the device suspension if the device is no longer
125  * required (usage count equal to 0). In all other cases, usage count will be
126  * decremented (down to 0).
127  *
128  * @note Asynchronous operations are not supported when in pre-kernel mode. In
129  * this case, the function will be blocking (equivalent to
130  * pm_device_runtime_put()).
131  *
132  * @funcprops \pre_kernel_ok, \async, \isr_ok
133  *
134  * @param dev Device instance.
135  * @param delay Minimum amount of time before triggering the action.
136  *
137  * @retval 0 If it succeeds. In case device runtime PM is not enabled or not
138  * available this function will be a no-op and will also return 0.
139  * @retval -EBUSY If the device is busy.
140  * @retval -EALREADY If device is already suspended (can only happen if get/put
141  * calls are unbalanced).
142  *
143  * @see pm_device_runtime_put()
144  */
145 int pm_device_runtime_put_async(const struct device *dev, k_timeout_t delay);
146 
147 /**
148  * @brief Check if device runtime is enabled for a given device.
149  *
150  * @funcprops \pre_kernel_ok
151  *
152  * @param dev Device instance.
153  *
154  * @retval true If device has device runtime PM enabled.
155  * @retval false If the device has device runtime PM disabled.
156  *
157  * @see pm_device_runtime_enable()
158  */
159 bool pm_device_runtime_is_enabled(const struct device *dev);
160 
161 /**
162  * @brief Return the current device usage counter.
163  *
164  * @param dev Device instance.
165  *
166  * @returns the current usage counter.
167  * @retval -ENOTSUP If the device is not using runtime PM.
168  * @retval -ENOSYS If the runtime PM is not enabled at all.
169  */
170 int pm_device_runtime_usage(const struct device *dev);
171 
172 #else
173 
174 static inline int pm_device_runtime_auto_enable(const struct device *dev)
175 {
176 	ARG_UNUSED(dev);
177 	return 0;
178 }
179 
180 static inline int pm_device_runtime_enable(const struct device *dev)
181 {
182 	ARG_UNUSED(dev);
183 	return 0;
184 }
185 
186 static inline int pm_device_runtime_disable(const struct device *dev)
187 {
188 	ARG_UNUSED(dev);
189 	return 0;
190 }
191 
192 static inline int pm_device_runtime_get(const struct device *dev)
193 {
194 	ARG_UNUSED(dev);
195 	return 0;
196 }
197 
198 static inline int pm_device_runtime_put(const struct device *dev)
199 {
200 	ARG_UNUSED(dev);
201 	return 0;
202 }
203 
204 static inline int pm_device_runtime_put_async(const struct device *dev,
205 		k_timeout_t delay)
206 {
207 	ARG_UNUSED(dev);
208 	ARG_UNUSED(delay);
209 	return 0;
210 }
211 
212 static inline bool pm_device_runtime_is_enabled(const struct device *dev)
213 {
214 	ARG_UNUSED(dev);
215 	return false;
216 }
217 
218 static inline int pm_device_runtime_usage(const struct device *dev)
219 {
220 	ARG_UNUSED(dev);
221 	return -ENOSYS;
222 }
223 
224 #endif
225 
226 /** @} */
227 
228 #ifdef __cplusplus
229 }
230 #endif
231 
232 #endif /* ZEPHYR_INCLUDE_PM_DEVICE_RUNTIME_H_ */
233