1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "test_driver.h"
8 
9 #include <zephyr/device.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/ztest.h>
12 #include <zephyr/pm/pm.h>
13 
14 /* Last state has not declared a minimum residency, so it should be
15  * set the default 0 value
16  */
17 static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, 10000, 100},
18 	       {PM_STATE_STANDBY, 0, 20000, 200}, {PM_STATE_SUSPEND_TO_RAM, 0, 50000, 500}};
19 static enum pm_state states[] = {PM_STATE_SUSPEND_TO_IDLE,
20 			PM_STATE_STANDBY, PM_STATE_SUSPEND_TO_RAM};
21 static enum pm_state wrong_states[] = {PM_STATE_SUSPEND_TO_DISK,
22 		PM_STATE_SUSPEND_TO_RAM, PM_STATE_SUSPEND_TO_RAM};
23 
24 static uint8_t suspend_to_ram_count;
25 
pm_state_set(enum pm_state state,uint8_t substate_id)26 void pm_state_set(enum pm_state state, uint8_t substate_id)
27 {
28 	ARG_UNUSED(substate_id);
29 
30 	if (state == PM_STATE_SUSPEND_TO_RAM) {
31 		suspend_to_ram_count++;
32 	}
33 
34 	k_cpu_idle();
35 }
36 
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)37 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
38 {
39 	ARG_UNUSED(state);
40 	ARG_UNUSED(substate_id);
41 
42 	irq_unlock(0);
43 }
44 
ZTEST(power_states_1cpu,test_power_states)45 ZTEST(power_states_1cpu, test_power_states)
46 {
47 	uint8_t ret;
48 	const struct pm_state_info *cpu_states;
49 	enum pm_state dts_states[] =
50 		PM_STATE_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0));
51 	struct pm_state_info dts_infos[] =
52 		PM_STATE_INFO_LIST_FROM_DT_CPU(DT_NODELABEL(cpu0));
53 	uint32_t dts_states_len =
54 		DT_NUM_CPU_POWER_STATES(DT_NODELABEL(cpu0));
55 
56 	zassert_true(ARRAY_SIZE(states) == dts_states_len,
57 		     "Invalid number of pm states");
58 	zassert_true(memcmp(infos, dts_infos, ARRAY_SIZE(dts_infos)) == 0,
59 		     "Invalid pm_state_info array");
60 	zassert_true(memcmp(states, dts_states, ARRAY_SIZE(dts_states)) == 0,
61 		     "Invalid pm-states array");
62 
63 	zassert_false(memcmp(wrong_states, dts_states, ARRAY_SIZE(dts_states)) == 0,
64 		     "Invalid pm-states array");
65 
66 	ret = pm_state_cpu_get_all(CONFIG_MP_MAX_NUM_CPUS + 1, &cpu_states);
67 	zassert_true(ret == 0, "Invalid pm_state_cpu_get_all return");
68 
69 	ret = pm_state_cpu_get_all(0U, &cpu_states);
70 	zassert_true(ret == dts_states_len,
71 		     "Invalid number of pm states");
72 	zassert_true(memcmp(cpu_states, dts_infos, ARRAY_SIZE(dts_infos)) == 0,
73 		     "Invalid pm_state_info array");
74 }
75 
ZTEST(power_states_1cpu,test_device_power_state_constraints)76 ZTEST(power_states_1cpu, test_device_power_state_constraints)
77 {
78 	static const struct device *const dev =
79 		DEVICE_DT_GET(DT_NODELABEL(test_dev));
80 	suspend_to_ram_count = 0;
81 
82 	test_driver_async_operation(dev);
83 
84 	/** Lets sleep long enough to suspend the CPU with `suspend to ram`
85 	 *  power state. If everything works well the cpu should not use this
86 	 *  state due the constraint set by `test_dev`.
87 	 */
88 	k_sleep(K_USEC(60000));
89 
90 	zassert_true(suspend_to_ram_count == 0, "Invalid suspend to ram count");
91 
92 	/** Now lets check ensure that if there is no ongoing work
93 	 *  the cpu will suspend to ram.
94 	 */
95 	k_sleep(K_MSEC(600));
96 
97 	zassert(suspend_to_ram_count != 0, "Not suspended to ram");
98 }
99 
100 ZTEST_SUITE(power_states_1cpu, NULL, NULL, ztest_simple_1cpu_before,
101 			ztest_simple_1cpu_after, NULL);
102