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 
dev_init(const struct device * dev)12 static int dev_init(const struct device *dev)
13 {
14 	if (!pm_device_is_powered(dev)) {
15 		pm_device_init_off(dev);
16 	}
17 	return 0;
18 }
19 
dev_pm_control(const struct device * dev,enum pm_device_action action)20 int dev_pm_control(const struct device *dev, enum pm_device_action action)
21 {
22 	ARG_UNUSED(dev);
23 	ARG_UNUSED(action);
24 
25 	return 0;
26 }
27 
28 PM_DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), dev_pm_control);
29 DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), dev_init, PM_DEVICE_DT_GET(DT_NODELABEL(test_dev)),
30 		 NULL, NULL, POST_KERNEL, 80, NULL);
31 
ZTEST(device_power_domain,test_device_power_domain)32 ZTEST(device_power_domain, test_device_power_domain)
33 {
34 	const struct device *const reg_0 = DEVICE_DT_GET(DT_NODELABEL(test_reg_0));
35 	const struct device *const reg_1 = DEVICE_DT_GET(DT_NODELABEL(test_reg_1));
36 	const struct device *const reg_chained = DEVICE_DT_GET(DT_NODELABEL(test_reg_chained));
37 	const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(test_dev));
38 	enum pm_device_state state;
39 
40 	/* Initial power state */
41 	zassert_true(pm_device_is_powered(reg_0), "");
42 	zassert_true(pm_device_is_powered(reg_1), "");
43 	zassert_true(pm_device_is_powered(reg_chained), "");
44 	zassert_true(pm_device_is_powered(dev), "");
45 
46 	TC_PRINT("Enabling runtime power management on regulators\n");
47 
48 	pm_device_runtime_enable(dev);
49 	pm_device_runtime_enable(reg_chained);
50 	pm_device_runtime_enable(reg_1);
51 	pm_device_runtime_enable(reg_0);
52 
53 	/* Power domains should now be suspended */
54 	zassert_true(pm_device_is_powered(reg_0), "");
55 	zassert_true(pm_device_is_powered(reg_1), "");
56 	zassert_false(pm_device_is_powered(reg_chained), "");
57 	zassert_false(pm_device_is_powered(dev), "");
58 	pm_device_state_get(dev, &state);
59 	zassert_equal(PM_DEVICE_STATE_OFF, state, "");
60 
61 	TC_PRINT("Cycling: %s\n", reg_0->name);
62 
63 	/* reg_chained is powered off reg_0, so it's power state should change */
64 	pm_device_runtime_get(reg_0);
65 	zassert_true(pm_device_is_powered(reg_chained), "");
66 	zassert_false(pm_device_is_powered(dev), "");
67 	pm_device_runtime_put(reg_0);
68 	zassert_false(pm_device_is_powered(reg_chained), "");
69 
70 	TC_PRINT("Cycling: %s\n", reg_1->name);
71 
72 	pm_device_runtime_get(reg_1);
73 	zassert_false(pm_device_is_powered(reg_chained), "");
74 	zassert_true(pm_device_is_powered(dev), "");
75 	/* dev is on reg_1, should have automatically moved to suspended */
76 	pm_device_state_get(dev, &state);
77 	zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
78 	pm_device_runtime_put(reg_1);
79 	pm_device_state_get(dev, &state);
80 	zassert_equal(PM_DEVICE_STATE_OFF, state, "");
81 
82 	TC_PRINT("Cycling: %s\n", reg_chained->name);
83 
84 	/* reg_chained should be powered after being requested */
85 	pm_device_runtime_get(reg_chained);
86 	zassert_true(pm_device_is_powered(reg_chained), "");
87 	zassert_false(pm_device_is_powered(dev), "");
88 	/* dev is not on reg_chained but does reference it, should still be in OFF */
89 	pm_device_state_get(dev, &state);
90 	zassert_equal(PM_DEVICE_STATE_OFF, state, "");
91 	pm_device_runtime_put(reg_chained);
92 
93 	TC_PRINT("Requesting dev: %s\n", dev->name);
94 
95 	/* Directly request the supported device */
96 	pm_device_runtime_get(dev);
97 	zassert_true(pm_device_is_powered(dev), "");
98 	pm_device_state_get(dev, &state);
99 	zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
100 	pm_device_state_get(reg_1, &state);
101 	zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
102 	pm_device_state_get(reg_chained, &state);
103 	zassert_equal(PM_DEVICE_STATE_OFF, state, "");
104 	/* Directly release the supported device */
105 	pm_device_runtime_put(dev);
106 	zassert_false(pm_device_is_powered(dev), "");
107 	pm_device_state_get(dev, &state);
108 	zassert_equal(PM_DEVICE_STATE_OFF, state, "");
109 	pm_device_state_get(reg_1, &state);
110 	zassert_equal(PM_DEVICE_STATE_SUSPENDED, state, "");
111 	pm_device_state_get(reg_chained, &state);
112 	zassert_equal(PM_DEVICE_STATE_OFF, state, "");
113 
114 	/* Directly request the supported device multiple times */
115 	pm_device_runtime_get(dev);
116 	pm_device_runtime_get(dev);
117 	/* Directly release the supported device the first time, check all still powered */
118 	pm_device_runtime_put(dev);
119 	zassert_true(pm_device_is_powered(dev), "");
120 	pm_device_state_get(dev, &state);
121 	zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
122 	pm_device_state_get(reg_1, &state);
123 	zassert_equal(PM_DEVICE_STATE_ACTIVE, state, "");
124 	/* Directly release the supported device the second time, check all off */
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 
132 	TC_PRINT("DONE\n");
133 }
134 
135 ZTEST_SUITE(device_power_domain, NULL, NULL, NULL, NULL, NULL);
136