1 /*
2 * Copyright (c) 2023, Commonwealth Scientific and Industrial Research
3 * Organisation (CSIRO) ABN 41 687 119 230.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * State checking in this test is done via the GPIO state instead of
8 * the PM API as this test runs without the PM api enabled.
9 */
10
11 #include <zephyr/ztest.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/pm/device.h>
14 #include <zephyr/pm/device_runtime.h>
15
16 #define POWER_GPIO_CONFIG_IS(node_id, config)\
17 {\
18 const struct gpio_dt_spec gpio = GPIO_DT_SPEC_GET(node_id, enable_gpios);\
19 gpio_flags_t gpio_config; \
20 int gpio_ret = gpio_pin_get_config_dt(&gpio, &gpio_config); \
21 zassert_equal(gpio_ret, 0, "GPIO config retrieval failed"); \
22 zassert_equal(gpio_config, config, "Unexpected config");\
23 }
24
25 #define DEVICE_STATE_IS(node_id, value) \
26 rc = pm_device_state_get(DEVICE_DT_GET(node_id), &state); \
27 zassert_equal(rc, 0, "Device state retrieval failed"); \
28 zassert_equal(state, value, "Unexpected device state");
29
ZTEST(device_driver_init,test_device_driver_init)30 ZTEST(device_driver_init, test_device_driver_init)
31 {
32 #if defined(CONFIG_PM_DEVICE_RUNTIME)
33 enum pm_device_state state;
34 int rc;
35 state = -1;
36 zassert_str_equal("", pm_device_state_str(state),
37 "Invalid device state");
38 /* No device runtime PM, starts on */
39 DEVICE_STATE_IS(DT_NODELABEL(test_reg), PM_DEVICE_STATE_ACTIVE);
40 DEVICE_STATE_IS(DT_NODELABEL(test_reg_chained), PM_DEVICE_STATE_ACTIVE);
41 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg), GPIO_OUTPUT_HIGH);
42 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained), GPIO_OUTPUT_HIGH);
43 zassert_str_equal("active", pm_device_state_str(state),
44 "Invalid device state");
45 /* Device powered, zephyr,pm-device-runtime-auto, starts suspended */
46 DEVICE_STATE_IS(DT_NODELABEL(test_reg_chained_auto), PM_DEVICE_STATE_SUSPENDED);
47 DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto), PM_DEVICE_STATE_SUSPENDED);
48 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained_auto), GPIO_OUTPUT_LOW);
49 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto), GPIO_OUTPUT_LOW);
50 zassert_str_equal("suspended", pm_device_state_str(state),
51 "Invalid device state");
52 /* Device not powered, starts off */
53 DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto_chained), PM_DEVICE_STATE_OFF);
54 DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto_chained_auto), PM_DEVICE_STATE_OFF);
55 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained), GPIO_DISCONNECTED);
56 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained_auto), GPIO_DISCONNECTED);
57 zassert_str_equal("off", pm_device_state_str(state),
58 "Invalid device state");
59 #else
60 /* Every regulator should be in "active" mode automatically.
61 * State checking via GPIO as PM API is disabled.
62 */
63 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg), GPIO_OUTPUT_HIGH);
64 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained), GPIO_OUTPUT_HIGH);
65 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained_auto), GPIO_OUTPUT_HIGH);
66 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto), GPIO_OUTPUT_HIGH);
67 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained), GPIO_OUTPUT_HIGH);
68 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained_auto), GPIO_OUTPUT_HIGH);
69 POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_disabled), GPIO_DISCONNECTED);
70 #endif
71 }
72
73 struct pm_transition_test_dev_data {
74 enum pm_device_state state_turn_on;
75 enum pm_device_state state_resume;
76 enum pm_device_state state_suspend;
77 enum pm_device_state state_turn_off;
78 bool state_other;
79 };
80
pm_transition_test_dev_pm_action(const struct device * dev,enum pm_device_action action)81 static int pm_transition_test_dev_pm_action(const struct device *dev, enum pm_device_action action)
82 {
83 struct pm_transition_test_dev_data *data = dev->data;
84
85 /* Preserve the observed internal state when actions ran */
86 switch (action) {
87 case PM_DEVICE_ACTION_TURN_ON:
88 pm_device_state_get(dev, &data->state_turn_on);
89 break;
90 case PM_DEVICE_ACTION_RESUME:
91 pm_device_state_get(dev, &data->state_resume);
92 break;
93 case PM_DEVICE_ACTION_SUSPEND:
94 pm_device_state_get(dev, &data->state_suspend);
95 break;
96 case PM_DEVICE_ACTION_TURN_OFF:
97 pm_device_state_get(dev, &data->state_turn_off);
98 break;
99 default:
100 data->state_other = true;
101 }
102 return 0;
103 }
104
pm_transition_test_dev_init(const struct device * dev)105 static int pm_transition_test_dev_init(const struct device *dev)
106 {
107 struct pm_transition_test_dev_data *data = dev->data;
108
109 data->state_turn_on = UINT8_MAX;
110 data->state_resume = UINT8_MAX;
111 data->state_suspend = UINT8_MAX;
112 data->state_turn_off = UINT8_MAX;
113 data->state_other = false;
114
115 return pm_device_driver_init(dev, pm_transition_test_dev_pm_action);
116 }
117
pm_transition_test_dev_deinit(const struct device * dev)118 static int pm_transition_test_dev_deinit(const struct device *dev)
119 {
120 struct pm_transition_test_dev_data *data = dev->data;
121
122 data->state_turn_on = UINT8_MAX;
123 data->state_resume = UINT8_MAX;
124 data->state_suspend = UINT8_MAX;
125 data->state_turn_off = UINT8_MAX;
126 data->state_other = false;
127
128 return pm_device_driver_deinit(dev, pm_transition_test_dev_pm_action);
129 }
130
131 static struct pm_transition_test_dev_data dev_data;
132 PM_DEVICE_DEFINE(pm_transition_test_dev_pm, pm_transition_test_dev_pm_action);
133 DEVICE_DEINIT_DEFINE(pm_transition_test_dev, "test_dev",
134 pm_transition_test_dev_init, pm_transition_test_dev_deinit,
135 PM_DEVICE_GET(pm_transition_test_dev_pm), &dev_data, NULL,
136 POST_KERNEL, 0, NULL);
137
ZTEST(device_driver_init,test_device_driver_init_pm_state)138 ZTEST(device_driver_init, test_device_driver_init_pm_state)
139 {
140 #ifdef CONFIG_PM_DEVICE
141 zassert_equal(PM_DEVICE_STATE_OFF, dev_data.state_turn_on);
142 zassert_equal(PM_DEVICE_STATE_SUSPENDED, dev_data.state_resume);
143 zassert_equal(UINT8_MAX, dev_data.state_suspend);
144 zassert_equal(UINT8_MAX, dev_data.state_turn_off);
145 zassert_false(dev_data.state_other);
146 #else
147 /* pm_device_state_get always returns PM_DEVICE_STATE_ACTIVE */
148 zassert_equal(PM_DEVICE_STATE_ACTIVE, dev_data.state_turn_on);
149 zassert_equal(PM_DEVICE_STATE_ACTIVE, dev_data.state_resume);
150 zassert_equal(UINT8_MAX, dev_data.state_suspend);
151 zassert_equal(UINT8_MAX, dev_data.state_turn_off);
152 zassert_false(dev_data.state_other);
153 #endif /* CONFIG_PM */
154
155 #ifdef CONFIG_PM_DEVICE
156 /* device_deinit() blocked if device is not suspended or off */
157 zassert_not_ok(device_deinit(DEVICE_GET(pm_transition_test_dev)));
158 zassert_ok(pm_device_action_run(DEVICE_GET(pm_transition_test_dev),
159 PM_DEVICE_ACTION_SUSPEND));
160 #endif
161
162 zassert_ok(device_deinit(DEVICE_GET(pm_transition_test_dev)));
163
164 #ifdef CONFIG_PM_DEVICE
165 /* no action called as device is already suspended or off */
166 zassert_equal(UINT8_MAX, dev_data.state_turn_on);
167 zassert_equal(UINT8_MAX, dev_data.state_resume);
168 zassert_equal(UINT8_MAX, dev_data.state_suspend);
169 zassert_equal(UINT8_MAX, dev_data.state_turn_off);
170 zassert_false(dev_data.state_other);
171 #else
172 /* pm_device_state_get always returns PM_DEVICE_STATE_ACTIVE */
173 zassert_equal(UINT8_MAX, dev_data.state_turn_on);
174 zassert_equal(UINT8_MAX, dev_data.state_resume);
175 zassert_equal(PM_DEVICE_STATE_ACTIVE, dev_data.state_suspend);
176 zassert_equal(UINT8_MAX, dev_data.state_turn_off);
177 zassert_false(dev_data.state_other);
178 #endif /* CONFIG_PM */
179 }
180
181 ZTEST_SUITE(device_driver_init, NULL, NULL, NULL, NULL, NULL);
182