Line data Source code
1 0 : /*
2 : * Copyright (c) 2015 Intel Corporation.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_PM_DEVICE_H_
8 : #define ZEPHYR_INCLUDE_PM_DEVICE_H_
9 :
10 : #include <zephyr/device.h>
11 : #include <zephyr/kernel.h>
12 : #include <zephyr/sys/atomic.h>
13 : #include <zephyr/sys/iterable_sections.h>
14 :
15 : #ifdef __cplusplus
16 : extern "C" {
17 : #endif
18 :
19 : /**
20 : * @brief Device Power Management API
21 : * @defgroup subsys_pm_device Device
22 : * @ingroup subsys_pm
23 : * @{
24 : */
25 :
26 : /** @cond INTERNAL_HIDDEN */
27 :
28 : struct device;
29 :
30 : /** @brief Device PM flags. */
31 : enum pm_device_flag {
32 : /** Indicate if the device is busy or not. */
33 : PM_DEVICE_FLAG_BUSY,
34 : /** Indicate if the device failed to power up. */
35 : PM_DEVICE_FLAG_TURN_ON_FAILED,
36 : /** Indicate if the device has claimed a power domain */
37 : PM_DEVICE_FLAG_PD_CLAIMED,
38 : /**
39 : * Indicates whether or not the device is capable of waking the system
40 : * up.
41 : */
42 : PM_DEVICE_FLAG_WS_CAPABLE,
43 : /** Indicates if the device is being used as wakeup source. */
44 : PM_DEVICE_FLAG_WS_ENABLED,
45 : /** Indicates if device runtime is enabled */
46 : PM_DEVICE_FLAG_RUNTIME_ENABLED,
47 : /** Indicates if the device is used as a power domain */
48 : PM_DEVICE_FLAG_PD,
49 : /** Indicates if device runtime PM should be automatically enabled */
50 : PM_DEVICE_FLAG_RUNTIME_AUTO,
51 : /** Indicates that device runtime PM supports suspending and resuming from any context. */
52 : PM_DEVICE_FLAG_ISR_SAFE,
53 : };
54 :
55 : /** @endcond */
56 :
57 : /** @brief Flag indicating that runtime PM API for the device can be called from any context.
58 : *
59 : * If @ref PM_DEVICE_ISR_SAFE flag is used for device definition, it indicates that PM actions
60 : * are synchronous and can be executed from any context. This approach can be used for cases where
61 : * suspending and resuming is short as it is executed in the critical section. This mode requires
62 : * less resources (~80 byte less RAM) and allows to use device runtime PM from any context
63 : * (including interrupts).
64 : */
65 1 : #define PM_DEVICE_ISR_SAFE 1
66 :
67 : /** @brief Device power states. */
68 1 : enum pm_device_state {
69 : /**
70 : * @brief Device hardware is powered, and the device is needed by the system.
71 : *
72 : * @details The device should be enabled in this state. Any device driver API
73 : * may be called in this state.
74 : */
75 : PM_DEVICE_STATE_ACTIVE,
76 : /**
77 : * @brief Device hardware is powered, but the device is not needed by the
78 : * system.
79 : *
80 : * @details The device should be put into its lowest internal power state,
81 : * commonly named "disabled" or "stopped".
82 : *
83 : * If a device has been specified as this device's power domain, and said
84 : * device is no longer needed by the system, this device will be
85 : * transitioned into the @ref PM_DEVICE_STATE_OFF state, followed by the
86 : * power domain device being transitioned to the
87 : * @ref PM_DEVICE_STATE_SUSPENDED state.
88 : *
89 : * A device driver may be deinitialized in this state. Once the device
90 : * driver has been deinitialized, we implicitly move to the
91 : * @ref PM_DEVICE_STATE_OFF state as the device hardware may lose power,
92 : * with no device driver to respond to the corresponding
93 : * @ref PM_DEVICE_ACTION_TURN_OFF action.
94 : *
95 : * @note This state is NOT a "low-power"/"partially operable" state,
96 : * those are configured using device driver specific APIs, and apply only
97 : * while the device is in the @ref PM_DEVICE_STATE_ACTIVE state.
98 : */
99 : PM_DEVICE_STATE_SUSPENDED,
100 : /**
101 : * @brief Device hardware is powered, but the device has been scheduled to
102 : * be suspended, as it is no longer needed by the system.
103 : *
104 : * @details This state is used when delegating suspension of a device to
105 : * the PM subsystem, optionally with residency to avoid unnecessary
106 : * suspend/resume cycles, resulting from a call to
107 : * @ref pm_device_runtime_put_async. The device will be unscheduled in case
108 : * the device becomes needed by the system.
109 : *
110 : * No device driver API calls must occur in this state.
111 : *
112 : * @note that this state is opaque to the device driver (no
113 : * @ref pm_device_action is called as this state is entered) and is used
114 : * solely by PM_DEVICE_RUNTIME.
115 : */
116 : PM_DEVICE_STATE_SUSPENDING,
117 : /**
118 : * @brief Device hardware is not powered. This is the initial state from
119 : * which a device driver is initialized.
120 : *
121 : * @details When a device driver is initialized, we do not know the state
122 : * of the device. As a result, the @ref PM_DEVICE_ACTION_TURN_ON action
123 : * should be able to transition the device from any internal state into
124 : * @ref PM_DEVICE_STATE_SUSPENDED, since no guarantees can be made across
125 : * resets. This is typically achieved through toggling a reset pin or
126 : * triggering a software reset through a register write before performing
127 : * any additional configuration needed to meet the requirements of
128 : * @ref PM_DEVICE_STATE_SUSPENDED. For devices where this is not possible,
129 : * the device driver must presume the device is in either the
130 : * @ref PM_DEVICE_STATE_OFF or @ref PM_DEVICE_STATE_SUSPENDED state at
131 : * time of initialization, as these are the states within which device
132 : * drivers may be deinitialized.
133 : *
134 : * If a device has been specified as this device's power domain, and said
135 : * device becomes needed by the system, the power domain device will be
136 : * transitioned into the @ref PM_DEVICE_STATE_ACTIVE state, followed by this
137 : * device being transitioned to the
138 : * @ref PM_DEVICE_STATE_SUSPENDED state.
139 : */
140 : PM_DEVICE_STATE_OFF
141 : };
142 :
143 : /** @brief Device PM actions. */
144 1 : enum pm_device_action {
145 : /** Suspend. */
146 : PM_DEVICE_ACTION_SUSPEND,
147 : /** Resume. */
148 : PM_DEVICE_ACTION_RESUME,
149 : /**
150 : * Turn off.
151 : * @note
152 : * Action triggered only by a power domain.
153 : */
154 : PM_DEVICE_ACTION_TURN_OFF,
155 : /**
156 : * Turn on.
157 : * @note
158 : * Action triggered only by a power domain.
159 : */
160 : PM_DEVICE_ACTION_TURN_ON,
161 : };
162 :
163 : /**
164 : * @brief Device PM action callback.
165 : *
166 : * @param dev Device instance.
167 : * @param action Requested action.
168 : *
169 : * @retval 0 If successful.
170 : * @retval -ENOTSUP If the requested action is not supported.
171 : * @retval Errno Other negative errno on failure.
172 : */
173 1 : typedef int (*pm_device_action_cb_t)(const struct device *dev,
174 : enum pm_device_action action);
175 :
176 : /**
177 : * @brief Device PM action failed callback
178 : *
179 : * @param dev Device that failed the action.
180 : * @param err Return code of action failure.
181 : *
182 : * @return True to continue iteration, false to halt iteration.
183 : */
184 1 : typedef bool (*pm_device_action_failed_cb_t)(const struct device *dev,
185 : int err);
186 :
187 : /**
188 : * @brief Device PM info
189 : *
190 : * Structure holds fields which are common for two PM devices: generic and
191 : * synchronous.
192 : */
193 1 : struct pm_device_base {
194 : /** Device PM status flags. */
195 1 : atomic_t flags;
196 : /** Device power state */
197 1 : enum pm_device_state state;
198 : /** Device PM action callback */
199 1 : pm_device_action_cb_t action_cb;
200 : #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
201 : /** Device usage count */
202 1 : uint32_t usage;
203 : #endif /* CONFIG_PM_DEVICE_RUNTIME */
204 : #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
205 : /** Power Domain it belongs */
206 : const struct device *domain;
207 : #endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
208 : };
209 :
210 : /**
211 : * @brief Runtime PM info for device with generic PM.
212 : *
213 : * Generic PM involves suspending and resuming operations which can be blocking,
214 : * long lasting or asynchronous. Runtime PM API is limited when used from
215 : * interrupt context.
216 : */
217 1 : struct pm_device {
218 : /** Base info. */
219 1 : struct pm_device_base base;
220 : #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
221 : /** Pointer to the device */
222 1 : const struct device *dev;
223 : /** Lock to synchronize the get/put operations */
224 1 : struct k_sem lock;
225 : /** Event var to listen to the sync request events */
226 1 : struct k_event event;
227 : #if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
228 : /** Work object for asynchronous calls */
229 1 : struct k_work_delayable work;
230 : #endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
231 : #endif /* CONFIG_PM_DEVICE_RUNTIME */
232 : };
233 :
234 : /**
235 : * @brief Runtime PM info for device with synchronous PM.
236 : *
237 : * Synchronous PM can be used with devices which suspend and resume operations can
238 : * be performed in the critical section as they are short and non-blocking.
239 : * Runtime PM API can be used from any context in that case.
240 : */
241 1 : struct pm_device_isr {
242 : /** Base info. */
243 1 : struct pm_device_base base;
244 : #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
245 : /** Lock to synchronize the synchronous get/put operations */
246 1 : struct k_spinlock lock;
247 : #endif
248 : };
249 :
250 : /* Base part must be the first element. */
251 : BUILD_ASSERT(offsetof(struct pm_device, base) == 0);
252 : BUILD_ASSERT(offsetof(struct pm_device_isr, base) == 0);
253 :
254 : /** @cond INTERNAL_HIDDEN */
255 :
256 : #ifdef CONFIG_PM_DEVICE_RUNTIME
257 : #define Z_PM_DEVICE_RUNTIME_INIT(obj) \
258 : .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1), \
259 : .event = Z_EVENT_INITIALIZER(obj.event),
260 : #else
261 : #define Z_PM_DEVICE_RUNTIME_INIT(obj)
262 : #endif /* CONFIG_PM_DEVICE_RUNTIME */
263 :
264 : #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
265 : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(_node_id) \
266 : .domain = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(_node_id, \
267 : power_domains)),
268 : #else
269 : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(obj)
270 : #endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
271 :
272 : /**
273 : * @brief Utility macro to initialize #pm_device_base flags
274 : *
275 : * @param node_id Devicetree node for the initialized device (can be invalid).
276 : */
277 : #define Z_PM_DEVICE_FLAGS(node_id) \
278 : (COND_CODE_1( \
279 : DT_NODE_EXISTS(node_id), \
280 : ((DT_PROP_OR(node_id, wakeup_source, 0) \
281 : << PM_DEVICE_FLAG_WS_CAPABLE) | \
282 : (DT_PROP_OR(node_id, zephyr_pm_device_runtime_auto, 0) \
283 : << PM_DEVICE_FLAG_RUNTIME_AUTO) | \
284 : (DT_NODE_HAS_COMPAT(node_id, power_domain) << \
285 : PM_DEVICE_FLAG_PD)), \
286 : (0)))
287 :
288 : /**
289 : * @brief Utility macro to initialize #pm_device.
290 : *
291 : * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
292 : * it may not be defined on all devices.
293 : *
294 : * @param obj Name of the #pm_device_base structure being initialized.
295 : * @param node_id Devicetree node for the initialized device (can be invalid).
296 : * @param pm_action_cb Device PM control callback function.
297 : * @param _flags Additional flags passed to the structure.
298 : */
299 : #define Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, _flags) \
300 : { \
301 : .flags = ATOMIC_INIT(Z_PM_DEVICE_FLAGS(node_id) | (_flags)), \
302 : .state = PM_DEVICE_STATE_ACTIVE, \
303 : .action_cb = pm_action_cb, \
304 : Z_PM_DEVICE_POWER_DOMAIN_INIT(node_id) \
305 : }
306 :
307 : /**
308 : * @brief Utility macro to initialize #pm_device_rt.
309 : *
310 : * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
311 : * it may not be defined on all devices.
312 : *
313 : * @param obj Name of the #pm_device_base structure being initialized.
314 : * @param node_id Devicetree node for the initialized device (can be invalid).
315 : * @param pm_action_cb Device PM control callback function.
316 : */
317 : #define Z_PM_DEVICE_INIT(obj, node_id, pm_action_cb, isr_safe) \
318 : { \
319 : .base = Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, \
320 : isr_safe ? BIT(PM_DEVICE_FLAG_ISR_SAFE) : 0), \
321 : COND_CODE_1(isr_safe, (), (Z_PM_DEVICE_RUNTIME_INIT(obj))) \
322 : }
323 :
324 : /**
325 : * Get the name of device PM resources.
326 : *
327 : * @param dev_id Device id.
328 : */
329 : #define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
330 :
331 : #ifdef CONFIG_PM
332 : /**
333 : * @brief Define device PM slot.
334 : *
335 : * This macro defines a pointer to a device in the pm_device_slots region.
336 : * When invoked for each device with PM, it will effectively result in a device
337 : * pointer array with the same size of the actual devices with PM enabled. This
338 : * is used internally by the PM subsystem to keep track of suspended devices
339 : * during system power transitions.
340 : *
341 : * @param dev_id Device id.
342 : */
343 : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id) \
344 : static STRUCT_SECTION_ITERABLE_ALTERNATE(pm_device_slots, device, \
345 : _CONCAT(__pm_slot_, dev_id))
346 : #else
347 : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id)
348 : #endif /* CONFIG_PM */
349 :
350 : #ifdef CONFIG_PM_DEVICE
351 : /**
352 : * Define device PM resources for the given node identifier.
353 : *
354 : * @param node_id Node identifier (DT_INVALID_NODE if not a DT device).
355 : * @param dev_id Device id.
356 : * @param pm_action_cb PM control callback.
357 : */
358 : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe) \
359 : Z_PM_DEVICE_DEFINE_SLOT(dev_id); \
360 : static struct COND_CODE_1(isr_safe, (pm_device_isr), (pm_device)) \
361 : Z_PM_DEVICE_NAME(dev_id) = \
362 : Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id, \
363 : pm_action_cb, isr_safe)
364 :
365 : /**
366 : * Get a reference to the device PM resources.
367 : *
368 : * @param dev_id Device id.
369 : */
370 : #define Z_PM_DEVICE_GET(dev_id) ((struct pm_device_base *)&Z_PM_DEVICE_NAME(dev_id))
371 :
372 : #else
373 : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)
374 : #define Z_PM_DEVICE_GET(dev_id) NULL
375 : #endif /* CONFIG_PM_DEVICE */
376 :
377 : /** @endcond */
378 :
379 : /**
380 : * Define device PM resources for the given device name.
381 : *
382 : * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
383 : *
384 : * @param dev_id Device id.
385 : * @param pm_action_cb PM control callback.
386 : * @param ... Optional flag to indicate that ISR safe. Use @ref PM_DEVICE_ISR_SAFE or 0.
387 : *
388 : * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DT_INST_DEFINE
389 : */
390 1 : #define PM_DEVICE_DEFINE(dev_id, pm_action_cb, ...) \
391 : Z_PM_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, pm_action_cb, \
392 : COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
393 :
394 : /**
395 : * Define device PM resources for the given node identifier.
396 : *
397 : * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
398 : *
399 : * @param node_id Node identifier.
400 : * @param pm_action_cb PM control callback.
401 : * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
402 : *
403 : * @see #PM_DEVICE_DT_INST_DEFINE, #PM_DEVICE_DEFINE
404 : */
405 1 : #define PM_DEVICE_DT_DEFINE(node_id, pm_action_cb, ...) \
406 : Z_PM_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), pm_action_cb, \
407 : COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
408 :
409 : /**
410 : * Define device PM resources for the given instance.
411 : *
412 : * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
413 : *
414 : * @param idx Instance index.
415 : * @param pm_action_cb PM control callback.
416 : * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
417 : *
418 : * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DEFINE
419 : */
420 1 : #define PM_DEVICE_DT_INST_DEFINE(idx, pm_action_cb, ...) \
421 : Z_PM_DEVICE_DEFINE(DT_DRV_INST(idx), \
422 : Z_DEVICE_DT_DEV_ID(DT_DRV_INST(idx)), \
423 : pm_action_cb, \
424 : COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
425 :
426 : /**
427 : * @brief Obtain a reference to the device PM resources for the given device.
428 : *
429 : * @param dev_id Device id.
430 : *
431 : * @return Reference to the device PM resources (NULL if device
432 : * @kconfig{CONFIG_PM_DEVICE} is disabled).
433 : */
434 1 : #define PM_DEVICE_GET(dev_id) \
435 : Z_PM_DEVICE_GET(dev_id)
436 :
437 : /**
438 : * @brief Obtain a reference to the device PM resources for the given node.
439 : *
440 : * @param node_id Node identifier.
441 : *
442 : * @return Reference to the device PM resources (NULL if device
443 : * @kconfig{CONFIG_PM_DEVICE} is disabled).
444 : */
445 1 : #define PM_DEVICE_DT_GET(node_id) \
446 : PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
447 :
448 : /**
449 : * @brief Obtain a reference to the device PM resources for the given instance.
450 : *
451 : * @param idx Instance index.
452 : *
453 : * @return Reference to the device PM resources (NULL if device
454 : * @kconfig{CONFIG_PM_DEVICE} is disabled).
455 : */
456 1 : #define PM_DEVICE_DT_INST_GET(idx) \
457 : PM_DEVICE_DT_GET(DT_DRV_INST(idx))
458 :
459 : /**
460 : * @brief Get name of device PM state
461 : *
462 : * @param state State id which name should be returned
463 : */
464 1 : const char *pm_device_state_str(enum pm_device_state state);
465 :
466 : /**
467 : * @brief Run a pm action on a device.
468 : *
469 : * This function calls the device PM control callback so that the device does
470 : * the necessary operations to execute the given action.
471 : *
472 : * @param dev Device instance.
473 : * @param action Device pm action.
474 : *
475 : * @retval 0 If successful.
476 : * @retval -ENOTSUP If requested state is not supported.
477 : * @retval -EALREADY If device is already at the requested state.
478 : * @retval -EBUSY If device is changing its state.
479 : * @retval -ENOSYS If device does not support PM.
480 : * @retval -EPERM If device has power state locked.
481 : * @retval Errno Other negative errno on failure.
482 : */
483 1 : int pm_device_action_run(const struct device *dev,
484 : enum pm_device_action action);
485 :
486 : /**
487 : * @brief Run a pm action on all children of a device.
488 : *
489 : * This function calls all child devices PM control callback so that the device
490 : * does the necessary operations to execute the given action.
491 : *
492 : * @param dev Device instance.
493 : * @param action Device pm action.
494 : * @param failure_cb Function to call if a child fails the action, can be NULL.
495 : */
496 1 : void pm_device_children_action_run(const struct device *dev,
497 : enum pm_device_action action,
498 : pm_device_action_failed_cb_t failure_cb);
499 :
500 : #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
501 : /**
502 : * @brief Obtain the power state of a device.
503 : *
504 : * @param dev Device instance.
505 : * @param state Pointer where device power state will be stored.
506 : *
507 : * @retval 0 If successful.
508 : * @retval -ENOSYS If device does not implement power management.
509 : */
510 1 : int pm_device_state_get(const struct device *dev,
511 : enum pm_device_state *state);
512 :
513 : /**
514 : * @brief Initialize a device state to #PM_DEVICE_STATE_SUSPENDED.
515 : *
516 : * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. However
517 : * in order to save power some drivers may choose to only initialize the device
518 : * to the suspended state, or actively put the device into the suspended state.
519 : * This function can therefore be used to notify the PM subsystem that the
520 : * device is in #PM_DEVICE_STATE_SUSPENDED instead of the default.
521 : *
522 : * @param dev Device instance.
523 : */
524 1 : static inline void pm_device_init_suspended(const struct device *dev)
525 : {
526 : struct pm_device_base *pm = dev->pm_base;
527 :
528 : pm->state = PM_DEVICE_STATE_SUSPENDED;
529 : }
530 :
531 : /**
532 : * @brief Initialize a device state to #PM_DEVICE_STATE_OFF.
533 : *
534 : * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. In
535 : * general, this makes sense because the device initialization function will
536 : * resume and configure a device, leaving it operational. However, when power
537 : * domains are enabled, the device may be connected to a switchable power
538 : * source, in which case it won't be powered at boot. This function can
539 : * therefore be used to notify the PM subsystem that the device is in
540 : * #PM_DEVICE_STATE_OFF instead of the default.
541 : *
542 : * @param dev Device instance.
543 : */
544 1 : static inline void pm_device_init_off(const struct device *dev)
545 : {
546 : struct pm_device_base *pm = dev->pm_base;
547 :
548 : pm->state = PM_DEVICE_STATE_OFF;
549 : }
550 :
551 : /**
552 : * @brief Mark a device as busy.
553 : *
554 : * Devices marked as busy will not be suspended when the system goes into
555 : * low-power states. This can be useful if, for example, the device is in the
556 : * middle of a transaction.
557 : *
558 : * @param dev Device instance.
559 : *
560 : * @see pm_device_busy_clear()
561 : */
562 1 : void pm_device_busy_set(const struct device *dev);
563 :
564 : /**
565 : * @brief Clear a device busy status.
566 : *
567 : * @param dev Device instance.
568 : *
569 : * @see pm_device_busy_set()
570 : */
571 1 : void pm_device_busy_clear(const struct device *dev);
572 :
573 : /**
574 : * @brief Check if any device is busy.
575 : *
576 : * @retval false If no device is busy
577 : * @retval true If one or more devices are busy
578 : */
579 1 : bool pm_device_is_any_busy(void);
580 :
581 : /**
582 : * @brief Check if a device is busy.
583 : *
584 : * @param dev Device instance.
585 : *
586 : * @retval false If the device is not busy
587 : * @retval true If the device is busy
588 : */
589 1 : bool pm_device_is_busy(const struct device *dev);
590 :
591 : /**
592 : * @brief Enable or disable a device as a wake up source.
593 : *
594 : * A device marked as a wake up source will not be suspended when the system
595 : * goes into low-power modes, thus allowing to use it as a wake up source for
596 : * the system.
597 : *
598 : * @param dev Device instance.
599 : * @param enable @c true to enable or @c false to disable
600 : *
601 : * @retval true If the wakeup source was successfully enabled.
602 : * @retval false If the wakeup source was not successfully enabled.
603 : */
604 1 : bool pm_device_wakeup_enable(const struct device *dev, bool enable);
605 :
606 : /**
607 : * @brief Check if a device is enabled as a wake up source.
608 : *
609 : * @param dev Device instance.
610 : *
611 : * @retval true if the wakeup source is enabled.
612 : * @retval false if the wakeup source is not enabled.
613 : */
614 1 : bool pm_device_wakeup_is_enabled(const struct device *dev);
615 :
616 : /**
617 : * @brief Check if a device is wake up capable
618 : *
619 : * @param dev Device instance.
620 : *
621 : * @retval true If the device is wake up capable.
622 : * @retval false If the device is not wake up capable.
623 : */
624 1 : bool pm_device_wakeup_is_capable(const struct device *dev);
625 :
626 : /**
627 : * @brief Check if the device is on a switchable power domain.
628 : *
629 : * @param dev Device instance.
630 : *
631 : * @retval true If device is on a switchable power domain.
632 : * @retval false If device is not on a switchable power domain.
633 : */
634 1 : bool pm_device_on_power_domain(const struct device *dev);
635 :
636 : /**
637 : * @brief Add a device to a power domain.
638 : *
639 : * This function adds a device to a given power domain.
640 : *
641 : * @param dev Device to be added to the power domain.
642 : * @param domain Power domain.
643 : *
644 : * @retval 0 If successful.
645 : * @retval -EALREADY If device is already part of the power domain.
646 : * @retval -ENOSYS If the application was built without power domain support.
647 : * @retval -ENOSPC If there is no space available in the power domain to add the device.
648 : */
649 1 : int pm_device_power_domain_add(const struct device *dev,
650 : const struct device *domain);
651 :
652 : /**
653 : * @brief Remove a device from a power domain.
654 : *
655 : * This function removes a device from a given power domain.
656 : *
657 : * @param dev Device to be removed from the power domain.
658 : * @param domain Power domain.
659 : *
660 : * @retval 0 If successful.
661 : * @retval -ENOSYS If the application was built without power domain support.
662 : * @retval -ENOENT If device is not in the given domain.
663 : */
664 1 : int pm_device_power_domain_remove(const struct device *dev,
665 : const struct device *domain);
666 :
667 : /**
668 : * @brief Check if the device is currently powered.
669 : *
670 : * @param dev Device instance.
671 : *
672 : * @retval true If device is currently powered, or is assumed to be powered
673 : * (i.e. it does not support PM or is not under a PM domain)
674 : * @retval false If device is not currently powered
675 : */
676 1 : bool pm_device_is_powered(const struct device *dev);
677 :
678 : /**
679 : * @brief Move a device driver into its initial device power state.
680 : *
681 : * @details This function uses the device driver's internal PM hook to
682 : * move the device from the OFF state to the initial power state expected
683 : * by the system.
684 : *
685 : * The initial power state expected by the system is:
686 : *
687 : * - ACTIVE if CONFIG_PM_DEVICE=n or (CONFIG_PM_DEVICE=y and
688 : * CONFIG_PM_DEVICE_RUNTIME=n) or (CONFIG_PM_DEVICE_RUNTIME=y and
689 : * !pm_device_runtime_is_enabled(dev)).
690 : * - SUSPENDED if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is ACTIVE.
691 : * - OFF if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is SUSPENDED.
692 : *
693 : * @note This function must be called at the end of a driver's init
694 : * function.
695 : *
696 : * @param dev Device instance.
697 : * @param action_cb Device PM control callback function.
698 : * @retval 0 On success.
699 : * @retval -errno Error code from @a action_cb on failure.
700 : */
701 1 : int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb);
702 :
703 : /**
704 : * @brief Prepare PM device for device driver deinit
705 : *
706 : * @details Ensures device is either SUSPENDED or OFF. If CONFIG_PM_DEVICE=y,
707 : * the function checks whether power management has moved the device to
708 : * either the SUSPENDED or OFF states. If CONFIG_PM_DEVICE=n, the function
709 : * uses the device driver's internal PM hook to move the device to the
710 : * SUSPENDED state.
711 : *
712 : * @note This function must be called at the beginning of a driver's deinit
713 : * function.
714 : *
715 : * @param dev Device instance.
716 : * @param action_cb Device PM control callback function.
717 : * @retval 0 if success.
718 : * @retval -EBUSY Device is not SUSPENDED nor OFF
719 : * @retval -errno code if failure.
720 : */
721 1 : int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb);
722 : #else
723 : static inline int pm_device_state_get(const struct device *dev,
724 : enum pm_device_state *state)
725 : {
726 : ARG_UNUSED(dev);
727 :
728 : *state = PM_DEVICE_STATE_ACTIVE;
729 :
730 : return 0;
731 : }
732 :
733 : static inline void pm_device_init_suspended(const struct device *dev)
734 : {
735 : ARG_UNUSED(dev);
736 : }
737 : static inline void pm_device_init_off(const struct device *dev)
738 : {
739 : ARG_UNUSED(dev);
740 : }
741 : static inline void pm_device_busy_set(const struct device *dev)
742 : {
743 : ARG_UNUSED(dev);
744 : }
745 : static inline void pm_device_busy_clear(const struct device *dev)
746 : {
747 : ARG_UNUSED(dev);
748 : }
749 : static inline bool pm_device_is_any_busy(void) { return false; }
750 : static inline bool pm_device_is_busy(const struct device *dev)
751 : {
752 : ARG_UNUSED(dev);
753 : return false;
754 : }
755 : static inline bool pm_device_wakeup_enable(const struct device *dev,
756 : bool enable)
757 : {
758 : ARG_UNUSED(dev);
759 : ARG_UNUSED(enable);
760 : return false;
761 : }
762 : static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
763 : {
764 : ARG_UNUSED(dev);
765 : return false;
766 : }
767 : static inline bool pm_device_wakeup_is_capable(const struct device *dev)
768 : {
769 : ARG_UNUSED(dev);
770 : return false;
771 : }
772 : static inline bool pm_device_on_power_domain(const struct device *dev)
773 : {
774 : ARG_UNUSED(dev);
775 : return false;
776 : }
777 :
778 : static inline int pm_device_power_domain_add(const struct device *dev,
779 : const struct device *domain)
780 : {
781 : ARG_UNUSED(dev);
782 : ARG_UNUSED(domain);
783 : return -ENOSYS;
784 : }
785 :
786 : static inline int pm_device_power_domain_remove(const struct device *dev,
787 : const struct device *domain)
788 : {
789 : ARG_UNUSED(dev);
790 : ARG_UNUSED(domain);
791 : return -ENOSYS;
792 : }
793 :
794 : static inline bool pm_device_is_powered(const struct device *dev)
795 : {
796 : ARG_UNUSED(dev);
797 : return true;
798 : }
799 :
800 : static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
801 : {
802 : int rc;
803 :
804 : /* When power management is not enabled, all drivers should initialise to active state */
805 : rc = action_cb(dev, PM_DEVICE_ACTION_TURN_ON);
806 : if ((rc < 0) && (rc != -ENOTSUP)) {
807 : return rc;
808 : }
809 :
810 : rc = action_cb(dev, PM_DEVICE_ACTION_RESUME);
811 : if (rc < 0) {
812 : return rc;
813 : }
814 :
815 : return 0;
816 : }
817 :
818 : static inline int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
819 : {
820 : return action_cb(dev, PM_DEVICE_ACTION_SUSPEND);
821 : }
822 :
823 : #endif /* CONFIG_PM_DEVICE */
824 :
825 : /** @} */
826 :
827 : #ifdef __cplusplus
828 : }
829 : #endif
830 :
831 : #endif
|