Skip to content

Commit f339347

Browse files
committed
drivers: ptp_clock: add ptp_clock shell commands
Added ptp_clock shell commands to check, use, and verify ptp clock. Supported get, set, adjust, rate adjust, and selftest functions. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
1 parent 8b3eb36 commit f339347

File tree

3 files changed

+262
-0
lines changed

3 files changed

+262
-0
lines changed

drivers/ptp_clock/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/ptp_clock.h)
55
zephyr_library()
66

77
zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK ptp_clock.c)
8+
zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK_SHELL ptp_clock_shell.c)
89
zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK_NXP_ENET ptp_clock_nxp_enet.c)

drivers/ptp_clock/Kconfig

+8
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,12 @@ config PTP_CLOCK_INIT_PRIORITY
1616
help
1717
PTP Clock device driver initialization priority
1818

19+
config PTP_CLOCK_SHELL
20+
bool "PTP Clock Shell"
21+
depends on SHELL
22+
help
23+
Enable PTP Clock Shell.
24+
25+
The PTP clock shell currently supports clock operations.
26+
1927
endif # PTP_CLOCK

drivers/ptp_clock/ptp_clock_shell.c

+253
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/shell/shell.h>
8+
#include <stdlib.h>
9+
#include <zephyr/drivers/ptp_clock.h>
10+
#include <string.h>
11+
#include <zephyr/sys/util.h>
12+
#include <zephyr/devicetree.h>
13+
14+
#include <zephyr/logging/log.h>
15+
LOG_MODULE_REGISTER(ptp_clock_shell, CONFIG_LOG_DEFAULT_LEVEL);
16+
17+
static bool device_is_ptp_clock(const struct device *dev)
18+
{
19+
return DEVICE_API_IS(ptp_clock, dev);
20+
}
21+
22+
static void device_name_get(size_t idx, struct shell_static_entry *entry)
23+
{
24+
const struct device *dev = shell_device_filter(idx, device_is_ptp_clock);
25+
26+
entry->syntax = (dev != NULL) ? dev->name : NULL;
27+
entry->handler = NULL;
28+
entry->help = NULL;
29+
entry->subcmd = NULL;
30+
}
31+
32+
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
33+
34+
static int parse_device_arg(const struct shell *sh, char **argv, const struct device **dev)
35+
{
36+
*dev = shell_device_get_binding(argv[1]);
37+
if (!*dev) {
38+
shell_error(sh, "device %s not found", argv[1]);
39+
return -ENODEV;
40+
}
41+
return 0;
42+
}
43+
44+
/* ptp_clock get <device> */
45+
static int cmd_ptp_clock_get(const struct shell *sh, size_t argc, char **argv)
46+
{
47+
struct net_ptp_time tm = {0};
48+
const struct device *dev;
49+
int ret;
50+
51+
ret = parse_device_arg(sh, argv, &dev);
52+
if (ret < 0) {
53+
return ret;
54+
}
55+
56+
ret = ptp_clock_get(dev, &tm);
57+
if (ret < 0) {
58+
return ret;
59+
}
60+
61+
shell_print(sh, "%"PRIu64".%09u", tm.second, tm.nanosecond);
62+
63+
return 0;
64+
}
65+
66+
/* ptp_clock set <device> <seconds> */
67+
static int cmd_ptp_clock_set(const struct shell *sh, size_t argc, char **argv)
68+
{
69+
struct net_ptp_time tm = {0};
70+
const struct device *dev;
71+
int ret;
72+
73+
ret = parse_device_arg(sh, argv, &dev);
74+
if (ret < 0) {
75+
return ret;
76+
}
77+
78+
tm.second = shell_strtoull(argv[2], 10, &ret);
79+
if (ret < 0) {
80+
return ret;
81+
}
82+
83+
ret = ptp_clock_set(dev, &tm);
84+
if (ret < 0) {
85+
return ret;
86+
}
87+
88+
return 0;
89+
}
90+
91+
/* ptp_clock adj <device> <seconds> */
92+
static int cmd_ptp_clock_adj(const struct shell *sh, size_t argc, char **argv)
93+
{
94+
const struct device *dev;
95+
int adj;
96+
int ret;
97+
98+
ret = parse_device_arg(sh, argv, &dev);
99+
if (ret < 0) {
100+
return ret;
101+
}
102+
103+
adj = shell_strtol(argv[2], 10, &ret);
104+
if (ret < 0) {
105+
return ret;
106+
}
107+
108+
ret = ptp_clock_adjust(dev, adj);
109+
if (ret < 0) {
110+
return ret;
111+
}
112+
113+
return 0;
114+
}
115+
116+
/* ptp_clock freq <device> <ppb> */
117+
static int cmd_ptp_clock_freq(const struct shell *sh, size_t argc, char **argv)
118+
{
119+
const struct device *dev;
120+
int ppb;
121+
int ret;
122+
123+
ret = parse_device_arg(sh, argv, &dev);
124+
if (ret < 0) {
125+
return ret;
126+
}
127+
128+
ppb = shell_strtol(argv[2], 10, &ret);
129+
if (ret < 0) {
130+
return ret;
131+
}
132+
133+
ret = ptp_clock_rate_adjust(dev, 1.0 + ((double)ppb / 1000000000.0));
134+
if (ret < 0) {
135+
return ret;
136+
}
137+
138+
return 0;
139+
}
140+
141+
/* ptp_clock selftest <device> <time> <freq> <delay> <adj> */
142+
static int cmd_ptp_clock_selftest(const struct shell *sh, size_t argc, char **argv)
143+
{
144+
struct net_ptp_time tm = {0};
145+
const struct device *dev;
146+
int time, freq, delay, adj, ret;
147+
148+
ret = parse_device_arg(sh, argv, &dev);
149+
if (ret < 0) {
150+
return ret;
151+
}
152+
153+
time = shell_strtol(argv[2], 10, &ret);
154+
if (ret < 0) {
155+
return ret;
156+
}
157+
158+
freq = shell_strtol(argv[3], 10, &ret);
159+
if (ret < 0) {
160+
return ret;
161+
}
162+
163+
delay = shell_strtol(argv[4], 10, &ret);
164+
if (ret < 0) {
165+
return ret;
166+
}
167+
168+
adj = shell_strtol(argv[5], 10, &ret);
169+
if (ret < 0) {
170+
return ret;
171+
}
172+
173+
/* set 'time' seconds and read back to verify clock setting/getting */
174+
tm.second = time;
175+
ret = ptp_clock_set(dev, &tm);
176+
if (ret < 0) {
177+
shell_print(sh, "failed to set time");
178+
return ret;
179+
}
180+
shell_print(sh, "test1: set time %"PRIu64".%09u", tm.second, tm.nanosecond);
181+
182+
ret = ptp_clock_get(dev, &tm);
183+
if (ret < 0) {
184+
shell_print(sh, "failed to get time");
185+
return ret;
186+
}
187+
shell_print(sh, " result: read back time %"PRIu64".%09u", tm.second, tm.nanosecond);
188+
189+
/* set 'freq' with ppb value, sleep 'delay' seconds, and read back time */
190+
ret = ptp_clock_rate_adjust(dev, 1.0 + ((double)freq / 1000000000.0));
191+
if (ret < 0) {
192+
shell_print(sh, "failed to adjust rate");
193+
return ret;
194+
}
195+
shell_print(sh, "test2: adjust frequency %d ppb (ratio %f), delay %d seconds...",
196+
freq, 1.0 + ((double)freq / 1000000000.0), delay);
197+
198+
k_sleep(K_SECONDS(delay));
199+
200+
ret = ptp_clock_get(dev, &tm);
201+
if (ret < 0) {
202+
shell_print(sh, "failed to get time");
203+
return ret;
204+
}
205+
shell_print(sh, " result: read back time %"PRIu64".%09u", tm.second, tm.nanosecond);
206+
207+
/* set 'adj' seconds and read back time to verify time adjustment */
208+
ret = ptp_clock_adjust(dev, adj);
209+
if (ret < 0) {
210+
shell_print(sh, "failed to adjtime");
211+
return ret;
212+
}
213+
shell_print(sh, "test3: adjust time %d seconds", adj);
214+
215+
ret = ptp_clock_get(dev, &tm);
216+
if (ret < 0) {
217+
shell_print(sh, "failed to get time");
218+
return ret;
219+
}
220+
shell_print(sh, " result: read back time %"PRIu64".%09u", tm.second, tm.nanosecond);
221+
222+
return 0;
223+
}
224+
225+
SHELL_STATIC_SUBCMD_SET_CREATE(sub_ptp_clock_cmds,
226+
SHELL_CMD_ARG(get, &dsub_device_name,
227+
"Get time: get <device>",
228+
cmd_ptp_clock_get, 2, 0),
229+
SHELL_CMD_ARG(set, &dsub_device_name,
230+
"Set time: set <device> <seconds>",
231+
cmd_ptp_clock_set, 3, 0),
232+
SHELL_CMD_ARG(adj, &dsub_device_name,
233+
"Adjust time: adj <device> <seconds>",
234+
cmd_ptp_clock_adj, 3, 0),
235+
SHELL_CMD_ARG(freq, &dsub_device_name,
236+
"Adjust frequency: freq <device> <ppb>",
237+
cmd_ptp_clock_freq, 3, 0),
238+
SHELL_CMD_ARG(selftest, &dsub_device_name,
239+
"selftest <device> <time> <freq> <delay> <adj>\n"
240+
"The selftest will do following steps:\n"
241+
"1. set 'time' with seconds and read back to\n"
242+
" verify clock setting/getting.\n"
243+
"2. set 'freq' with ppb value, sleep 'delay' seconds,\n"
244+
" and read back time to verify rate adjustment.\n"
245+
"3. set 'adj' seconds and read back time to\n"
246+
" verify time adjustment.\n"
247+
"Example:\n"
248+
" ptp_clock selftest ptp_clock 1000 100000000 10 10",
249+
cmd_ptp_clock_selftest, 6, 0),
250+
SHELL_SUBCMD_SET_END /* Array terminated. */
251+
);
252+
253+
SHELL_CMD_REGISTER(ptp_clock, &sub_ptp_clock_cmds, "PTP clock commands", NULL);

0 commit comments

Comments
 (0)