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 : #if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
226 : /** Event var to listen to the sync request events */
227 1 : struct k_event event;
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_ASYNC
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 : #elif CONFIG_PM_DEVICE_RUNTIME
261 : #define Z_PM_DEVICE_RUNTIME_INIT(obj) \
262 : .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1),
263 : #else
264 : #define Z_PM_DEVICE_RUNTIME_INIT(obj)
265 : #endif /* CONFIG_PM_DEVICE_RUNTIME */
266 :
267 : #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
268 : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(_node_id) \
269 : .domain = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(_node_id, \
270 : power_domains)),
271 : #else
272 : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(obj)
273 : #endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
274 :
275 : /**
276 : * @brief Utility macro to initialize #pm_device_base flags
277 : *
278 : * @param node_id Devicetree node for the initialized device (can be invalid).
279 : */
280 : #define Z_PM_DEVICE_FLAGS(node_id) \
281 : (COND_CODE_1( \
282 : DT_NODE_EXISTS(node_id), \
283 : ((DT_PROP_OR(node_id, wakeup_source, 0) \
284 : << PM_DEVICE_FLAG_WS_CAPABLE) | \
285 : (DT_PROP_OR(node_id, zephyr_pm_device_runtime_auto, 0) \
286 : << PM_DEVICE_FLAG_RUNTIME_AUTO) | \
287 : (DT_NODE_HAS_COMPAT(node_id, power_domain) << \
288 : PM_DEVICE_FLAG_PD)), \
289 : (0)))
290 :
291 : /**
292 : * @brief Utility macro to initialize #pm_device.
293 : *
294 : * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
295 : * it may not be defined on all devices.
296 : *
297 : * @param obj Name of the #pm_device_base structure being initialized.
298 : * @param node_id Devicetree node for the initialized device (can be invalid).
299 : * @param pm_action_cb Device PM control callback function.
300 : * @param _flags Additional flags passed to the structure.
301 : */
302 : #define Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, _flags) \
303 : { \
304 : .flags = ATOMIC_INIT(Z_PM_DEVICE_FLAGS(node_id) | (_flags)), \
305 : .state = PM_DEVICE_STATE_ACTIVE, \
306 : .action_cb = pm_action_cb, \
307 : Z_PM_DEVICE_POWER_DOMAIN_INIT(node_id) \
308 : }
309 :
310 : /**
311 : * @brief Utility macro to initialize #pm_device_rt.
312 : *
313 : * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
314 : * it may not be defined on all devices.
315 : *
316 : * @param obj Name of the #pm_device_base structure being initialized.
317 : * @param node_id Devicetree node for the initialized device (can be invalid).
318 : * @param pm_action_cb Device PM control callback function.
319 : */
320 : #define Z_PM_DEVICE_INIT(obj, node_id, pm_action_cb, isr_safe) \
321 : { \
322 : .base = Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, \
323 : isr_safe ? BIT(PM_DEVICE_FLAG_ISR_SAFE) : 0), \
324 : COND_CODE_1(isr_safe, (), (Z_PM_DEVICE_RUNTIME_INIT(obj))) \
325 : }
326 :
327 : /**
328 : * Get the name of device PM resources.
329 : *
330 : * @param dev_id Device id.
331 : */
332 : #define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
333 :
334 : #ifdef CONFIG_PM
335 : /**
336 : * @brief Define device PM slot.
337 : *
338 : * This macro defines a pointer to a device in the pm_device_slots region.
339 : * When invoked for each device with PM, it will effectively result in a device
340 : * pointer array with the same size of the actual devices with PM enabled. This
341 : * is used internally by the PM subsystem to keep track of suspended devices
342 : * during system power transitions.
343 : *
344 : * @param dev_id Device id.
345 : */
346 : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id) \
347 : static STRUCT_SECTION_ITERABLE_ALTERNATE(pm_device_slots, device, \
348 : _CONCAT(__pm_slot_, dev_id))
349 : #else
350 : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id)
351 : #endif /* CONFIG_PM */
352 :
353 : #ifdef CONFIG_PM_DEVICE
354 : /**
355 : * Define device PM resources for the given node identifier.
356 : *
357 : * @param node_id Node identifier (DT_INVALID_NODE if not a DT device).
358 : * @param dev_id Device id.
359 : * @param pm_action_cb PM control callback.
360 : */
361 : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe) \
362 : Z_PM_DEVICE_DEFINE_SLOT(dev_id); \
363 : static struct COND_CODE_1(isr_safe, (pm_device_isr), (pm_device)) \
364 : Z_PM_DEVICE_NAME(dev_id) = \
365 : Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id, \
366 : pm_action_cb, isr_safe)
367 :
368 : /**
369 : * Get a reference to the device PM resources.
370 : *
371 : * @param dev_id Device id.
372 : */
373 : #define Z_PM_DEVICE_GET(dev_id) ((struct pm_device_base *)&Z_PM_DEVICE_NAME(dev_id))
374 :
375 : #else
376 : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)
377 : #define Z_PM_DEVICE_GET(dev_id) NULL
378 : #endif /* CONFIG_PM_DEVICE */
379 :
380 : /** @endcond */
381 :
382 : /**
383 : * Define device PM resources for the given device name.
384 : *
385 : * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
386 : *
387 : * @param dev_id Device id.
388 : * @param pm_action_cb PM control callback.
389 : * @param ... Optional flag to indicate that ISR safe. Use @ref PM_DEVICE_ISR_SAFE or 0.
390 : *
391 : * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DT_INST_DEFINE
392 : */
393 1 : #define PM_DEVICE_DEFINE(dev_id, pm_action_cb, ...) \
394 : Z_PM_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, pm_action_cb, \
395 : COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
396 :
397 : /**
398 : * Define device PM resources for the given node identifier.
399 : *
400 : * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
401 : *
402 : * @param node_id Node identifier.
403 : * @param pm_action_cb PM control callback.
404 : * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
405 : *
406 : * @see #PM_DEVICE_DT_INST_DEFINE, #PM_DEVICE_DEFINE
407 : */
408 1 : #define PM_DEVICE_DT_DEFINE(node_id, pm_action_cb, ...) \
409 : Z_PM_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), pm_action_cb, \
410 : COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
411 :
412 : /**
413 : * Define device PM resources for the given instance.
414 : *
415 : * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
416 : *
417 : * @param idx Instance index.
418 : * @param pm_action_cb PM control callback.
419 : * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
420 : *
421 : * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DEFINE
422 : */
423 1 : #define PM_DEVICE_DT_INST_DEFINE(idx, pm_action_cb, ...) \
424 : Z_PM_DEVICE_DEFINE(DT_DRV_INST(idx), \
425 : Z_DEVICE_DT_DEV_ID(DT_DRV_INST(idx)), \
426 : pm_action_cb, \
427 : COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
428 :
429 : /**
430 : * @brief Obtain a reference to the device PM resources for the given device.
431 : *
432 : * @param dev_id Device id.
433 : *
434 : * @return Reference to the device PM resources (NULL if device
435 : * @kconfig{CONFIG_PM_DEVICE} is disabled).
436 : */
437 1 : #define PM_DEVICE_GET(dev_id) \
438 : Z_PM_DEVICE_GET(dev_id)
439 :
440 : /**
441 : * @brief Obtain a reference to the device PM resources for the given node.
442 : *
443 : * @param node_id Node identifier.
444 : *
445 : * @return Reference to the device PM resources (NULL if device
446 : * @kconfig{CONFIG_PM_DEVICE} is disabled).
447 : */
448 1 : #define PM_DEVICE_DT_GET(node_id) \
449 : PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
450 :
451 : /**
452 : * @brief Obtain a reference to the device PM resources for the given instance.
453 : *
454 : * @param idx Instance index.
455 : *
456 : * @return Reference to the device PM resources (NULL if device
457 : * @kconfig{CONFIG_PM_DEVICE} is disabled).
458 : */
459 1 : #define PM_DEVICE_DT_INST_GET(idx) \
460 : PM_DEVICE_DT_GET(DT_DRV_INST(idx))
461 :
462 : /**
463 : * @brief Get name of device PM state
464 : *
465 : * @param state State id which name should be returned
466 : */
467 1 : const char *pm_device_state_str(enum pm_device_state state);
468 :
469 : /**
470 : * @brief Run a pm action on a device.
471 : *
472 : * This function calls the device PM control callback so that the device does
473 : * the necessary operations to execute the given action.
474 : *
475 : * @param dev Device instance.
476 : * @param action Device pm action.
477 : *
478 : * @retval 0 If successful.
479 : * @retval -ENOTSUP If requested state is not supported.
480 : * @retval -EALREADY If device is already at the requested state.
481 : * @retval -EBUSY If device is changing its state.
482 : * @retval -ENOSYS If device does not support PM.
483 : * @retval -EPERM If device has power state locked.
484 : * @retval Errno Other negative errno on failure.
485 : */
486 1 : int pm_device_action_run(const struct device *dev,
487 : enum pm_device_action action);
488 :
489 : /**
490 : * @brief Run a pm action on all children of a device.
491 : *
492 : * This function calls all child devices PM control callback so that the device
493 : * does the necessary operations to execute the given action.
494 : *
495 : * @param dev Device instance.
496 : * @param action Device pm action.
497 : * @param failure_cb Function to call if a child fails the action, can be NULL.
498 : */
499 1 : void pm_device_children_action_run(const struct device *dev,
500 : enum pm_device_action action,
501 : pm_device_action_failed_cb_t failure_cb);
502 :
503 : #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
504 : /**
505 : * @brief Obtain the power state of a device.
506 : *
507 : * @param dev Device instance.
508 : * @param state Pointer where device power state will be stored.
509 : *
510 : * @retval 0 If successful.
511 : * @retval -ENOSYS If device does not implement power management.
512 : */
513 1 : int pm_device_state_get(const struct device *dev,
514 : enum pm_device_state *state);
515 :
516 : /**
517 : * @brief Initialize a device state to #PM_DEVICE_STATE_SUSPENDED.
518 : *
519 : * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. However
520 : * in order to save power some drivers may choose to only initialize the device
521 : * to the suspended state, or actively put the device into the suspended state.
522 : * This function can therefore be used to notify the PM subsystem that the
523 : * device is in #PM_DEVICE_STATE_SUSPENDED instead of the default.
524 : *
525 : * @param dev Device instance.
526 : */
527 1 : static inline void pm_device_init_suspended(const struct device *dev)
528 : {
529 : struct pm_device_base *pm = dev->pm_base;
530 :
531 : pm->state = PM_DEVICE_STATE_SUSPENDED;
532 : }
533 :
534 : /**
535 : * @brief Initialize a device state to #PM_DEVICE_STATE_OFF.
536 : *
537 : * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. In
538 : * general, this makes sense because the device initialization function will
539 : * resume and configure a device, leaving it operational. However, when power
540 : * domains are enabled, the device may be connected to a switchable power
541 : * source, in which case it won't be powered at boot. This function can
542 : * therefore be used to notify the PM subsystem that the device is in
543 : * #PM_DEVICE_STATE_OFF instead of the default.
544 : *
545 : * @param dev Device instance.
546 : */
547 1 : static inline void pm_device_init_off(const struct device *dev)
548 : {
549 : struct pm_device_base *pm = dev->pm_base;
550 :
551 : pm->state = PM_DEVICE_STATE_OFF;
552 : }
553 :
554 : /**
555 : * @brief Mark a device as busy.
556 : *
557 : * Devices marked as busy will not be suspended when the system goes into
558 : * low-power states. This can be useful if, for example, the device is in the
559 : * middle of a transaction.
560 : *
561 : * @param dev Device instance.
562 : *
563 : * @see pm_device_busy_clear()
564 : */
565 1 : void pm_device_busy_set(const struct device *dev);
566 :
567 : /**
568 : * @brief Clear a device busy status.
569 : *
570 : * @param dev Device instance.
571 : *
572 : * @see pm_device_busy_set()
573 : */
574 1 : void pm_device_busy_clear(const struct device *dev);
575 :
576 : /**
577 : * @brief Check if any device is busy.
578 : *
579 : * @retval false If no device is busy
580 : * @retval true If one or more devices are busy
581 : */
582 1 : bool pm_device_is_any_busy(void);
583 :
584 : /**
585 : * @brief Check if a device is busy.
586 : *
587 : * @param dev Device instance.
588 : *
589 : * @retval false If the device is not busy
590 : * @retval true If the device is busy
591 : */
592 1 : bool pm_device_is_busy(const struct device *dev);
593 :
594 : /**
595 : * @brief Enable or disable a device as a wake up source.
596 : *
597 : * A device marked as a wake up source will not be suspended when the system
598 : * goes into low-power modes, thus allowing to use it as a wake up source for
599 : * the system.
600 : *
601 : * @param dev Device instance.
602 : * @param enable @c true to enable or @c false to disable
603 : *
604 : * @retval true If the wakeup source was successfully enabled.
605 : * @retval false If the wakeup source was not successfully enabled.
606 : */
607 1 : bool pm_device_wakeup_enable(const struct device *dev, bool enable);
608 :
609 : /**
610 : * @brief Check if a device is enabled as a wake up source.
611 : *
612 : * @param dev Device instance.
613 : *
614 : * @retval true if the wakeup source is enabled.
615 : * @retval false if the wakeup source is not enabled.
616 : */
617 1 : bool pm_device_wakeup_is_enabled(const struct device *dev);
618 :
619 : /**
620 : * @brief Check if a device is wake up capable
621 : *
622 : * @param dev Device instance.
623 : *
624 : * @retval true If the device is wake up capable.
625 : * @retval false If the device is not wake up capable.
626 : */
627 1 : bool pm_device_wakeup_is_capable(const struct device *dev);
628 :
629 : /**
630 : * @brief Check if the device is on a switchable power domain.
631 : *
632 : * @param dev Device instance.
633 : *
634 : * @retval true If device is on a switchable power domain.
635 : * @retval false If device is not on a switchable power domain.
636 : */
637 1 : bool pm_device_on_power_domain(const struct device *dev);
638 :
639 : /**
640 : * @brief Add a device to a power domain.
641 : *
642 : * This function adds a device to a given power domain.
643 : *
644 : * @param dev Device to be added to the power domain.
645 : * @param domain Power domain.
646 : *
647 : * @retval 0 If successful.
648 : * @retval -EALREADY If device is already part of the power domain.
649 : * @retval -ENOSYS If the application was built without power domain support.
650 : * @retval -ENOSPC If there is no space available in the power domain to add the device.
651 : */
652 1 : int pm_device_power_domain_add(const struct device *dev,
653 : const struct device *domain);
654 :
655 : /**
656 : * @brief Remove a device from a power domain.
657 : *
658 : * This function removes a device from a given power domain.
659 : *
660 : * @param dev Device to be removed from the power domain.
661 : * @param domain Power domain.
662 : *
663 : * @retval 0 If successful.
664 : * @retval -ENOSYS If the application was built without power domain support.
665 : * @retval -ENOENT If device is not in the given domain.
666 : */
667 1 : int pm_device_power_domain_remove(const struct device *dev,
668 : const struct device *domain);
669 :
670 : /**
671 : * @brief Check if the device is currently powered.
672 : *
673 : * @param dev Device instance.
674 : *
675 : * @retval true If device is currently powered, or is assumed to be powered
676 : * (i.e. it does not support PM or is not under a PM domain)
677 : * @retval false If device is not currently powered
678 : */
679 1 : bool pm_device_is_powered(const struct device *dev);
680 :
681 : /**
682 : * @brief Move a device driver into its initial device power state.
683 : *
684 : * @details This function uses the device driver's internal PM hook to
685 : * move the device from the OFF state to the initial power state expected
686 : * by the system.
687 : *
688 : * The initial power state expected by the system is:
689 : *
690 : * - ACTIVE if CONFIG_PM_DEVICE=n or (CONFIG_PM_DEVICE=y and
691 : * CONFIG_PM_DEVICE_RUNTIME=n) or (CONFIG_PM_DEVICE_RUNTIME=y and
692 : * !pm_device_runtime_is_enabled(dev)).
693 : * - SUSPENDED if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is ACTIVE.
694 : * - OFF if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is SUSPENDED.
695 : *
696 : * @note This function must be called at the end of a driver's init
697 : * function.
698 : *
699 : * @param dev Device instance.
700 : * @param action_cb Device PM control callback function.
701 : * @retval 0 On success.
702 : * @retval -errno Error code from @a action_cb on failure.
703 : */
704 1 : int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb);
705 :
706 : /**
707 : * @brief Prepare PM device for device driver deinit
708 : *
709 : * @details Ensures device is either SUSPENDED or OFF. If CONFIG_PM_DEVICE=y,
710 : * the function checks whether power management has moved the device to
711 : * either the SUSPENDED or OFF states. If CONFIG_PM_DEVICE=n, the function
712 : * uses the device driver's internal PM hook to move the device to the
713 : * SUSPENDED state.
714 : *
715 : * @note This function must be called at the beginning of a driver's deinit
716 : * function.
717 : *
718 : * @param dev Device instance.
719 : * @param action_cb Device PM control callback function.
720 : * @retval 0 if success.
721 : * @retval -EBUSY Device is not SUSPENDED nor OFF
722 : * @retval -errno code if failure.
723 : */
724 1 : int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb);
725 : #else
726 : static inline int pm_device_state_get(const struct device *dev,
727 : enum pm_device_state *state)
728 : {
729 : ARG_UNUSED(dev);
730 :
731 : *state = PM_DEVICE_STATE_ACTIVE;
732 :
733 : return 0;
734 : }
735 :
736 : static inline void pm_device_init_suspended(const struct device *dev)
737 : {
738 : ARG_UNUSED(dev);
739 : }
740 : static inline void pm_device_init_off(const struct device *dev)
741 : {
742 : ARG_UNUSED(dev);
743 : }
744 : static inline void pm_device_busy_set(const struct device *dev)
745 : {
746 : ARG_UNUSED(dev);
747 : }
748 : static inline void pm_device_busy_clear(const struct device *dev)
749 : {
750 : ARG_UNUSED(dev);
751 : }
752 : static inline bool pm_device_is_any_busy(void) { return false; }
753 : static inline bool pm_device_is_busy(const struct device *dev)
754 : {
755 : ARG_UNUSED(dev);
756 : return false;
757 : }
758 : static inline bool pm_device_wakeup_enable(const struct device *dev,
759 : bool enable)
760 : {
761 : ARG_UNUSED(dev);
762 : ARG_UNUSED(enable);
763 : return false;
764 : }
765 : static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
766 : {
767 : ARG_UNUSED(dev);
768 : return false;
769 : }
770 : static inline bool pm_device_wakeup_is_capable(const struct device *dev)
771 : {
772 : ARG_UNUSED(dev);
773 : return false;
774 : }
775 : static inline bool pm_device_on_power_domain(const struct device *dev)
776 : {
777 : ARG_UNUSED(dev);
778 : return false;
779 : }
780 :
781 : static inline int pm_device_power_domain_add(const struct device *dev,
782 : const struct device *domain)
783 : {
784 : ARG_UNUSED(dev);
785 : ARG_UNUSED(domain);
786 : return -ENOSYS;
787 : }
788 :
789 : static inline int pm_device_power_domain_remove(const struct device *dev,
790 : const struct device *domain)
791 : {
792 : ARG_UNUSED(dev);
793 : ARG_UNUSED(domain);
794 : return -ENOSYS;
795 : }
796 :
797 : static inline bool pm_device_is_powered(const struct device *dev)
798 : {
799 : ARG_UNUSED(dev);
800 : return true;
801 : }
802 :
803 : static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
804 : {
805 : int rc;
806 :
807 : /* When power management is not enabled, all drivers should initialise to active state */
808 : rc = action_cb(dev, PM_DEVICE_ACTION_TURN_ON);
809 : if ((rc < 0) && (rc != -ENOTSUP)) {
810 : return rc;
811 : }
812 :
813 : rc = action_cb(dev, PM_DEVICE_ACTION_RESUME);
814 : if (rc < 0) {
815 : return rc;
816 : }
817 :
818 : return 0;
819 : }
820 :
821 : static inline int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
822 : {
823 : return action_cb(dev, PM_DEVICE_ACTION_SUSPEND);
824 : }
825 :
826 : #endif /* CONFIG_PM_DEVICE */
827 :
828 : /** @} */
829 :
830 : #ifdef __cplusplus
831 : }
832 : #endif
833 :
834 : #endif
|