Zephyr API Documentation 4.2.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
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
25
27
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
56
65#define PM_DEVICE_ISR_SAFE 1
66
142
162
173typedef int (*pm_device_action_cb_t)(const struct device *dev,
174 enum pm_device_action action);
175
184typedef bool (*pm_device_action_failed_cb_t)(const struct device *dev,
185 int err);
186
200#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
203#endif /* CONFIG_PM_DEVICE_RUNTIME */
204#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
206 const struct device *domain;
207#endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
208};
209
217struct pm_device {
220#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
222 const struct device *dev;
224 struct k_sem lock;
225#if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
230#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
231#endif /* CONFIG_PM_DEVICE_RUNTIME */
232};
233
244#if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
247#endif
248};
249
250/* Base part must be the first element. */
251BUILD_ASSERT(offsetof(struct pm_device, base) == 0);
252BUILD_ASSERT(offsetof(struct pm_device_isr, base) == 0);
253
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
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
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
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
332#define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
333
334#ifdef CONFIG_PM
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
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
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
381
393#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
408#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
423#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
437#define PM_DEVICE_GET(dev_id) \
438 Z_PM_DEVICE_GET(dev_id)
439
448#define PM_DEVICE_DT_GET(node_id) \
449 PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
450
459#define PM_DEVICE_DT_INST_GET(idx) \
460 PM_DEVICE_DT_GET(DT_DRV_INST(idx))
461
468
486int pm_device_action_run(const struct device *dev,
487 enum pm_device_action action);
488
500 enum pm_device_action action,
502
503#if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
513int pm_device_state_get(const struct device *dev,
514 enum pm_device_state *state);
515
527static inline void pm_device_init_suspended(const struct device *dev)
528{
529 struct pm_device_base *pm = dev->pm_base;
530
532}
533
547static inline void pm_device_init_off(const struct device *dev)
548{
549 struct pm_device_base *pm = dev->pm_base;
550
552}
553
565void pm_device_busy_set(const struct device *dev);
566
574void pm_device_busy_clear(const struct device *dev);
575
583
592bool pm_device_is_busy(const struct device *dev);
593
607bool pm_device_wakeup_enable(const struct device *dev, bool enable);
608
617bool pm_device_wakeup_is_enabled(const struct device *dev);
618
627bool pm_device_wakeup_is_capable(const struct device *dev);
628
637bool pm_device_on_power_domain(const struct device *dev);
638
652int pm_device_power_domain_add(const struct device *dev,
653 const struct device *domain);
654
668 const struct device *domain);
669
679bool pm_device_is_powered(const struct device *dev);
680
705
725#else
726static inline int pm_device_state_get(const struct device *dev,
728{
729 ARG_UNUSED(dev);
730
732
733 return 0;
734}
735
736static inline void pm_device_init_suspended(const struct device *dev)
737{
738 ARG_UNUSED(dev);
739}
740static inline void pm_device_init_off(const struct device *dev)
741{
742 ARG_UNUSED(dev);
743}
744static inline void pm_device_busy_set(const struct device *dev)
745{
746 ARG_UNUSED(dev);
747}
748static inline void pm_device_busy_clear(const struct device *dev)
749{
750 ARG_UNUSED(dev);
751}
752static inline bool pm_device_is_any_busy(void) { return false; }
753static inline bool pm_device_is_busy(const struct device *dev)
754{
755 ARG_UNUSED(dev);
756 return false;
757}
758static 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}
765static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
766{
767 ARG_UNUSED(dev);
768 return false;
769}
770static inline bool pm_device_wakeup_is_capable(const struct device *dev)
771{
772 ARG_UNUSED(dev);
773 return false;
774}
775static inline bool pm_device_on_power_domain(const struct device *dev)
776{
777 ARG_UNUSED(dev);
778 return false;
779}
780
781static 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
789static 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
797static inline bool pm_device_is_powered(const struct device *dev)
798{
799 ARG_UNUSED(dev);
800 return true;
801}
802
803static 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 */
809 if ((rc < 0) && (rc != -ENOTSUP)) {
810 return rc;
811 }
812
814 if (rc < 0) {
815 return rc;
816 }
817
818 return 0;
819}
820
821static inline int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
822{
824}
825
826#endif /* CONFIG_PM_DEVICE */
827
829
830#ifdef __cplusplus
831}
832#endif
833
834#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:527
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:173
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:184
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:144
static void pm_device_init_off(const struct device *dev)
Initialize a device state to PM_DEVICE_STATE_OFF.
Definition device.h:547
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:99
@ PM_DEVICE_STATE_OFF
Device hardware is not powered.
Definition device.h:140
@ 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:116
@ PM_DEVICE_STATE_ACTIVE
Device hardware is powered, and the device is needed by the system.
Definition device.h:75
@ PM_DEVICE_ACTION_TURN_OFF
Turn off.
Definition device.h:154
@ PM_DEVICE_ACTION_SUSPEND
Suspend.
Definition device.h:146
@ PM_DEVICE_ACTION_RESUME
Resume.
Definition device.h:148
@ PM_DEVICE_ACTION_TURN_ON
Turn on.
Definition device.h:160
#define ENOSYS
Function not implemented.
Definition errno.h:82
#define ENOTSUP
Unsupported value.
Definition errno.h:114
#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:510
struct pm_device_base * pm_base
Definition device.h:542
Event Structure.
Definition kernel.h:2421
Semaphore structure.
Definition kernel.h:3399
Kernel Spin Lock.
Definition spinlock.h:45
A structure used to submit work after a delay.
Definition kernel.h:4322
Device PM info.
Definition device.h:193
uint32_t usage
Device usage count.
Definition device.h:202
pm_device_action_cb_t action_cb
Device PM action callback.
Definition device.h:199
enum pm_device_state state
Device power state.
Definition device.h:197
atomic_t flags
Device PM status flags.
Definition device.h:195
Runtime PM info for device with synchronous PM.
Definition device.h:241
struct k_spinlock lock
Lock to synchronize the synchronous get/put operations.
Definition device.h:246
struct pm_device_base base
Base info.
Definition device.h:243
Runtime PM info for device with generic PM.
Definition device.h:217
struct k_work_delayable work
Work object for asynchronous calls.
Definition device.h:229
struct k_event event
Event var to listen to the sync request events.
Definition device.h:227
struct k_sem lock
Lock to synchronize the get/put operations.
Definition device.h:224
const struct device * dev
Pointer to the device.
Definition device.h:222
struct pm_device_base base
Base info.
Definition device.h:219