/* * Copyright (c) 2018 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include "pm_policy.h" #define LOG_LEVEL CONFIG_PM_LOG_LEVEL /* From power module Kconfig */ #include LOG_MODULE_DECLARE(power); #define SECS_TO_TICKS CONFIG_SYS_CLOCK_TICKS_PER_SEC #if !(defined(CONFIG_SYS_POWER_STATE_CPU_LPS_SUPPORTED) || \ defined(CONFIG_SYS_POWER_STATE_CPU_LPS_1_SUPPORTED) || \ defined(CONFIG_SYS_POWER_STATE_CPU_LPS_2_SUPPORTED) || \ defined(CONFIG_SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED) || \ defined(CONFIG_SYS_POWER_STATE_DEEP_SLEEP_1_SUPPORTED) || \ defined(CONFIG_SYS_POWER_STATE_DEEP_SLEEP_2_SUPPORTED)) #error "Enable Low Power States at SoC Level" #endif struct sys_soc_pm_policy { enum power_states pm_state; int sys_state; int min_residency; }; /* PM Policy based on SoC/Platform residency requirements */ static struct sys_soc_pm_policy pm_policy[] = { #ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_SUPPORTED {SYS_POWER_STATE_CPU_LPS, SYS_PM_LOW_POWER_STATE, CONFIG_PM_LPS_MIN_RES * SECS_TO_TICKS}, #endif #ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_1_SUPPORTED {SYS_POWER_STATE_CPU_LPS_1, SYS_PM_LOW_POWER_STATE, CONFIG_PM_LPS_1_MIN_RES * SECS_TO_TICKS}, #endif #ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_2_SUPPORTED {SYS_POWER_STATE_CPU_LPS_2, SYS_PM_LOW_POWER_STATE, CONFIG_PM_LPS_2_MIN_RES * SECS_TO_TICKS}, #endif #ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED {SYS_POWER_STATE_DEEP_SLEEP, SYS_PM_DEEP_SLEEP, CONFIG_PM_DEEP_SLEEP_MIN_RES * SECS_TO_TICKS}, #endif #ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_1_SUPPORTED {SYS_POWER_STATE_DEEP_SLEEP_1, SYS_PM_DEEP_SLEEP, CONFIG_PM_DEEP_SLEEP_1_MIN_RES * SECS_TO_TICKS}, #endif #ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_2_SUPPORTED {SYS_POWER_STATE_DEEP_SLEEP_2, SYS_PM_DEEP_SLEEP, CONFIG_PM_DEEP_SLEEP_2_MIN_RES * SECS_TO_TICKS}, #endif }; int sys_pm_policy_next_state(s32_t ticks, enum power_states *pm_state) { int i; if ((ticks != K_FOREVER) && (ticks < pm_policy[0].min_residency)) { LOG_ERR("Not enough time for PM operations: %d\n", ticks); return SYS_PM_NOT_HANDLED; } for (i = 0; i < (ARRAY_SIZE(pm_policy) - 1); i++) { if ((ticks >= pm_policy[i].min_residency) && (ticks < pm_policy[i + 1].min_residency)) { break; } } if (!_sys_soc_is_valid_power_state(pm_policy[i].pm_state)) { LOG_ERR("pm_state(%d) not supported by SoC\n", pm_policy[i].pm_state); return SYS_PM_NOT_HANDLED; } *pm_state = pm_policy[i].pm_state; LOG_DBG("pm_state: %d, min_residency: %d, idx: %d\n", *pm_state, pm_policy[i].min_residency, i); return pm_policy[i].sys_state; }