blob: 60a35b269c00be822f773950302680e88d93a88e [file] [log] [blame]
/*
* Copyright (c) 2021 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/pm/pm.h>
BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS == 2, "Invalid number of cpus");
#define NUM_OF_ITERATIONS (5)
#define THRESHOLD (10)
/* Arbitrary times to trigger different power states. It is by the
* application to sleep and the policy to define which power state
* to use. They have no relationship with any platform.
*/
#define ACTIVE_MSEC (40)
#define ACTIVE_TIMEOUT K_MSEC(40)
#define IDLE_MSEC (60 + THRESHOLD)
#define IDLE_TIMEOUT K_MSEC(60)
#define SUSPEND_TO_IDLE_MSEC (100 + THRESHOLD)
#define SUSPEND_TO_IDLE_TIMEOUT K_MSEC(100)
#define STANDBY_TIMEOUT K_MSEC(200)
static enum pm_state state_testing[2];
void pm_state_set(enum pm_state state, uint8_t substate_id)
{
ARG_UNUSED(substate_id);
switch (state_testing[_current_cpu->id]) {
case PM_STATE_ACTIVE:
zassert_equal(PM_STATE_ACTIVE, state);
break;
case PM_STATE_RUNTIME_IDLE:
zassert_equal(PM_STATE_RUNTIME_IDLE, state);
break;
case PM_STATE_SUSPEND_TO_IDLE:
zassert_equal(PM_STATE_SUSPEND_TO_IDLE, state);
break;
case PM_STATE_STANDBY:
zassert_equal(_current_cpu->id, 1U);
zassert_equal(PM_STATE_STANDBY, state);
break;
default:
zassert_unreachable(NULL);
break;
}
}
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
{
ARG_UNUSED(state);
ARG_UNUSED(substate_id);
/* pm_system_suspend is entered with irq locked
* unlock irq before leave pm_system_suspend
*/
irq_unlock(0);
}
const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int ticks)
{
static struct pm_state_info info = {};
int32_t msecs = k_ticks_to_ms_floor64(ticks);
if (msecs < ACTIVE_MSEC) {
info.state = PM_STATE_ACTIVE;
} else if (msecs <= IDLE_MSEC) {
info.state = PM_STATE_RUNTIME_IDLE;
} else if (msecs <= SUSPEND_TO_IDLE_MSEC) {
info.state = PM_STATE_SUSPEND_TO_IDLE;
} else {
if (cpu == 0U) {
info.state = PM_STATE_SUSPEND_TO_IDLE;
} else {
info.state = PM_STATE_STANDBY;
}
}
state_testing[cpu] = info.state;
return &info;
}
/*
* @brief test power idle in multicore
*
* @details
* - Go over a list of timeouts that should trigger different sleep states
* - The test assumes there are two cpus. The cpu 1 has one deeper sleep state than cpu 0.
* - Checks that the states given by the policy are properly used in the idle thread.
* - Iterate a number of times to stress it.
*
* @see pm_policy_next_state()
* @see pm_state_set()
*
* @ingroup power_tests
*/
ZTEST(pm_multicore, test_power_idle)
{
for (uint8_t i = 0U; i < NUM_OF_ITERATIONS; i++) {
k_sleep(ACTIVE_TIMEOUT);
k_sleep(IDLE_TIMEOUT);
k_sleep(SUSPEND_TO_IDLE_TIMEOUT);
k_sleep(STANDBY_TIMEOUT);
}
}
ZTEST_SUITE(pm_multicore, NULL, NULL, NULL, NULL, NULL);