1 /*
2 * Copyright (c) 2022, Commonwealth Scientific and Industrial Research
3 * Organisation (CSIRO) ABN 41 687 119 230.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/ztest.h>
9 #include <zephyr/pm/device.h>
10 #include <zephyr/pm/device_runtime.h>
11
12 static int dev_pm_control_resume_ret;
13 static int dev_pm_control_turn_on_ret;
14
dev_init(const struct device * dev)15 static int dev_init(const struct device *dev)
16 {
17 if (!pm_device_is_powered(dev)) {
18 pm_device_init_off(dev);
19 }
20 return 0;
21 }
22
dev_pm_control(const struct device * dev,enum pm_device_action action)23 int dev_pm_control(const struct device *dev, enum pm_device_action action)
24 {
25 ARG_UNUSED(dev);
26
27 int ret = 0;
28
29 switch (action) {
30 case PM_DEVICE_ACTION_SUSPEND:
31 break;
32 case PM_DEVICE_ACTION_RESUME:
33 ret = dev_pm_control_resume_ret;
34 break;
35 case PM_DEVICE_ACTION_TURN_ON:
36 ret = dev_pm_control_turn_on_ret;
37 break;
38 case PM_DEVICE_ACTION_TURN_OFF:
39 break;
40 default:
41 ret = -ENOTSUP;
42 break;
43 }
44
45 return ret;
46 }
47
48 PM_DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), dev_pm_control);
49 DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), dev_init, PM_DEVICE_DT_GET(DT_NODELABEL(test_dev)),
50 NULL, NULL, POST_KERNEL, 80, NULL);
51
ZTEST(device_power_domain,test_device_power_domain)52 ZTEST(device_power_domain, test_device_power_domain)
53 {
54 const struct device *const reg_0 = DEVICE_DT_GET(DT_NODELABEL(test_reg_0));
55 const struct device *const reg_1 = DEVICE_DT_GET(DT_NODELABEL(test_reg_1));
56 const struct device *const reg_chained = DEVICE_DT_GET(DT_NODELABEL(test_reg_chained));
57 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(test_dev));
58 enum pm_device_state state;
59
60 /* Initial power state */
61 zassert_true(pm_device_is_powered(reg_0), "");
62 zassert_true(pm_device_is_powered(reg_1), "");
63 zassert_true(pm_device_is_powered(reg_chained), "");
64 zassert_true(pm_device_is_powered(dev), "");
65
66 TC_PRINT("Enabling runtime power management on regulators\n");
67
68 pm_device_runtime_enable(dev);
69 pm_device_runtime_enable(reg_chained);
70 pm_device_runtime_enable(reg_1);
71 pm_device_runtime_enable(reg_0);
72
73 /* Power domains should now be suspended */
74 zassert_true(pm_device_is_powered(reg_0), "");
75 zassert_true(pm_device_is_powered(reg_1), "");
76 zassert_false(pm_device_is_powered(reg_chained), "");
77 zassert_false(pm_device_is_powered(dev), "");
78 pm_device_state_get(dev, &state);
79 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
80
81 TC_PRINT("Cycling: %s\n", reg_0->name);
82
83 /* reg_chained is powered off reg_0, so it's power state should change */
84 pm_device_runtime_get(reg_0);
85 zassert_true(pm_device_is_powered(reg_chained), "");
86 zassert_false(pm_device_is_powered(dev), "");
87 pm_device_runtime_put(reg_0);
88 zassert_false(pm_device_is_powered(reg_chained), "");
89
90 TC_PRINT("Cycling: %s\n", reg_1->name);
91
92 pm_device_runtime_get(reg_1);
93 zassert_false(pm_device_is_powered(reg_chained), "");
94 zassert_true(pm_device_is_powered(dev), "");
95 /* dev is on reg_1, should have automatically moved to suspended */
96 pm_device_state_get(dev, &state);
97 zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
98 pm_device_runtime_put(reg_1);
99 pm_device_state_get(dev, &state);
100 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
101
102 TC_PRINT("Cycling: %s\n", reg_chained->name);
103
104 /* reg_chained should be powered after being requested */
105 pm_device_runtime_get(reg_chained);
106 zassert_true(pm_device_is_powered(reg_chained), "");
107 zassert_false(pm_device_is_powered(dev), "");
108 /* dev is not on reg_chained but does reference it, should still be in OFF */
109 pm_device_state_get(dev, &state);
110 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
111 pm_device_runtime_put(reg_chained);
112
113 TC_PRINT("Requesting dev: %s\n", dev->name);
114
115 /* Directly request the supported device */
116 pm_device_runtime_get(dev);
117 zassert_true(pm_device_is_powered(dev), "");
118 pm_device_state_get(dev, &state);
119 zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
120 pm_device_state_get(reg_1, &state);
121 zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
122 pm_device_state_get(reg_chained, &state);
123 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
124 /* Directly release the supported device */
125 pm_device_runtime_put(dev);
126 zassert_false(pm_device_is_powered(dev), "");
127 pm_device_state_get(dev, &state);
128 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
129 pm_device_state_get(reg_1, &state);
130 zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
131 pm_device_state_get(reg_chained, &state);
132 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
133
134 /* Directly request the supported device multiple times */
135 pm_device_runtime_get(dev);
136 pm_device_runtime_get(dev);
137 pm_device_runtime_get(dev);
138 /* Directly release the supported device the first time, check all still powered */
139 pm_device_runtime_put(dev);
140 zassert_true(pm_device_is_powered(dev), "");
141 pm_device_state_get(dev, &state);
142 zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
143 pm_device_state_get(reg_1, &state);
144 zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
145 /* Release the supported device the twice using async */
146 zassert_ok(pm_device_runtime_put_async(dev, K_SECONDS(1)));
147 zassert_ok(pm_device_runtime_put_async(dev, K_SECONDS(1)));
148 k_sleep(K_SECONDS(2));
149 /* Check all off */
150 zassert_false(pm_device_is_powered(dev), "");
151 pm_device_state_get(dev, &state);
152 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
153 pm_device_state_get(reg_1, &state);
154 zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
155
156 /* Directly request the supported device but turn on fails */
157 dev_pm_control_turn_on_ret = -EBUSY;
158 pm_device_runtime_get(dev);
159 dev_pm_control_turn_on_ret = 0;
160 zassert_false(pm_device_is_powered(dev), "");
161 pm_device_state_get(dev, &state);
162 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
163 pm_device_state_get(reg_1, &state);
164 zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
165 pm_device_state_get(reg_chained, &state);
166 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
167
168 /* Directly request the supported device but resume fails */
169 dev_pm_control_resume_ret = -EBUSY;
170 pm_device_runtime_get(dev);
171 dev_pm_control_resume_ret = 0;
172 zassert_false(pm_device_is_powered(dev), "");
173 pm_device_state_get(dev, &state);
174 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
175 pm_device_state_get(reg_1, &state);
176 zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
177 pm_device_state_get(reg_chained, &state);
178 zassert_equal(PM_DEVICE_STATE_OFF, state, "");
179
180 TC_PRINT("DONE\n");
181 }
182
183 ZTEST_SUITE(device_power_domain, NULL, NULL, NULL, NULL, NULL);
184