Skip to content

Commit 492f516

Browse files
Flavio Ceolincfriedt
authored andcommitted
tests: pm: Test devices suspend/resume order
Check if devices are suspend and resumed following the device initialization order. Signed-off-by: Flavio Ceolin <[email protected]>
1 parent 86abf46 commit 492f516

File tree

3 files changed

+169
-8
lines changed

3 files changed

+169
-8
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2021 Intel Corporation.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
device_a: device_a {
9+
label = "device_a";
10+
compatible = "test-device-pm";
11+
};
12+
13+
device_b: device_b {
14+
label = "device_b";
15+
compatible = "test-device-pm";
16+
};
17+
18+
device_c: device_c {
19+
label = "device_c";
20+
compatible = "test-device-pm";
21+
};
22+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2021, Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
This binding provides resources required to build and run the
6+
tests/subsys/power/power_mgmt test in Zephyr.
7+
8+
compatible: "test-device-pm"

tests/subsys/pm/power_mgmt/src/main.c

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,121 @@ static bool set_pm;
2626
static bool leave_idle;
2727
static bool idle_entered;
2828
static bool testing_device_runtime;
29+
static bool testing_device_order;
2930

3031
static const struct device *device_dummy;
3132
static struct dummy_driver_api *api;
3233

34+
static const struct device *device_a;
35+
static const struct device *device_c;
36+
37+
38+
/*
39+
* According with the initialization level, devices A, B and C are
40+
* initialized in the following order A -> B -> C.
41+
*
42+
* The power management subsystem uses this order to suspend and resume
43+
* devices. Devices are suspended in the reverse order:
44+
*
45+
* C -> B -> A
46+
*
47+
* While resuming uses the initialization order:
48+
*
49+
* A -> B -> C
50+
*
51+
* This test checks if these order is correct checking devices A and C states
52+
* when suspending / resuming device B.
53+
*/
54+
55+
56+
/* Common init function for devices A,B and C */
57+
static int device_init(const struct device *dev)
58+
{
59+
ARG_UNUSED(dev);
60+
61+
return 0;
62+
}
63+
64+
static int device_a_pm_action(const struct device *dev,
65+
enum pm_device_action pm_action)
66+
{
67+
ARG_UNUSED(dev);
68+
ARG_UNUSED(pm_action);
69+
70+
return 0;
71+
}
72+
73+
DEVICE_DT_DEFINE(DT_INST(0, test_device_pm), device_init,
74+
device_a_pm_action, NULL, NULL,
75+
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
76+
NULL);
77+
78+
79+
static int device_b_pm_action(const struct device *dev,
80+
enum pm_device_action pm_action)
81+
{
82+
enum pm_device_state state_a;
83+
enum pm_device_state state_c;
84+
85+
if (!testing_device_order) {
86+
return 0;
87+
}
88+
89+
(void)pm_device_state_get(device_a, &state_a);
90+
(void)pm_device_state_get(device_c, &state_c);
91+
92+
switch (pm_action) {
93+
case PM_DEVICE_ACTION_RESUME:
94+
/* Check if device C is still suspended */
95+
zassert_equal(state_c, PM_DEVICE_STATE_SUSPENDED,
96+
"Inconsistent states");
97+
/* Check if device A is already active */
98+
zassert_equal(state_a, PM_DEVICE_STATE_ACTIVE,
99+
"Inconsistent states");
100+
break;
101+
case PM_DEVICE_ACTION_SUSPEND:
102+
/* Check if device C is already suspended */
103+
zassert_equal(state_c, PM_DEVICE_STATE_SUSPENDED,
104+
"Inconsistent states");
105+
/* Check if device A is still active */
106+
zassert_equal(state_a, PM_DEVICE_STATE_ACTIVE,
107+
"Inconsistent states");
108+
break;
109+
default:
110+
break;
111+
}
112+
113+
return 0;
114+
}
115+
116+
DEVICE_DT_DEFINE(DT_INST(1, test_device_pm), device_init,
117+
device_b_pm_action, NULL, NULL,
118+
PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
119+
NULL);
120+
121+
static int device_c_pm_action(const struct device *dev,
122+
enum pm_device_action pm_action)
123+
{
124+
ARG_UNUSED(dev);
125+
ARG_UNUSED(pm_action);
126+
127+
return 0;
128+
}
129+
130+
DEVICE_DT_DEFINE(DT_INST(2, test_device_pm), device_init,
131+
device_c_pm_action, NULL, NULL,
132+
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
133+
NULL);
134+
135+
136+
33137
void pm_power_state_set(struct pm_state_info info)
34138
{
139+
/* If testing device order this function does not need to anything */
140+
if (testing_device_order) {
141+
return;
142+
}
143+
35144
/* at this point, notify_pm_state_entry() implemented in
36145
* this file has been called and set_pm should have been set
37146
*/
@@ -157,6 +266,11 @@ void test_power_idle(void)
157266
zassert_true(idle_entered, "Never entered idle thread");
158267
}
159268

