1 /*
2 * Copyright (c) 2021 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/pm/pm.h>
10
11 BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS == 2, "Invalid number of cpus");
12
13 #define NUM_OF_ITERATIONS (5)
14
15 #define THRESHOLD (10)
16
17 /* Arbitrary times to trigger different power states. It is by the
18 * application to sleep and the policy to define which power state
19 * to use. They have no relationship with any platform.
20 */
21 #define ACTIVE_MSEC (40)
22 #define ACTIVE_TIMEOUT K_MSEC(40)
23 #define IDLE_MSEC (60 + THRESHOLD)
24 #define IDLE_TIMEOUT K_MSEC(60)
25 #define SUSPEND_TO_IDLE_MSEC (100 + THRESHOLD)
26 #define SUSPEND_TO_IDLE_TIMEOUT K_MSEC(100)
27 #define STANDBY_TIMEOUT K_MSEC(200)
28
29
30 static enum pm_state state_testing[2];
31
pm_state_set(enum pm_state state,uint8_t substate_id)32 void pm_state_set(enum pm_state state, uint8_t substate_id)
33 {
34 ARG_UNUSED(substate_id);
35
36 switch (state_testing[_current_cpu->id]) {
37 case PM_STATE_RUNTIME_IDLE:
38 zassert_equal(PM_STATE_RUNTIME_IDLE, state);
39 break;
40 case PM_STATE_SUSPEND_TO_IDLE:
41 zassert_equal(PM_STATE_SUSPEND_TO_IDLE, state);
42 break;
43 case PM_STATE_STANDBY:
44 zassert_equal(_current_cpu->id, 1U);
45 zassert_equal(PM_STATE_STANDBY, state);
46 break;
47 default:
48 zassert_unreachable(NULL);
49 break;
50 }
51 }
52
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)53 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
54 {
55 ARG_UNUSED(state);
56 ARG_UNUSED(substate_id);
57
58 /* pm_system_suspend is entered with irq locked
59 * unlock irq before leave pm_system_suspend
60 */
61 irq_unlock(0);
62 }
63
pm_policy_next_state(uint8_t cpu,int ticks)64 const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int ticks)
65 {
66 static struct pm_state_info info = {};
67 int32_t msecs = k_ticks_to_ms_floor64(ticks);
68
69 if (msecs < ACTIVE_MSEC) {
70 info.state = PM_STATE_ACTIVE;
71 } else if (msecs <= IDLE_MSEC) {
72 info.state = PM_STATE_RUNTIME_IDLE;
73 } else if (msecs <= SUSPEND_TO_IDLE_MSEC) {
74 info.state = PM_STATE_SUSPEND_TO_IDLE;
75 } else {
76 if (cpu == 0U) {
77 info.state = PM_STATE_SUSPEND_TO_IDLE;
78 } else {
79 info.state = PM_STATE_STANDBY;
80 }
81 }
82
83 state_testing[cpu] = info.state;
84
85 return &info;
86 }
87
88 /*
89 * @brief test power idle in multicore
90 *
91 * @details
92 * - Go over a list of timeouts that should trigger different sleep states
93 * - The test assumes there are two cpus. The cpu 1 has one deeper sleep state than cpu 0.
94 * - Checks that the states given by the policy are properly used in the idle thread.
95 * - Iterate a number of times to stress it.
96 *
97 * @see pm_policy_next_state()
98 * @see pm_state_set()
99 *
100 * @ingroup power_tests
101 */
ZTEST(pm_multicore,test_power_idle)102 ZTEST(pm_multicore, test_power_idle)
103 {
104
105 for (uint8_t i = 0U; i < NUM_OF_ITERATIONS; i++) {
106 k_sleep(ACTIVE_TIMEOUT);
107
108 k_sleep(IDLE_TIMEOUT);
109
110 k_sleep(SUSPEND_TO_IDLE_TIMEOUT);
111
112 k_sleep(STANDBY_TIMEOUT);
113 }
114 }
115
116 ZTEST_SUITE(pm_multicore, NULL, NULL, NULL, NULL, NULL);
117