Zephyr API Documentation 4.0.0
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
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>
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
28struct device;
29
31enum pm_device_flag {
33 PM_DEVICE_FLAG_BUSY,
35 PM_DEVICE_FLAG_TURN_ON_FAILED,
37 PM_DEVICE_FLAG_PD_CLAIMED,
42 PM_DEVICE_FLAG_WS_CAPABLE,
44 PM_DEVICE_FLAG_WS_ENABLED,
46 PM_DEVICE_FLAG_RUNTIME_ENABLED,
48 PM_DEVICE_FLAG_PD,
50 PM_DEVICE_FLAG_RUNTIME_AUTO,
52 PM_DEVICE_FLAG_ISR_SAFE,
53};
54
65#define PM_DEVICE_ISR_SAFE 1
66
88
108
119typedef int (*pm_device_action_cb_t)(const struct device *dev,
120 enum pm_device_action action);
121
130typedef bool (*pm_device_action_failed_cb_t)(const struct device *dev,
131 int err);
132
146#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
149#endif /* CONFIG_PM_DEVICE_RUNTIME */
150#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
152 const struct device *domain;
153#endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
154};
155
163struct pm_device {
166#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
168 const struct device *dev;
170 struct k_sem lock;
175#endif /* CONFIG_PM_DEVICE_RUNTIME */
176};
177
188#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
191#endif
192};
193
194/* Base part must be the first element. */
195BUILD_ASSERT(offsetof(struct pm_device, base) == 0);
196BUILD_ASSERT(offsetof(struct pm_device_isr, base) == 0);
197
200#ifdef CONFIG_PM_DEVICE_RUNTIME
201#define Z_PM_DEVICE_RUNTIME_INIT(obj) \
202 .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1), \
203 .event = Z_EVENT_INITIALIZER(obj.event),
204#else
205#define Z_PM_DEVICE_RUNTIME_INIT(obj)
206#endif /* CONFIG_PM_DEVICE_RUNTIME */
207
208#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
209#define Z_PM_DEVICE_POWER_DOMAIN_INIT(_node_id) \
210 .domain = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(_node_id, \
211 power_domains)),
212#else
213#define Z_PM_DEVICE_POWER_DOMAIN_INIT(obj)
214#endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
215
221#define Z_PM_DEVICE_FLAGS(node_id) \
222 (COND_CODE_1( \
223 DT_NODE_EXISTS(node_id), \
224 ((DT_PROP_OR(node_id, wakeup_source, 0) \
225 << PM_DEVICE_FLAG_WS_CAPABLE) | \
226 (DT_PROP_OR(node_id, zephyr_pm_device_runtime_auto, 0) \
227 << PM_DEVICE_FLAG_RUNTIME_AUTO) | \
228 (DT_NODE_HAS_COMPAT(node_id, power_domain) << \
229 PM_DEVICE_FLAG_PD)), \
230 (0)))
231
243#define Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, _flags) \
244 { \
245 .flags = ATOMIC_INIT(Z_PM_DEVICE_FLAGS(node_id) | (_flags)), \
246 .state = PM_DEVICE_STATE_ACTIVE, \
247 .action_cb = pm_action_cb, \
248 Z_PM_DEVICE_POWER_DOMAIN_INIT(node_id) \
249 }
250
261#define Z_PM_DEVICE_INIT(obj, node_id, pm_action_cb, isr_safe) \
262 { \
263 .base = Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, \
264 isr_safe ? BIT(PM_DEVICE_FLAG_ISR_SAFE) : 0), \
265 COND_CODE_1(isr_safe, (), (Z_PM_DEVICE_RUNTIME_INIT(obj))) \
266 }
267
273#define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
274
275#ifdef CONFIG_PM
287#define Z_PM_DEVICE_DEFINE_SLOT(dev_id) \
288 static STRUCT_SECTION_ITERABLE_ALTERNATE(pm_device_slots, device, \
289 _CONCAT(__pm_slot_, dev_id))
290#else
291#define Z_PM_DEVICE_DEFINE_SLOT(dev_id)
292#endif /* CONFIG_PM */
293
294#ifdef CONFIG_PM_DEVICE
302#define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe) \
303 Z_PM_DEVICE_DEFINE_SLOT(dev_id); \
304 static struct COND_CODE_1(isr_safe, (pm_device_isr), (pm_device)) \
305 Z_PM_DEVICE_NAME(dev_id) = \
306 Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id, \
307 pm_action_cb, isr_safe)
308
314#define Z_PM_DEVICE_GET(dev_id) ((struct pm_device_base *)&Z_PM_DEVICE_NAME(dev_id))
315
316#else
317#define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)
318#define Z_PM_DEVICE_GET(dev_id) NULL
319#endif /* CONFIG_PM_DEVICE */
320
334#define PM_DEVICE_DEFINE(dev_id, pm_action_cb, ...) \
335 Z_PM_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, pm_action_cb, \
336 COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
337
349#define PM_DEVICE_DT_DEFINE(node_id, pm_action_cb, ...) \
350 Z_PM_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), pm_action_cb, \
351 COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
352
364#define PM_DEVICE_DT_INST_DEFINE(idx, pm_action_cb, ...) \
365 Z_PM_DEVICE_DEFINE(DT_DRV_INST(idx), \
366 Z_DEVICE_DT_DEV_ID(DT_DRV_INST(idx)), \
367 pm_action_cb, \
368 COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
369
378#define PM_DEVICE_GET(dev_id) \
379 Z_PM_DEVICE_GET(dev_id)
380
389#define PM_DEVICE_DT_GET(node_id) \
390 PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
391
400#define PM_DEVICE_DT_INST_GET(idx) \
401 PM_DEVICE_DT_GET(DT_DRV_INST(idx))
402
409
427int pm_device_action_run(const struct device *dev,
428 enum pm_device_action action);
429
441 enum pm_device_action action,
443
444#if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
454int pm_device_state_get(const struct device *dev,
455 enum pm_device_state *state);
456
468static inline void pm_device_init_suspended(const struct device *dev)
469{
470 struct pm_device_base *pm = dev->pm_base;
471
473}
474
488static inline void pm_device_init_off(const struct device *dev)
489{
490 struct pm_device_base *pm = dev->pm_base;
491
493}
494
506void pm_device_busy_set(const struct device *dev);
507
515void pm_device_busy_clear(const struct device *dev);
516
524
533bool pm_device_is_busy(const struct device *dev);
534
548bool pm_device_wakeup_enable(const struct device *dev, bool enable);
549
558bool pm_device_wakeup_is_enabled(const struct device *dev);
559
568bool pm_device_wakeup_is_capable(const struct device *dev);
569
578bool pm_device_on_power_domain(const struct device *dev);
579
593int pm_device_power_domain_add(const struct device *dev,
594 const struct device *domain);
595
609 const struct device *domain);
610
620bool pm_device_is_powered(const struct device *dev);
621
637
638#else
639static inline int pm_device_state_get(const struct device *dev,
641{
642 ARG_UNUSED(dev);
643
645
646 return 0;
647}
648
649static inline void pm_device_init_suspended(const struct device *dev)
650{
651 ARG_UNUSED(dev);
652}
653static inline void pm_device_init_off(const struct device *dev)
654{
655 ARG_UNUSED(dev);
656}
657static inline void pm_device_busy_set(const struct device *dev)
658{
659 ARG_UNUSED(dev);
660}
661static inline void pm_device_busy_clear(const struct device *dev)
662{
663 ARG_UNUSED(dev);
664}
665static inline bool pm_device_is_any_busy(void) { return false; }
666static inline bool pm_device_is_busy(const struct device *dev)
667{
668 ARG_UNUSED(dev);
669 return false;
670}
671static inline bool pm_device_wakeup_enable(const struct device *dev,
672 bool enable)
673{
674 ARG_UNUSED(dev);
675 ARG_UNUSED(enable);
676 return false;
677}
678static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
679{
680 ARG_UNUSED(dev);
681 return false;
682}
683static inline bool pm_device_wakeup_is_capable(const struct device *dev)
684{
685 ARG_UNUSED(dev);
686 return false;
687}
688static inline bool pm_device_on_power_domain(const struct device *dev)
689{
690 ARG_UNUSED(dev);
691 return false;
692}
693
694static inline int pm_device_power_domain_add(const struct device *dev,
695 const struct device *domain)
696{
697 ARG_UNUSED(dev);
698 ARG_UNUSED(domain);
699 return -ENOSYS;
700}
701
702static inline int pm_device_power_domain_remove(const struct device *dev,
703 const struct device *domain)
704{
705 ARG_UNUSED(dev);
706 ARG_UNUSED(domain);
707 return -ENOSYS;
708}
709
710static inline bool pm_device_is_powered(const struct device *dev)
711{
712 ARG_UNUSED(dev);
713 return true;
714}
715
716static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
717{
718 int rc;
719
720 /* When power management is not enabled, all drivers should initialise to active state */
722 if ((rc < 0) && (rc != -ENOTSUP)) {
723 return rc;
724 }
725
727 if (rc < 0) {
728 return rc;
729 }
730
731 return 0;
732}
733
734#endif /* CONFIG_PM_DEVICE */
735
738#ifdef __cplusplus
739}
740#endif
741
742#endif
long atomic_t
Definition atomic_types.h:15
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:468
pm_device_state
Device power states.
Definition device.h:68
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:119
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:130
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)
Setup a device driver into the lowest valid power mode.
bool pm_device_is_any_busy(void)
Check if any device is busy.
pm_device_action
Device PM actions.
Definition device.h:90
static void pm_device_init_off(const struct device *dev)
Initialize a device state to PM_DEVICE_STATE_OFF.
Definition device.h:488
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 is suspended.
Definition device.h:77
@ PM_DEVICE_STATE_OFF
Device is turned off (power removed).
Definition device.h:86
@ PM_DEVICE_STATE_SUSPENDING
Device is being suspended.
Definition device.h:79
@ PM_DEVICE_STATE_ACTIVE
Device is in active or regular state.
Definition device.h:70
@ PM_DEVICE_ACTION_TURN_OFF
Turn off.
Definition device.h:100
@ PM_DEVICE_ACTION_SUSPEND
Suspend.
Definition device.h:92
@ PM_DEVICE_ACTION_RESUME
Resume.
Definition device.h:94
@ PM_DEVICE_ACTION_TURN_ON
Turn on.
Definition device.h:106
#define ENOSYS
Function not implemented.
Definition errno.h:82
#define ENOTSUP
Unsupported value.
Definition errno.h:114
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:412
struct pm_device_base * pm_base
Definition device.h:440
Event Structure.
Definition kernel.h:2301
Kernel Spin Lock.
Definition spinlock.h:45
A structure used to submit work after a delay.
Definition kernel.h:3985
Device PM info.
Definition device.h:139
uint32_t usage
Device usage count.
Definition device.h:148
pm_device_action_cb_t action_cb
Device PM action callback.
Definition device.h:145
enum pm_device_state state
Device power state.
Definition device.h:143
atomic_t flags
Device PM status flags.
Definition device.h:141
Runtime PM info for device with synchronous PM.
Definition device.h:185
struct k_spinlock lock
Lock to synchronize the synchronous get/put operations.
Definition device.h:190
struct pm_device_base base
Base info.
Definition device.h:187
Runtime PM info for device with generic PM.
Definition device.h:163
struct k_work_delayable work
Work object for asynchronous calls.
Definition device.h:174
struct k_event event
Event var to listen to the sync request events.
Definition device.h:172
struct k_sem lock
Lock to synchronize the get/put operations.
Definition device.h:170
const struct device * dev
Pointer to the device.
Definition device.h:168
struct pm_device_base base
Base info.
Definition device.h:165