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