Zephyr Project API 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
device.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
12
13#ifndef ZEPHYR_INCLUDE_PM_DEVICE_H_
14#define ZEPHYR_INCLUDE_PM_DEVICE_H_
15
16#include <zephyr/device.h>
17#include <zephyr/kernel.h>
18#include <zephyr/sys/atomic.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
33
35
36struct device;
37
39enum pm_device_flag {
41 PM_DEVICE_FLAG_BUSY,
43 PM_DEVICE_FLAG_TURN_ON_FAILED,
45 PM_DEVICE_FLAG_PD_CLAIMED,
50 PM_DEVICE_FLAG_WS_CAPABLE,
52 PM_DEVICE_FLAG_WS_ENABLED,
54 PM_DEVICE_FLAG_RUNTIME_ENABLED,
56 PM_DEVICE_FLAG_PD,
58 PM_DEVICE_FLAG_RUNTIME_AUTO,
60 PM_DEVICE_FLAG_ISR_SAFE,
62 PM_DEVICE_FLAG_PD_SUSPENDED,
63};
64
66
75#define PM_DEVICE_ISR_SAFE 1
76
152
183
193typedef int (*pm_device_action_cb_t)(const struct device *dev,
194 enum pm_device_action action);
195
204typedef bool (*pm_device_action_failed_cb_t)(const struct device *dev,
205 int err);
206
220#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
223#endif /* CONFIG_PM_DEVICE_RUNTIME */
224#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
226 const struct device *domain;
227#endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
228};
229
237struct pm_device {
240#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
242 const struct device *dev;
244 struct k_sem lock;
245#if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
250#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
251#endif /* CONFIG_PM_DEVICE_RUNTIME */
252};
253
264#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
267#endif
268};
269
270/* Base part must be the first element. */
271BUILD_ASSERT(offsetof(struct pm_device, base) == 0);
272BUILD_ASSERT(offsetof(struct pm_device_isr, base) == 0);
273
275
276#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
277#define Z_PM_DEVICE_RUNTIME_INIT(obj) \
278 .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1), \
279 .event = Z_EVENT_INITIALIZER(obj.event),
280#elif CONFIG_PM_DEVICE_RUNTIME
281#define Z_PM_DEVICE_RUNTIME_INIT(obj) \
282 .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1),
283#else
284#define Z_PM_DEVICE_RUNTIME_INIT(obj)
285#endif /* CONFIG_PM_DEVICE_RUNTIME */
286
287#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
288#define Z_PM_DEVICE_POWER_DOMAIN_INIT(_node_id) \
289 .domain = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(_node_id, \
290 power_domains)),
291#else
292#define Z_PM_DEVICE_POWER_DOMAIN_INIT(obj)
293#endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
294
300#define Z_PM_DEVICE_FLAGS(node_id) \
301 (COND_CODE_1( \
302 DT_NODE_EXISTS(node_id), \
303 ((DT_PROP_OR(node_id, wakeup_source, 0) \
304 << PM_DEVICE_FLAG_WS_CAPABLE) | \
305 (DT_PROP_OR(node_id, zephyr_pm_device_runtime_auto, 0) \
306 << PM_DEVICE_FLAG_RUNTIME_AUTO) | \
307 (DT_NODE_HAS_COMPAT(node_id, power_domain) << \
308 PM_DEVICE_FLAG_PD)), \
309 (0)))
310
322#define Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, _flags) \
323 { \
324 .flags = ATOMIC_INIT(Z_PM_DEVICE_FLAGS(node_id) | (_flags)), \
325 .state = PM_DEVICE_STATE_ACTIVE, \
326 .action_cb = pm_action_cb, \
327 Z_PM_DEVICE_POWER_DOMAIN_INIT(node_id) \
328 }
329
340#define Z_PM_DEVICE_INIT(obj, node_id, pm_action_cb, isr_safe) \
341 { \
342 .base = Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, \
343 isr_safe ? BIT(PM_DEVICE_FLAG_ISR_SAFE) : 0), \
344 COND_CODE_1(isr_safe, (), (Z_PM_DEVICE_RUNTIME_INIT(obj))) \
345 }
346
352#define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
353
354#ifdef CONFIG_PM
366#define Z_PM_DEVICE_DEFINE_SLOT(dev_id) \
367 static STRUCT_SECTION_ITERABLE_ALTERNATE(pm_device_slots, device, \
368 _CONCAT(__pm_slot_, dev_id))
369#else
370#define Z_PM_DEVICE_DEFINE_SLOT(dev_id)
371#endif /* CONFIG_PM */
372
373#ifdef CONFIG_PM_DEVICE
381#define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe) \
382 Z_PM_DEVICE_DEFINE_SLOT(dev_id); \
383 static struct COND_CODE_1(isr_safe, (pm_device_isr), (pm_device)) \
384 Z_PM_DEVICE_NAME(dev_id) = \
385 Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id, \
386 pm_action_cb, isr_safe)
387
393#define Z_PM_DEVICE_GET(dev_id) ((struct pm_device_base *)&Z_PM_DEVICE_NAME(dev_id))
394
395#else
396#define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)
397#define Z_PM_DEVICE_GET(dev_id) NULL
398#endif /* CONFIG_PM_DEVICE */
399
401
413#define PM_DEVICE_DEFINE(dev_id, pm_action_cb, ...) \
414 Z_PM_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, pm_action_cb, \
415 COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
416
428#define PM_DEVICE_DT_DEFINE(node_id, pm_action_cb, ...) \
429 Z_PM_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), pm_action_cb, \
430 COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
431
443#define PM_DEVICE_DT_INST_DEFINE(idx, pm_action_cb, ...) \
444 Z_PM_DEVICE_DEFINE(DT_DRV_INST(idx), \
445 Z_DEVICE_DT_DEV_ID(DT_DRV_INST(idx)), \
446 pm_action_cb, \
447 COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
448
457#define PM_DEVICE_GET(dev_id) \
458 Z_PM_DEVICE_GET(dev_id)
459
468#define PM_DEVICE_DT_GET(node_id) \
469 PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
470
479#define PM_DEVICE_DT_INST_GET(idx) \
480 PM_DEVICE_DT_GET(DT_DRV_INST(idx))
481
488
506int pm_device_action_run(const struct device *dev,
507 enum pm_device_action action);
508
520 enum pm_device_action action,
522
523#if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
533int pm_device_state_get(const struct device *dev,
534 enum pm_device_state *state);
535
547static inline void pm_device_init_suspended(const struct device *dev)
548{
549 struct pm_device_base *pm = dev->pm_base;
550
552}
553
567static inline void pm_device_init_off(const struct device *dev)
568{
569 struct pm_device_base *pm = dev->pm_base;
570
572}
573
585void pm_device_busy_set(const struct device *dev);
586
594void pm_device_busy_clear(const struct device *dev);
595
603
612bool pm_device_is_busy(const struct device *dev);
613
627bool pm_device_wakeup_enable(const struct device *dev, bool enable);
628
637bool pm_device_wakeup_is_enabled(const struct device *dev);
638
647bool pm_device_wakeup_is_capable(const struct device *dev);
648
657bool pm_device_on_power_domain(const struct device *dev);
658
672int pm_device_power_domain_add(const struct device *dev,
673 const struct device *domain);
674
688 const struct device *domain);
689
699bool pm_device_is_powered(const struct device *dev);
700
724
743#else
744static inline int pm_device_state_get(const struct device *dev,
746{
747 ARG_UNUSED(dev);
748
750
751 return 0;
752}
753
754static inline void pm_device_init_suspended(const struct device *dev)
755{
756 ARG_UNUSED(dev);
757}
758static inline void pm_device_init_off(const struct device *dev)
759{
760 ARG_UNUSED(dev);
761}
762static inline void pm_device_busy_set(const struct device *dev)
763{
764 ARG_UNUSED(dev);
765}
766static inline void pm_device_busy_clear(const struct device *dev)
767{
768 ARG_UNUSED(dev);
769}
770static inline bool pm_device_is_any_busy(void) { return false; }
771static inline bool pm_device_is_busy(const struct device *dev)
772{
773 ARG_UNUSED(dev);
774 return false;
775}
776static inline bool pm_device_wakeup_enable(const struct device *dev,
777 bool enable)
778{
779 ARG_UNUSED(dev);
780 ARG_UNUSED(enable);
781 return false;
782}
783static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
784{
785 ARG_UNUSED(dev);
786 return false;
787}
788static inline bool pm_device_wakeup_is_capable(const struct device *dev)
789{
790 ARG_UNUSED(dev);
791 return false;
792}
793static inline bool pm_device_on_power_domain(const struct device *dev)
794{
795 ARG_UNUSED(dev);
796 return false;
797}
798
799static inline int pm_device_power_domain_add(const struct device *dev,
800 const struct device *domain)
801{
802 ARG_UNUSED(dev);
803 ARG_UNUSED(domain);
804 return -ENOSYS;
805}
806
807static inline int pm_device_power_domain_remove(const struct device *dev,
808 const struct device *domain)
809{
810 ARG_UNUSED(dev);
811 ARG_UNUSED(domain);
812 return -ENOSYS;
813}
814
815static inline bool pm_device_is_powered(const struct device *dev)
816{
817 ARG_UNUSED(dev);
818 return true;
819}
820
821static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
822{
823 int rc;
824
825 /* When power management is not enabled, all drivers should initialise to active state */
827 if ((rc < 0) && (rc != -ENOTSUP)) {
828 return rc;
829 }
830
832 if (rc < 0) {
833 return rc;
834 }
835
836 return 0;
837}
838
839static inline int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
840{
842}
843
844#endif /* CONFIG_PM_DEVICE */
845
847
848#ifdef __cplusplus
849}
850#endif
851
852#endif
long atomic_t
Atomic integer variable.
Definition atomic_types.h:31
bool pm_device_wakeup_is_enabled(const struct device *dev)
Check if a device is enabled as a wake up source.
int pm_device_power_domain_remove(const struct device *dev, const struct device *domain)
Remove a device from a power domain.
bool pm_device_on_power_domain(const struct device *dev)
Check if the device is on a switchable power domain.
int pm_device_action_run(const struct device *dev, enum pm_device_action action)
Run a pm action on a device.
static void pm_device_init_suspended(const struct device *dev)
Initialize a device state to PM_DEVICE_STATE_SUSPENDED.
Definition device.h:547
pm_device_state
Device power states.
Definition device.h:78
bool pm_device_wakeup_enable(const struct device *dev, bool enable)
Enable or disable a device as a wake up source.
void pm_device_children_action_run(const struct device *dev, enum pm_device_action action, pm_device_action_failed_cb_t failure_cb)
Run a pm action on all children of a device.
void pm_device_busy_set(const struct device *dev)
Mark a device as busy.
int(* pm_device_action_cb_t)(const struct device *dev, enum pm_device_action action)
Device PM action callback.
Definition device.h:193
void pm_device_busy_clear(const struct device *dev)
Clear a device busy status.
bool pm_device_is_busy(const struct device *dev)
Check if a device is busy.
bool(* pm_device_action_failed_cb_t)(const struct device *dev, int err)
Device PM action failed callback.
Definition device.h:204
bool pm_device_is_powered(const struct device *dev)
Check if the device is currently powered.
int pm_device_power_domain_add(const struct device *dev, const struct device *domain)
Add a device to a power domain.
bool pm_device_wakeup_is_capable(const struct device *dev)
Check if a device is wake up capable.
const char * pm_device_state_str(enum pm_device_state state)
Get name of device PM state.
int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
Move a device driver into its initial device power state.
int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
Prepare PM device for device driver deinit.
bool pm_device_is_any_busy(void)
Check if any device is busy.
pm_device_action
Device PM actions.
Definition device.h:154
static void pm_device_init_off(const struct device *dev)
Initialize a device state to PM_DEVICE_STATE_OFF.
Definition device.h:567
int pm_device_state_get(const struct device *dev, enum pm_device_state *state)
Obtain the power state of a device.
@ PM_DEVICE_STATE_SUSPENDED
Device hardware is powered, but the device is not needed by the system.
Definition device.h:109
@ PM_DEVICE_STATE_OFF
Device hardware is not powered.
Definition device.h:150
@ PM_DEVICE_STATE_SUSPENDING
Device hardware is powered, but the device has been scheduled to be suspended, as it is no longer nee...
Definition device.h:126
@ PM_DEVICE_STATE_ACTIVE
Device hardware is powered, and the device is needed by the system.
Definition device.h:85
@ PM_DEVICE_ACTION_TURN_OFF
Turn off.
Definition device.h:173
@ PM_DEVICE_ACTION_SUSPEND
Suspend.
Definition device.h:156
@ PM_DEVICE_ACTION_RESUME
Resume.
Definition device.h:158
@ PM_DEVICE_ACTION_TURN_ON
Turn on.
Definition device.h:181
#define ENOSYS
Function not implemented.
Definition errno.h:83
#define ENOTSUP
Unsupported value.
Definition errno.h:115
#define BUILD_ASSERT(EXPR, MSG...)
Definition llvm.h:51
Public kernel APIs.
state
Definition parser_state.h:29
#define bool
Definition stdbool.h:13
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
Runtime device structure (in ROM) per driver instance.
Definition device.h:525
struct pm_device_base * pm_base
Definition device.h:557
Event Structure.
Definition kernel.h:2695
Semaphore structure.
Definition kernel.h:3726
Kernel Spin Lock.
Definition spinlock.h:45
A structure used to submit work after a delay.
Definition kernel.h:4678
Device PM info.
Definition device.h:213
uint32_t usage
Device usage count.
Definition device.h:222
pm_device_action_cb_t action_cb
Device PM action callback.
Definition device.h:219
enum pm_device_state state
Device power state.
Definition device.h:217
atomic_t flags
Device PM status flags.
Definition device.h:215
Runtime PM info for device with synchronous PM.
Definition device.h:261
struct k_spinlock lock
Lock to synchronize the synchronous get/put operations.
Definition device.h:266
struct pm_device_base base
Base info.
Definition device.h:263
Runtime PM info for device with generic PM.
Definition device.h:237
struct k_work_delayable work
Work object for asynchronous calls.
Definition device.h:249
struct k_event event
Event var to listen to the sync request events.
Definition device.h:247
struct k_sem lock
Lock to synchronize the get/put operations.
Definition device.h:244
const struct device * dev
Pointer to the device.
Definition device.h:242
struct pm_device_base base
Base info.
Definition device.h:239
Header file for the Atomic operations API.
Iterable sections helpers.