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