269+
static struct pm_notifier notifier = {
270+
.state_entry = notify_pm_state_entry,
271+
.state_exit = notify_pm_state_exit,
272+
};
273+
160274
/*
161275
* @brief test power state transition
162276
*
@@ -174,16 +288,19 @@ void test_power_state_trans(void)
174288
{
175289
int ret;
176290

291+
pm_notifier_register(&notifier);
177292
enter_low_power = true;
178293

179-
ret = pm_device_runtime_disable(dev);
294+
ret = pm_device_runtime_disable(device_dummy);
180295
zassert_true(ret == 0, "Failed to disable device runtime PM");
181296

182297
/* give way to idle thread */
183298
k_sleep(SLEEP_TIMEOUT);
184299
zassert_true(leave_idle, NULL);
185300

186-
pm_device_runtime_enable(dev);
301+
pm_device_runtime_enable(device_dummy);
302+
303+
pm_notifier_unregister(&notifier);
187304
}
188305

189306
/*
@@ -205,6 +322,7 @@ void test_power_state_notification(void)
205322
int ret;
206323
enum pm_device_state device_power_state;
207324

325+
pm_notifier_register(&notifier);
208326
enter_low_power = true;
209327

210328
ret = api->open(device_dummy);
@@ -223,22 +341,35 @@ void test_power_state_notification(void)
223341
api->close(device_dummy);
224342
pm_device_state_get(device_dummy, &device_power_state);
225343
zassert_equal(device_power_state, PM_DEVICE_STATE_SUSPENDED, NULL);
344+
pm_notifier_unregister(&notifier);
226345
}
227346

228-
void test_main(void)
347+
void test_device_order(void)
229348
{
230-
struct pm_notifier notifier = {
231-
.state_entry = notify_pm_state_entry,
232-
.state_exit = notify_pm_state_exit,
233-
};
349+
device_a = DEVICE_DT_GET(DT_INST(0, test_device_pm));
350+
zassert_not_null(device_a, "Failed to get device");
234351

235-
pm_notifier_register(&notifier);
352+
device_c = DEVICE_DT_GET(DT_INST(2, test_device_pm));
353+
zassert_not_null(device_c, "Failed to get device");
354+
355+
testing_device_order = true;
356+
enter_low_power = true;
357+
358+
k_sleep(SLEEP_TIMEOUT);
359+
360+
testing_device_order = false;
361+
}
362+
363+
364+
void test_main(void)
365+
{
236366
device_dummy = device_get_binding(DUMMY_DRIVER_NAME);
237367
api = (struct dummy_driver_api *)device_dummy->api;
238368

239369
ztest_test_suite(power_management_test,
240370
ztest_1cpu_unit_test(test_power_idle),
241371
ztest_1cpu_unit_test(test_power_state_trans),
372+
ztest_1cpu_unit_test(test_device_order),
242373
ztest_1cpu_unit_test(test_power_state_notification));
243374
ztest_run_test_suite(power_management_test);
244375
pm_notifier_unregister(&notifier);

0 commit comments

Comments
 (0)