1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/devicetree/clocks.h>
10 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
11 
12 #if DT_NODE_EXISTS(DT_ALIAS(sample_device))
13 #define SAMPLE_CLOCK_NODE DT_CLOCKS_CTLR(DT_ALIAS(sample_device))
14 #elif DT_NODE_EXISTS(DT_ALIAS(sample_clock))
15 #define SAMPLE_CLOCK_NODE DT_ALIAS(sample_clock)
16 #endif
17 
18 #define SAMPLE_CLOCK_NAME DT_NODE_FULL_NAME(SAMPLE_CLOCK_NODE)
19 
20 #define SAMPLE_NOTIFY_TIMEOUT       K_SECONDS(2)
21 #define SAMPLE_PRE_REQUEST_TIMEOUT  K_SECONDS(CONFIG_SAMPLE_PRE_REQUEST_TIMEOUT)
22 #define SAMPLE_KEEP_REQUEST_TIMEOUT K_SECONDS(CONFIG_SAMPLE_KEEP_REQUEST_TIMEOUT)
23 
24 const struct device *sample_clock_dev = DEVICE_DT_GET(SAMPLE_CLOCK_NODE);
25 
26 static K_SEM_DEFINE(sample_sem, 0, 1);
27 
sample_notify_cb(struct onoff_manager * mgr,struct onoff_client * cli,uint32_t state,int res)28 static void sample_notify_cb(struct onoff_manager *mgr,
29 			     struct onoff_client *cli,
30 			     uint32_t state,
31 			     int res)
32 {
33 	ARG_UNUSED(mgr);
34 	ARG_UNUSED(cli);
35 	ARG_UNUSED(state);
36 	ARG_UNUSED(res);
37 
38 	k_sem_give(&sample_sem);
39 }
40 
main(void)41 int main(void)
42 {
43 	struct onoff_client cli;
44 	int ret;
45 	int res;
46 	int64_t req_start_uptime;
47 	int64_t req_stop_uptime;
48 
49 	printk("\n");
50 	printk("clock name: %s\n", SAMPLE_CLOCK_NAME);
51 	printk("minimum frequency request: %uHz\n", CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ);
52 	printk("minimum accuracy request: %uPPM\n", CONFIG_SAMPLE_CLOCK_ACCURACY_PPM);
53 	printk("minimum precision request: %u\n", CONFIG_SAMPLE_CLOCK_PRECISION);
54 
55 	const struct nrf_clock_spec spec = {
56 		.frequency = CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ,
57 		.accuracy = CONFIG_SAMPLE_CLOCK_ACCURACY_PPM,
58 		.precision = CONFIG_SAMPLE_CLOCK_PRECISION,
59 	};
60 
61 	sys_notify_init_callback(&cli.notify, sample_notify_cb);
62 
63 	k_sleep(SAMPLE_PRE_REQUEST_TIMEOUT);
64 
65 	printk("\n");
66 	printk("requesting minimum clock specs\n");
67 	req_start_uptime = k_uptime_get();
68 	ret = nrf_clock_control_request(sample_clock_dev, &spec, &cli);
69 	if (ret < 0) {
70 		printk("minimum clock specs could not be met\n");
71 		return 0;
72 	}
73 
74 	ret = k_sem_take(&sample_sem, SAMPLE_NOTIFY_TIMEOUT);
75 	if (ret < 0) {
76 		printk("timed out waiting for clock to meet request\n");
77 		return 0;
78 	}
79 
80 	req_stop_uptime = k_uptime_get();
81 
82 	ret = sys_notify_fetch_result(&cli.notify, &res);
83 	if (ret < 0) {
84 		printk("sys notify fetch failed\n");
85 		return 0;
86 	}
87 
88 	if (res < 0) {
89 		printk("failed to apply request to clock\n");
90 		return 0;
91 	}
92 
93 	printk("request applied to clock in %llims\n", req_stop_uptime - req_start_uptime);
94 	k_sleep(SAMPLE_KEEP_REQUEST_TIMEOUT);
95 
96 	printk("\n");
97 	printk("releasing requested clock specs\n");
98 	ret = nrf_clock_control_release(sample_clock_dev, &spec);
99 	if (ret < 0) {
100 		printk("failed to release requested clock specs\n");
101 		return 0;
102 	}
103 
104 	printk("clock spec request released\n");
105 	return 0;
106 }
107