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