1 /*
2  * Copyright (c) 2019, Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/ztest.h>
7 #include <zephyr/drivers/clock_control.h>
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_REGISTER(test);
10 
11 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
12 
get_mgr(void)13 static struct onoff_manager *get_mgr(void)
14 {
15 	return z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
16 }
17 
clock_is_off(void)18 static bool clock_is_off(void)
19 {
20 	const struct device *const clk = DEVICE_DT_GET_ONE(nordic_nrf_clock);
21 
22 	zassert_true(device_is_ready(clk), "Device is not ready");
23 
24 	return clock_control_get_status(clk, CLOCK_CONTROL_NRF_SUBSYS_HF) ==
25 			CLOCK_CONTROL_STATUS_OFF;
26 }
27 
clock_off(void)28 static void clock_off(void)
29 {
30 	struct onoff_manager *mgr = get_mgr();
31 
32 	do {
33 		(void)onoff_release(mgr);
34 
35 	} while (!clock_is_off());
36 }
37 
ZTEST(clock_control_onoff,test_clock_blocking_on)38 ZTEST(clock_control_onoff, test_clock_blocking_on)
39 {
40 	struct onoff_client cli;
41 	struct onoff_manager *mgr = get_mgr();
42 	int err;
43 
44 	clock_off();
45 
46 	sys_notify_init_spinwait(&cli.notify);
47 	err = onoff_request(mgr, &cli);
48 	zassert_true(err >= 0, "");
49 
50 	while (sys_notify_fetch_result(&cli.notify, &err) < 0) {
51 		/* empty */
52 	}
53 	zassert_true(err >= 0, "");
54 
55 	/* clock on, now turn it off */
56 
57 	err = onoff_release(mgr);
58 	zassert_true(err >= 0, "");
59 }
60 
ZTEST(clock_control_onoff,test_clock_spinwait_release_before_start)61 ZTEST(clock_control_onoff, test_clock_spinwait_release_before_start)
62 {
63 	struct onoff_client cli;
64 	struct onoff_manager *mgr = get_mgr();
65 	int err;
66 
67 	clock_off();
68 	k_busy_wait(10000);
69 
70 	sys_notify_init_spinwait(&cli.notify);
71 	err = onoff_request(mgr, &cli);
72 	zassert_true(err >= 0, "err: %d", err);
73 
74 	/* Attempt to release while ongoing start. Cannot do that */
75 	err = onoff_cancel_or_release(mgr, &cli);
76 	zassert_true(err >= 0, "err: %d", err);
77 
78 	k_busy_wait(100000);
79 
80 	zassert_true(clock_is_off(), "");
81 }
82 
request_cb(struct onoff_manager * mgr,struct onoff_client * cli,uint32_t state,int res)83 static void request_cb(struct onoff_manager *mgr, struct onoff_client *cli,
84 			uint32_t state, int res)
85 {
86 	int err;
87 
88 	err = onoff_cancel_or_release(mgr, cli);
89 	zassert_true(err >= 0, "err: %d", err);
90 }
91 
92 /* Test checks if premature clock release works ok. If clock is released before
93  * it is started it is the best to do that release from the callback to avoid
94  * waiting until clock is started in the release context.
95  */
ZTEST(clock_control_onoff,test_clock_release_from_callback)96 ZTEST(clock_control_onoff, test_clock_release_from_callback)
97 {
98 	struct onoff_client cli;
99 	struct onoff_manager *mgr = get_mgr();
100 	int err;
101 
102 	clock_off();
103 	k_busy_wait(100);
104 
105 	sys_notify_init_callback(&cli.notify, request_cb);
106 	err = onoff_request(mgr, &cli);
107 	zassert_true(err >= 0, "err: %d", err);
108 
109 	k_busy_wait(100000);
110 
111 	/* clock should be turned off in the started callback */
112 	zassert_true(clock_is_off(), "clock should be off");
113 }
114 ZTEST_SUITE(clock_control_onoff, NULL, NULL, NULL, NULL, NULL);
115