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 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock)
12 #include "nrf_device_subsys.h"
13 #elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_rtc)
14 #include "esp32_device_subsys.h"
15 #elif DT_HAS_COMPAT_STATUS_OKAY(silabs_series_clock)
16 #include "silabs_device_subsys.h"
17 #else
18 #error "Unsupported board"
19 #endif
20
21 typedef void (*test_func_t)(const struct device *dev,
22 clock_control_subsys_t subsys,
23 uint32_t startup_us);
24
25 typedef bool (*test_capability_check_t)(const struct device *dev,
26 clock_control_subsys_t subsys);
27
setup_instance(const struct device * dev,clock_control_subsys_t subsys)28 static void setup_instance(const struct device *dev, clock_control_subsys_t subsys)
29 {
30 int err;
31 k_busy_wait(1000);
32 do {
33 err = clock_control_off(dev, subsys);
34 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock)
35 if (err == -EPERM) {
36 struct onoff_manager *mgr =
37 z_nrf_clock_control_get_onoff(subsys);
38
39 err = onoff_release(mgr);
40 if (err >= 0) {
41 break;
42 }
43 }
44 #endif
45 } while (clock_control_get_status(dev, subsys) !=
46 CLOCK_CONTROL_STATUS_OFF);
47
48 LOG_INF("setup done");
49 }
50
tear_down_instance(const struct device * dev,clock_control_subsys_t subsys)51 static void tear_down_instance(const struct device *dev,
52 clock_control_subsys_t subsys)
53 {
54 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock)
55 /* Turn on LF clock using onoff service if it is disabled. */
56 const struct device *const clk = DEVICE_DT_GET_ONE(nordic_nrf_clock);
57 struct onoff_client cli;
58 struct onoff_manager *mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
59 int err;
60
61 zassert_true(device_is_ready(clk), "Clock dev is not ready");
62
63 if (clock_control_get_status(clk, CLOCK_CONTROL_NRF_SUBSYS_LF) !=
64 CLOCK_CONTROL_STATUS_OFF) {
65 return;
66 }
67
68 sys_notify_init_spinwait(&cli.notify);
69 err = onoff_request(mgr, &cli);
70 zassert_true(err >= 0, "");
71
72 while (sys_notify_fetch_result(&cli.notify, &err) < 0) {
73 /*empty*/
74 }
75 zassert_true(err >= 0, "");
76 #endif
77 }
78
test_with_single_instance(const struct device * dev,clock_control_subsys_t subsys,uint32_t startup_time,test_func_t func,test_capability_check_t capability_check)79 static void test_with_single_instance(const struct device *dev,
80 clock_control_subsys_t subsys,
81 uint32_t startup_time,
82 test_func_t func,
83 test_capability_check_t capability_check)
84 {
85 setup_instance(dev, subsys);
86
87 if ((capability_check == NULL) || capability_check(dev, subsys)) {
88 func(dev, subsys, startup_time);
89 } else {
90 PRINT("test skipped for subsys:%d\n", (int)subsys);
91 }
92
93 tear_down_instance(dev, subsys);
94 /* Allow logs to be printed. */
95 k_sleep(K_MSEC(100));
96 }
test_all_instances(test_func_t func,test_capability_check_t capability_check)97 static void test_all_instances(test_func_t func,
98 test_capability_check_t capability_check)
99 {
100 for (size_t i = 0; i < ARRAY_SIZE(devices); i++) {
101 for (size_t j = 0; j < devices[i].subsys_cnt; j++) {
102 zassert_true(device_is_ready(devices[i].dev),
103 "Device %s is not ready", devices[i].dev->name);
104 test_with_single_instance(devices[i].dev,
105 devices[i].subsys_data[j].subsys,
106 devices[i].subsys_data[j].startup_us,
107 func, capability_check);
108 }
109 }
110 }
111
112 /*
113 * Basic test for checking correctness of getting clock status.
114 */
test_on_off_status_instance(const struct device * dev,clock_control_subsys_t subsys,uint32_t startup_us)115 static void test_on_off_status_instance(const struct device *dev,
116 clock_control_subsys_t subsys,
117 uint32_t startup_us)
118 {
119 enum clock_control_status status;
120 int err;
121
122 status = clock_control_get_status(dev, subsys);
123 zassert_equal(CLOCK_CONTROL_STATUS_OFF, status,
124 "%s: Unexpected status (%d)", dev->name, status);
125
126 err = clock_control_on(dev, subsys);
127 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
128
129 status = clock_control_get_status(dev, subsys);
130 zassert_equal(status, CLOCK_CONTROL_STATUS_ON,
131 "%s: Unexpected status (%d)", dev->name, status);
132
133 err = clock_control_off(dev, subsys);
134 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
135
136 status = clock_control_get_status(dev, subsys);
137 zassert_equal(CLOCK_CONTROL_STATUS_OFF, status,
138 "%s: Unexpected status (%d)", dev->name, status);
139 }
140
ZTEST(clock_control,test_on_off_status)141 ZTEST(clock_control, test_on_off_status)
142 {
143 test_all_instances(test_on_off_status_instance, NULL);
144 }
145
async_capable_callback(const struct device * dev,clock_control_subsys_t subsys,void * user_data)146 static void async_capable_callback(const struct device *dev,
147 clock_control_subsys_t subsys,
148 void *user_data)
149 {
150 /* empty */
151 }
152
153 /* Function checks if clock supports asynchronous starting. */
async_capable(const struct device * dev,clock_control_subsys_t subsys)154 static bool async_capable(const struct device *dev, clock_control_subsys_t subsys)
155 {
156 int err;
157
158 err = clock_control_async_on(dev, subsys, async_capable_callback, NULL);
159 if (err == -ENOSYS) {
160 ztest_test_skip();
161 } else if (err < 0) {
162 printk("failed %d", err);
163 return false;
164 }
165
166 while (clock_control_get_status(dev, subsys) !=
167 CLOCK_CONTROL_STATUS_ON) {
168 /* pend util clock is started */
169 }
170
171 err = clock_control_off(dev, subsys);
172 if (err < 0) {
173 printk("clock_control_off failed %d", err);
174 return false;
175 }
176
177 return true;
178 }
179
180 /*
181 * Test checks that callbacks are called after clock is started.
182 */
clock_on_callback(const struct device * dev,clock_control_subsys_t subsys,void * user_data)183 static void clock_on_callback(const struct device *dev,
184 clock_control_subsys_t subsys,
185 void *user_data)
186 {
187 bool *executed = (bool *)user_data;
188
189 *executed = true;
190 }
191
test_async_on_instance(const struct device * dev,clock_control_subsys_t subsys,uint32_t startup_us)192 static void test_async_on_instance(const struct device *dev,
193 clock_control_subsys_t subsys,
194 uint32_t startup_us)
195 {
196 enum clock_control_status status;
197 int err;
198 bool executed = false;
199
200 status = clock_control_get_status(dev, subsys);
201 zassert_equal(CLOCK_CONTROL_STATUS_OFF, status,
202 "%s: Unexpected status (%d)", dev->name, status);
203
204 err = clock_control_async_on(dev, subsys, clock_on_callback, &executed);
205 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
206
207 /* wait for clock started. */
208 k_busy_wait(startup_us);
209
210 zassert_true(executed, "%s: Expected flag to be true", dev->name);
211 zassert_equal(CLOCK_CONTROL_STATUS_ON,
212 clock_control_get_status(dev, subsys),
213 "Unexpected clock status");
214 }
215
ZTEST(clock_control,test_async_on)216 ZTEST(clock_control, test_async_on)
217 {
218 test_all_instances(test_async_on_instance, async_capable);
219 }
220
221 /*
222 * Test checks that when asynchronous clock enabling is scheduled but clock
223 * is disabled before being started then callback is never called and error
224 * is reported.
225 */
test_async_on_stopped_on_instance(const struct device * dev,clock_control_subsys_t subsys,uint32_t startup_us)226 static void test_async_on_stopped_on_instance(const struct device *dev,
227 clock_control_subsys_t subsys,
228 uint32_t startup_us)
229 {
230 enum clock_control_status status;
231 int err;
232 unsigned int key;
233 bool executed = false;
234
235 status = clock_control_get_status(dev, subsys);
236 zassert_equal(CLOCK_CONTROL_STATUS_OFF, status,
237 "%s: Unexpected status (%d)", dev->name, status);
238
239 /* lock to prevent clock interrupt for fast starting clocks.*/
240 key = irq_lock();
241 err = clock_control_async_on(dev, subsys, clock_on_callback, &executed);
242 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
243
244 /* Attempt to stop clock while it is being started. */
245 err = clock_control_off(dev, subsys);
246 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
247
248 irq_unlock(key);
249
250 k_busy_wait(10000);
251
252 zassert_false(executed, "%s: Expected flag to be false", dev->name);
253 }
254
ZTEST(clock_control,test_async_on_stopped)255 ZTEST(clock_control, test_async_on_stopped)
256 {
257 test_all_instances(test_async_on_stopped_on_instance, async_capable);
258 }
259
260 /*
261 * Test checks that the second start returns error.
262 */
test_double_start_on_instance(const struct device * dev,clock_control_subsys_t subsys,uint32_t startup_us)263 static void test_double_start_on_instance(const struct device *dev,
264 clock_control_subsys_t subsys,
265 uint32_t startup_us)
266 {
267 enum clock_control_status status;
268 int err;
269
270 status = clock_control_get_status(dev, subsys);
271 zassert_equal(CLOCK_CONTROL_STATUS_OFF, status,
272 "%s: Unexpected status (%d)", dev->name, status);
273
274 err = clock_control_on(dev, subsys);
275 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
276
277 err = clock_control_on(dev, subsys);
278 zassert_true(err < 0, "%s: Unexpected return value:%d", dev->name, err);
279 }
280
ZTEST(clock_control,test_double_start)281 ZTEST(clock_control, test_double_start)
282 {
283 test_all_instances(test_double_start_on_instance, NULL);
284 }
285
286 /*
287 * Test checks that the second stop returns 0.
288 * Test precondition: clock is stopped.
289 */
test_double_stop_on_instance(const struct device * dev,clock_control_subsys_t subsys,uint32_t startup_us)290 static void test_double_stop_on_instance(const struct device *dev,
291 clock_control_subsys_t subsys,
292 uint32_t startup_us)
293 {
294 enum clock_control_status status;
295 int err;
296
297 status = clock_control_get_status(dev, subsys);
298 zassert_equal(CLOCK_CONTROL_STATUS_OFF, status,
299 "%s: Unexpected status (%d)", dev->name, status);
300
301 err = clock_control_off(dev, subsys);
302 zassert_equal(0, err, "%s: Unexpected err (%d)", dev->name, err);
303 }
304
ZTEST(clock_control,test_double_stop)305 ZTEST(clock_control, test_double_stop)
306 {
307 test_all_instances(test_double_stop_on_instance, NULL);
308 }
309
310 ZTEST_SUITE(clock_control, NULL, NULL, NULL, NULL, NULL);
311