text: /*
   * Copyright (c) 2018 Intel Corporation.
   *
   * SPDX-License-Identifier: Apache-2.0
   */
  
  #include <zephyr.h>
  #include <kernel.h>
  #include "pm_policy.h"
  
  #define LOG_LEVEL CONFIG_SYS_PM_LOG_LEVEL /* From power module Kconfig */
  #include <logging/log.h>
  LOG_MODULE_DECLARE(power);
  
  #define SECS_TO_TICKS		CONFIG_SYS_CLOCK_TICKS_PER_SEC
  
  /* PM Policy based on SoC/Platform residency requirements */
  static const unsigned int pm_min_residency[] = {
  #ifdef CONFIG_SYS_POWER_SLEEP_STATES
  #ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_1
  	CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_1 * SECS_TO_TICKS / MSEC_PER_SEC,
  #endif
  
  #ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_2
  	CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_2 * SECS_TO_TICKS / MSEC_PER_SEC,
  #endif
  
  #ifdef CONFIG_HAS_SYS_POWER_STATE_SLEEP_3
  	CONFIG_SYS_PM_MIN_RESIDENCY_SLEEP_3 * SECS_TO_TICKS / MSEC_PER_SEC,
  #endif
  #endif /* CONFIG_SYS_POWER_SLEEP_STATES */
  };
  
  enum power_states sys_pm_policy_next_state(s32_t ticks)
  {
  	int i;
  
  	if ((ticks != K_FOREVER) && (ticks < pm_min_residency[0])) {
  		LOG_DBG("Not enough time for PM operations: %d", ticks);
  		return SYS_POWER_STATE_ACTIVE;
  	}
  
  	for (i = ARRAY_SIZE(pm_min_residency) - 1; i >= 0; i--) {
  #ifdef CONFIG_SYS_PM_STATE_LOCK
  		if (!sys_pm_ctrl_is_state_enabled((enum power_states)(i))) {
  			continue;
  		}
  #endif
  		if ((ticks == K_FOREVER) ||
  		    (ticks >= pm_min_residency[i])) {
  			LOG_DBG("Selected power state %d "
  					"(ticks: %d, min_residency: %u)",
  					i, ticks, pm_min_residency[i]);
  			return (enum power_states)(i);
  		}
  	}
  
  	LOG_DBG("No suitable power state found!");
  	return SYS_POWER_STATE_ACTIVE;
  }
  
  __weak bool sys_pm_policy_low_power_devices(enum power_states pm_state)
  {
  	return sys_pm_is_sleep_state(pm_state);
  }
  