Skip to content

Commit 75bd191

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 75bd191

File tree

3 files changed

+242
-0
lines changed

3 files changed

+242
-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

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
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 = strtoull(argv[2], NULL, 10);
79+
80+
ret = ptp_clock_set(dev, &tm);
81+
if (ret < 0) {
82+
return ret;
83+
}
84+
85+
return 0;
86+
}
87+
88+
/* ptp_clock adj <device> <nanoseconds> */
89+
static int cmd_ptp_clock_adj(const struct shell *sh, size_t argc, char **argv)
90+
{
91+
const struct device *dev;
92+
int adj;
93+
int ret;
94+
95+
ret = parse_device_arg(sh, argv, &dev);
96+
if (ret < 0) {
97+
return ret;
98+
}
99+
100+
adj = strtol(argv[2], NULL, 10);
101+
102+
ret = ptp_clock_adjust(dev, adj);
103+
if (ret < 0) {
104+
return ret;
105+
}
106+
107+
return 0;
108+
}
109+
110+
/* ptp_clock freq <device> <ppb> */
111+
static int cmd_ptp_clock_freq(const struct shell *sh, size_t argc, char **argv)
112+
{
113+
const struct device *dev;
114+
int64_t ppb;
115+
int ret;
116+
117+
ret = parse_device_arg(sh, argv, &dev);
118+
if (ret < 0) {
119+
return ret;
120+
}
121+
122+
ppb = strtoll(argv[2], NULL, 10);
123+
124+
ret = ptp_clock_rate_adjust(dev, 1.0 + ((double)ppb / 1000000000.0));
125+
if (ret < 0) {
126+
return ret;
127+
}
128+
129+
return 0;
130+
}
131+
132+
/* ptp_clock selftest <device> */
133+
static int cmd_ptp_clock_selftest(const struct shell *sh, size_t argc, char **argv)
134+
{
135+
struct net_ptp_time tm = {0};
136+
const struct device *dev;
137+
int i, ret;
138+
double ratio = 1.1;
139+
140+
ret = parse_device_arg(sh, argv, &dev);
141+
if (ret < 0) {
142+
return ret;
143+
}
144+
145+
/* test getting time */
146+
ret = ptp_clock_get(dev, &tm);
147+
if (ret < 0) {
148+
shell_print(sh, "failed to test getting time");
149+
return ret;
150+
}
151+
152+
shell_print(sh, "get time: %"PRIu64".%09u", tm.second, tm.nanosecond);
153+
154+
/* test setting time */
155+
tm.second = 1000;
156+
tm.nanosecond = 0;
157+
ret = ptp_clock_set(dev, &tm);
158+
if (ret < 0) {
159+
shell_print(sh, "failed to test setting time");
160+
return ret;
161+
}
162+
163+
shell_print(sh, "set time 1000s and read back: %"PRIu64".%09u", tm.second, tm.nanosecond);
164+
165+
/* test adjusting rate */
166+
for (i = 0; i < 10; i++) {
167+
ret = ptp_clock_rate_adjust(dev, ratio);
168+
if (ret < 0) {
169+
/* retry */
170+
ratio -= 0.01;
171+
continue;
172+
}
173+
break;
174+
}
175+
176+
if (i == 10) {
177+
shell_print(sh, "failed to test adjusting rate");
178+
return ret;
179+
}
180+
181+
shell_print(sh, "adjust ratio %f, sleep 10s...", ratio);
182+
k_sleep(K_MSEC(10000));
183+
184+
/* get time again */
185+
ret = ptp_clock_get(dev, &tm);
186+
if (ret < 0) {
187+
shell_print(sh, "failed to get time");
188+
return ret;
189+
}
190+
191+
shell_print(sh, "get time: %"PRIu64".%09u", tm.second, tm.nanosecond);
192+
193+
/* test adjusting time - adjust 3 second */
194+
for (i = 0; i < 30; i++) {
195+
ret = ptp_clock_adjust(dev, 100000000);
196+
if (ret < 0) {
197+
shell_print(sh, "failed to test adjusting time");
198+
return ret;
199+
}
200+
}
201+
202+
/* get time again */
203+
ret = ptp_clock_get(dev, &tm);
204+
if (ret < 0) {
205+
shell_print(sh, "failed to get time");
206+
return ret;
207+
}
208+
209+
shell_print(sh, "adjust 3 seconds: %"PRIu64".%09u", tm.second, tm.nanosecond);
210+
211+
return 0;
212+
}
213+
214+
SHELL_STATIC_SUBCMD_SET_CREATE(sub_ptp_clock_cmds,
215+
SHELL_CMD_ARG(get, &dsub_device_name,
216+
"Get time: get <device>",
217+
cmd_ptp_clock_get, 2, 0),
218+
SHELL_CMD_ARG(set, &dsub_device_name,
219+
"Set time: set <device> <seconds>",
220+
cmd_ptp_clock_set, 3, 0),
221+
SHELL_CMD_ARG(adj, &dsub_device_name,
222+
"Adjust time: adj <device> <nanoseconds>",
223+
cmd_ptp_clock_adj, 3, 0),
224+
SHELL_CMD_ARG(freq, &dsub_device_name,
225+
"Adjust frequency: freq <device> <ppb>",
226+
cmd_ptp_clock_freq, 3, 0),
227+
SHELL_CMD_ARG(selftest, &dsub_device_name,
228+
"Selftest for clock operations: selftest <device>",
229+
cmd_ptp_clock_selftest, 2, 0),
230+
SHELL_SUBCMD_SET_END /* Array terminated. */
231+
);
232+
233+
SHELL_CMD_REGISTER(ptp_clock, &sub_ptp_clock_cmds, "PTP clock commands", NULL);

0 commit comments

Comments
 (0)