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