Skip to content

Commit 8eceeee

Browse files
Flavio Ceolincfriedt
authored andcommitted
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 <[email protected]>
1 parent a245ed2 commit 8eceeee

File tree

7 files changed

+115
-3
lines changed

7 files changed

+115
-3
lines changed

doc/_scripts/gen_devicetree_rest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,11 @@ def load_base_binding():
226226
# nodes from node-specific properties.
227227

228228
base_yaml = ZEPHYR_BASE / 'dts' / 'bindings' / 'base' / 'base.yaml'
229+
base_includes = {"pm.yaml": os.fspath(ZEPHYR_BASE / 'dts' / 'bindings' / 'base'/ 'pm.yaml')}
230+
229231
if not base_yaml.is_file():
230232
sys.exit(f'Expected to find base.yaml at {base_yaml}')
231-
return edtlib.Binding(os.fspath(base_yaml), {}, require_compatible=False,
233+
return edtlib.Binding(os.fspath(base_yaml), base_includes, require_compatible=False,
232234
require_description=False)
233235

234236
def dump_content(bindings, base_binding, vnd_lookup, out_dir):

dts/bindings/base/base.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Common fields for all devices
22

3+
include: [pm.yaml]
4+
35
properties:
46
status:
57
type: string

dts/bindings/base/pm.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2021 Intel Corporation.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Properties for Power Management (PM)
5+
6+
properties:
7+
wakeup-source:
8+
required: false
9+
type: boolean
10+
description: |
11+
Property to identify that a device can be used as wake up source.
12+
13+
When this property is provided a specific flag is set into the
14+
device that tells the system that the device is capable of
15+
wake up the system.
16+
17+
Wake up capable devices are disabled (interruptions will not wake up
18+
the system) by default but they can be enabled at runtime if necessary.

include/device.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,7 @@ static inline bool device_is_ready(const struct device *dev)
663663
*/
664664
#define Z_DEVICE_DEFINE_PRE(node_id, dev_name, ...) \
665665
Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) \
666+
Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
666667
Z_DEVICE_DEFINE_PM_SLOT(dev_name)
667668

668669

@@ -713,7 +714,6 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
713714
*/
714715
#define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_control_fn, \
715716
data_ptr, cfg_ptr, level, prio, api_ptr, ...) \
716-
static struct device_state Z_DEVICE_STATE_NAME(dev_name); \
717717
Z_DEVICE_DEFINE_PRE(node_id, dev_name, __VA_ARGS__) \
718718
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
719719
const Z_DECL_ALIGN(struct device) \
@@ -732,10 +732,24 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
732732
(&DEVICE_NAME_GET(dev_name)), level, prio)
733733

734734
#ifdef CONFIG_PM_DEVICE
735-
#define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) \
735+
#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
736+
static struct device_state Z_DEVICE_STATE_NAME(dev_name) = { \
737+
.pm = { \
738+
.flags = ATOMIC_INIT(COND_CODE_1( \
739+
DT_NODE_EXISTS(node_id), \
740+
(DT_PROP( \
741+
node_id, wakeup_source)), \
742+
(0)) << \
743+
PM_DEVICE_FLAGS_WS_CAPABLE), \
744+
}, \
745+
};
746+
747+
#define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) \
736748
.pm_control = (pm_control_fn), \
737749
.pm = &Z_DEVICE_STATE_NAME(dev_name).pm,
738750
#else
751+
#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
752+
static struct device_state Z_DEVICE_STATE_NAME(dev_name);
739753
#define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn)
740754
#endif
741755

include/pm/device.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ enum pm_device_state {
6666
enum pm_device_flag {
6767
/** Indicate if the device is busy or not. */
6868
PM_DEVICE_FLAG_BUSY,
69+
/**
70+
* Indicates whether or not the device is capable of waking the system
71+
* up.
72+
*/
73+
PM_DEVICE_FLAGS_WS_CAPABLE,
74+
/** Indicates if the device is being used as wakeup source. */
75+
PM_DEVICE_FLAGS_WS_ENABLED,
6976
/** Number of flags (internal use only). */
7077
PM_DEVICE_FLAG_COUNT
7178
};
@@ -231,6 +238,42 @@ __deprecated static inline int device_busy_check(const struct device *dev)
231238
/** Alias for legacy use of device_pm_control_nop */
232239
#define device_pm_control_nop __DEPRECATED_MACRO NULL
233240

241+
/**
242+
* @brief Enable a power management wakeup source
243+
*
244+
* Enable a wakeup source. This will keep the current device active when the
245+
* system is suspended, allowing it to be used to wake up the system.
246+
*
247+
* @param dev device object to enable.
248+
* @param enable @c true to enable or @c false to disable
249+
*
250+
* @retval true if the wakeup source was successfully enabled.
251+
* @retval false if the wakeup source was not successfully enabled.
252+
*/
253+
bool pm_device_wakeup_enable(struct device *dev, bool enable);
254+
255+
/**
256+
* @brief Check if a power management wakeup source is enabled
257+
*
258+
* Checks if a wake up source is enabled.
259+
*
260+
* @param dev device object to check.
261+
*
262+
* @retval true if the wakeup source is enabled.
263+
* @retval false if the wakeup source is not enabled.
264+
*/
265+
bool pm_device_wakeup_is_enabled(const struct device *dev);
266+
267+
/**
268+
* @brief Check if a device is wake up capable
269+
*
270+
* @param dev device object to check.
271+
*
272+
* @retval true if the device is wake up capable.
273+
* @retval false if the device is not wake up capable.
274+
*/
275+
bool pm_device_wakeup_is_capable(const struct device *dev);
276+
234277
/** @} */
235278

236279
#ifdef __cplusplus

kernel/device.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static inline void device_pm_state_init(const struct device *dev)
3333
.lock = Z_MUTEX_INITIALIZER(dev->pm->lock),
3434
.condvar = Z_CONDVAR_INITIALIZER(dev->pm->condvar),
3535
.state = PM_DEVICE_STATE_ACTIVE,
36+
.flags = ATOMIC_INIT(dev->pm->flags),
3637
};
3738
#endif /* CONFIG_PM_DEVICE */
3839
}

subsys/pm/device.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,35 @@ void pm_device_busy_clear(const struct device *dev)
206206
{
207207
atomic_clear_bit(&dev->pm->flags, PM_DEVICE_FLAG_BUSY);
208208
}
209+
210+
bool pm_device_wakeup_enable(struct device *dev, bool enable)
211+
{
212+
atomic_val_t flags, new_flags;
213+
214+
flags = atomic_get(&dev->pm->flags);
215+
216+
if ((flags & BIT(PM_DEVICE_FLAGS_WS_CAPABLE)) == 0U) {
217+
return false;
218+
}
219+
220+
if (enable) {
221+
new_flags = flags |
222+
BIT(PM_DEVICE_FLAGS_WS_ENABLED);
223+
} else {
224+
new_flags = flags & ~BIT(PM_DEVICE_FLAGS_WS_ENABLED);
225+
}
226+
227+
return atomic_cas(&dev->pm->flags, flags, new_flags);
228+
}
229+
230+
bool pm_device_wakeup_is_enabled(const struct device *dev)
231+
{
232+
return atomic_test_bit(&dev->pm->flags,
233+
PM_DEVICE_FLAGS_WS_ENABLED);
234+
}
235+
236+
bool pm_device_wakeup_is_capable(const struct device *dev)
237+
{
238+
return atomic_test_bit(&dev->pm->flags,
239+
PM_DEVICE_FLAGS_WS_CAPABLE);
240+
}

0 commit comments

Comments
 (0)