| /* |
| * Copyright (c) 2024 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/pm/device.h> |
| #include <zephyr/pm/device_runtime.h> |
| |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL); |
| |
| #define DT_PM_DEVICE_ENABLED(node_id) \ |
| COND_CODE_1(DT_PROP(node_id, zephyr_pm_device_disabled), \ |
| (), (1 +)) |
| |
| #define DT_PM_DEVICE_NEEDED \ |
| (DT_FOREACH_STATUS_OKAY(zephyr_power_state, DT_PM_DEVICE_ENABLED) 0) |
| |
| #if DT_PM_DEVICE_NEEDED |
| TYPE_SECTION_START_EXTERN(const struct device *, pm_device_slots); |
| |
| /* Number of devices successfully suspended. */ |
| static size_t num_susp; |
| |
| bool pm_suspend_devices(void) |
| { |
| const struct device *devs; |
| size_t devc; |
| |
| devc = z_device_get_all_static(&devs); |
| |
| num_susp = 0; |
| |
| for (const struct device *dev = devs + devc - 1; dev >= devs; dev--) { |
| int ret; |
| |
| /* |
| * Ignore uninitialized devices, busy devices, wake up sources, and |
| * devices with runtime PM enabled. |
| */ |
| if (!device_is_ready(dev) || pm_device_is_busy(dev) || |
| pm_device_wakeup_is_enabled(dev) || |
| pm_device_runtime_is_enabled(dev)) { |
| continue; |
| } |
| |
| ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND); |
| /* ignore devices not supporting or already at the given state */ |
| if ((ret == -ENOSYS) || (ret == -ENOTSUP) || (ret == -EALREADY)) { |
| continue; |
| } else if (ret < 0) { |
| LOG_ERR("Device %s did not enter %s state (%d)", |
| dev->name, |
| pm_device_state_str(PM_DEVICE_STATE_SUSPENDED), |
| ret); |
| return false; |
| } |
| |
| TYPE_SECTION_START(pm_device_slots)[num_susp] = dev; |
| num_susp++; |
| } |
| |
| return true; |
| } |
| |
| void pm_resume_devices(void) |
| { |
| for (int i = (num_susp - 1); i >= 0; i--) { |
| pm_device_action_run(TYPE_SECTION_START(pm_device_slots)[i], |
| PM_DEVICE_ACTION_RESUME); |
| } |
| |
| num_susp = 0; |
| } |
| |
| #else /* !DT_PM_DEVICE_NEEDED */ |
| |
| void pm_resume_devices(void) |
| { |
| } |
| |
| bool pm_suspend_devices(void) |
| { |
| return true; |
| } |
| |
| #endif |