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