pm: device: Add wakeup source API
Introduce a new API to allow devices capable of wake up the system register themselves was wake up sources. This permits applications to select the most appropriate way to wake up the system when it is suspended. Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
parent
a245ed2a87
commit
8eceeee798
7 changed files with 115 additions and 3 deletions
|
@ -226,9 +226,11 @@ def load_base_binding():
|
|||
# nodes from node-specific properties.
|
||||
|
||||
base_yaml = ZEPHYR_BASE / 'dts' / 'bindings' / 'base' / 'base.yaml'
|
||||
base_includes = {"pm.yaml": os.fspath(ZEPHYR_BASE / 'dts' / 'bindings' / 'base'/ 'pm.yaml')}
|
||||
|
||||
if not base_yaml.is_file():
|
||||
sys.exit(f'Expected to find base.yaml at {base_yaml}')
|
||||
return edtlib.Binding(os.fspath(base_yaml), {}, require_compatible=False,
|
||||
return edtlib.Binding(os.fspath(base_yaml), base_includes, require_compatible=False,
|
||||
require_description=False)
|
||||
|
||||
def dump_content(bindings, base_binding, vnd_lookup, out_dir):
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Common fields for all devices
|
||||
|
||||
include: [pm.yaml]
|
||||
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
|
|
18
dts/bindings/base/pm.yaml
Normal file
18
dts/bindings/base/pm.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2021 Intel Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Properties for Power Management (PM)
|
||||
|
||||
properties:
|
||||
wakeup-source:
|
||||
required: false
|
||||
type: boolean
|
||||
description: |
|
||||
Property to identify that a device can be used as wake up source.
|
||||
|
||||
When this property is provided a specific flag is set into the
|
||||
device that tells the system that the device is capable of
|
||||
wake up the system.
|
||||
|
||||
Wake up capable devices are disabled (interruptions will not wake up
|
||||
the system) by default but they can be enabled at runtime if necessary.
|
|
@ -663,6 +663,7 @@ static inline bool device_is_ready(const struct device *dev)
|
|||
*/
|
||||
#define Z_DEVICE_DEFINE_PRE(node_id, dev_name, ...) \
|
||||
Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) \
|
||||
Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
|
||||
Z_DEVICE_DEFINE_PM_SLOT(dev_name)
|
||||
|
||||
|
||||
|
@ -713,7 +714,6 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
|
|||
*/
|
||||
#define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_control_fn, \
|
||||
data_ptr, cfg_ptr, level, prio, api_ptr, ...) \
|
||||
static struct device_state Z_DEVICE_STATE_NAME(dev_name); \
|
||||
Z_DEVICE_DEFINE_PRE(node_id, dev_name, __VA_ARGS__) \
|
||||
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
|
||||
const Z_DECL_ALIGN(struct device) \
|
||||
|
@ -732,10 +732,24 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
|
|||
(&DEVICE_NAME_GET(dev_name)), level, prio)
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
#define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) \
|
||||
#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
|
||||
static struct device_state Z_DEVICE_STATE_NAME(dev_name) = { \
|
||||
.pm = { \
|
||||
.flags = ATOMIC_INIT(COND_CODE_1( \
|
||||
DT_NODE_EXISTS(node_id), \
|
||||
(DT_PROP( \
|
||||
node_id, wakeup_source)), \
|
||||
(0)) << \
|
||||
PM_DEVICE_FLAGS_WS_CAPABLE), \
|
||||
}, \
|
||||
};
|
||||
|
||||
#define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) \
|
||||
.pm_control = (pm_control_fn), \
|
||||
.pm = &Z_DEVICE_STATE_NAME(dev_name).pm,
|
||||
#else
|
||||
#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
|
||||
static struct device_state Z_DEVICE_STATE_NAME(dev_name);
|
||||
#define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -66,6 +66,13 @@ enum pm_device_state {
|
|||
enum pm_device_flag {
|
||||
/** Indicate if the device is busy or not. */
|
||||
PM_DEVICE_FLAG_BUSY,
|
||||
/**
|
||||
* Indicates whether or not the device is capable of waking the system
|
||||
* up.
|
||||
*/
|
||||
PM_DEVICE_FLAGS_WS_CAPABLE,
|
||||
/** Indicates if the device is being used as wakeup source. */
|
||||
PM_DEVICE_FLAGS_WS_ENABLED,
|
||||
/** Number of flags (internal use only). */
|
||||
PM_DEVICE_FLAG_COUNT
|
||||
};
|
||||
|
@ -231,6 +238,42 @@ __deprecated static inline int device_busy_check(const struct device *dev)
|
|||
/** Alias for legacy use of device_pm_control_nop */
|
||||
#define device_pm_control_nop __DEPRECATED_MACRO NULL
|
||||
|
||||
/**
|
||||
* @brief Enable a power management wakeup source
|
||||
*
|
||||
* Enable a wakeup source. This will keep the current device active when the
|
||||
* system is suspended, allowing it to be used to wake up the system.
|
||||
*
|
||||
* @param dev device object to enable.
|
||||
* @param enable @c true to enable or @c false to disable
|
||||
*
|
||||
* @retval true if the wakeup source was successfully enabled.
|
||||
* @retval false if the wakeup source was not successfully enabled.
|
||||
*/
|
||||
bool pm_device_wakeup_enable(struct device *dev, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Check if a power management wakeup source is enabled
|
||||
*
|
||||
* Checks if a wake up source is enabled.
|
||||
*
|
||||
* @param dev device object to check.
|
||||
*
|
||||
* @retval true if the wakeup source is enabled.
|
||||
* @retval false if the wakeup source is not enabled.
|
||||
*/
|
||||
bool pm_device_wakeup_is_enabled(const struct device *dev);
|
||||
|
||||
/**
|
||||
* @brief Check if a device is wake up capable
|
||||
*
|
||||
* @param dev device object to check.
|
||||
*
|
||||
* @retval true if the device is wake up capable.
|
||||
* @retval false if the device is not wake up capable.
|
||||
*/
|
||||
bool pm_device_wakeup_is_capable(const struct device *dev);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -33,6 +33,7 @@ static inline void device_pm_state_init(const struct device *dev)
|
|||
.lock = Z_MUTEX_INITIALIZER(dev->pm->lock),
|
||||
.condvar = Z_CONDVAR_INITIALIZER(dev->pm->condvar),
|
||||
.state = PM_DEVICE_STATE_ACTIVE,
|
||||
.flags = ATOMIC_INIT(dev->pm->flags),
|
||||
};
|
||||
#endif /* CONFIG_PM_DEVICE */
|
||||
}
|
||||
|
|
|
@ -206,3 +206,35 @@ void pm_device_busy_clear(const struct device *dev)
|
|||
{
|
||||
atomic_clear_bit(&dev->pm->flags, PM_DEVICE_FLAG_BUSY);
|
||||
}
|
||||
|
||||
bool pm_device_wakeup_enable(struct device *dev, bool enable)
|
||||
{
|
||||
atomic_val_t flags, new_flags;
|
||||
|
||||
flags = atomic_get(&dev->pm->flags);
|
||||
|
||||
if ((flags & BIT(PM_DEVICE_FLAGS_WS_CAPABLE)) == 0U) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
new_flags = flags |
|
||||
BIT(PM_DEVICE_FLAGS_WS_ENABLED);
|
||||
} else {
|
||||
new_flags = flags & ~BIT(PM_DEVICE_FLAGS_WS_ENABLED);
|
||||
}
|
||||
|
||||
return atomic_cas(&dev->pm->flags, flags, new_flags);
|
||||
}
|
||||
|
||||
bool pm_device_wakeup_is_enabled(const struct device *dev)
|
||||
{
|
||||
return atomic_test_bit(&dev->pm->flags,
|
||||
PM_DEVICE_FLAGS_WS_ENABLED);
|
||||
}
|
||||
|
||||
bool pm_device_wakeup_is_capable(const struct device *dev)
|
||||
{
|
||||
return atomic_test_bit(&dev->pm->flags,
|
||||
PM_DEVICE_FLAGS_WS_CAPABLE);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue