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