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 #include <zephyr/pm/device.h>
11 
12 static const struct device *const dev =
13 	DEVICE_DT_GET(DT_NODELABEL(gpio0));
14 static uint8_t sleep_count;
15 
16 
pm_state_set(enum pm_state state,uint8_t substate_id)17 void pm_state_set(enum pm_state state, uint8_t substate_id)
18 {
19 	ARG_UNUSED(substate_id);
20 
21 	enum pm_device_state dev_state;
22 
23 	switch (sleep_count) {
24 	case 1:
25 		/* Just  a sanity check that the system is the right state.
26 		 * Devices are suspended before SoC on PM_STATE_SUSPEND_TO_RAM, that is why
27 		 * we can check the device state here.
28 		 */
29 		zassert_equal(state, PM_STATE_SUSPEND_TO_RAM, "Wrong system state");
30 
31 		(void)pm_device_state_get(dev, &dev_state);
32 		zassert_equal(dev_state, PM_DEVICE_STATE_SUSPENDED, "Wrong device state");
33 
34 		/* Enable wakeup source. Next time the system is called
35 		 * to sleep, this device will still be active.
36 		 */
37 		(void)pm_device_wakeup_enable(dev, true);
38 		break;
39 	case 2:
40 		zassert_equal(state, PM_STATE_SUSPEND_TO_RAM, "Wrong system state");
41 
42 		/* Second time this function is called, the system is asked to standby
43 		 * and devices were suspended.
44 		 */
45 		(void)pm_device_state_get(dev, &dev_state);
46 		zassert_equal(dev_state, PM_DEVICE_STATE_ACTIVE, "Wrong device state");
47 		break;
48 	default:
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 	irq_unlock(0);
59 }
60 
pm_policy_next_state(uint8_t cpu,int32_t ticks)61 const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks)
62 {
63 	const struct pm_state_info *cpu_states;
64 
65 	zassert_true(pm_state_cpu_get_all(cpu, &cpu_states) == 1,
66 		     "There is no power state defined");
67 
68 	while (sleep_count < 3) {
69 		sleep_count++;
70 		return &cpu_states[0];
71 	}
72 
73 	return NULL;
74 }
75 
ZTEST(wakeup_device_1cpu,test_wakeup_device_api)76 ZTEST(wakeup_device_1cpu, test_wakeup_device_api)
77 {
78 	bool ret = false;
79 
80 	zassert_true(device_is_ready(dev), "Device not ready");
81 
82 	ret = pm_device_wakeup_is_capable(dev);
83 	zassert_true(ret, "Device not marked as capable");
84 
85 	ret = pm_device_wakeup_enable(dev, true);
86 	zassert_true(ret, "Could not enable wakeup source");
87 
88 	ret = pm_device_wakeup_is_enabled(dev);
89 	zassert_true(ret, "Wakeup source not enabled");
90 
91 	ret = pm_device_wakeup_enable(dev, false);
92 	zassert_true(ret, "Could not disable wakeup source");
93 
94 	ret = pm_device_wakeup_is_enabled(dev);
95 	zassert_false(ret, "Wakeup source is enabled");
96 }
97 
ZTEST(wakeup_device_1cpu,test_wakeup_device_system_pm)98 ZTEST(wakeup_device_1cpu, test_wakeup_device_system_pm)
99 {
100 	/*
101 	 * Trigger system PM. The policy manager will return
102 	 * PM_STATE_SUSPEND_TO_RAM and then the PM subsystem will
103 	 * suspend all devices. As gpio is wakeup capability is not
104 	 * enabled, the device will be suspended.  This will be
105 	 * confirmed in pm_state_set().
106 	 *
107 	 * As the native posix implementation does not properly sleeps,
108 	 * the idle thread will call several times the PM subsystem. This
109 	 * test workaround this problem keeping track of the calls using
110 	 * the sleep_count variable.
111 	 */
112 	k_sleep(K_SECONDS(1));
113 }
114 
115 ZTEST_SUITE(wakeup_device_1cpu, NULL, NULL, ztest_simple_1cpu_before,
116 			ztest_simple_1cpu_after, NULL);
117