aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/testing/selftests/ptp/testptp.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/ptp/testptp.c')
-rw-r--r--tools/testing/selftests/ptp/testptp.c161
1 files changed, 138 insertions, 23 deletions
diff --git a/tools/testing/selftests/ptp/testptp.c b/tools/testing/selftests/ptp/testptp.c
index f7911aaeb007..011252fe238c 100644
--- a/tools/testing/selftests/ptp/testptp.c
+++ b/tools/testing/selftests/ptp/testptp.c
@@ -110,7 +110,7 @@ static long ppb_to_scaled_ppm(int ppb)
static int64_t pctns(struct ptp_clock_time *t)
{
- return t->sec * 1000000000LL + t->nsec;
+ return t->sec * NSEC_PER_SEC + t->nsec;
}
static void usage(char *progname)
@@ -121,6 +121,7 @@ static void usage(char *progname)
" -d name device to open\n"
" -e val read 'val' external time stamp events\n"
" -f val adjust the ptp clock frequency by 'val' ppb\n"
+ " -F chan Enable single channel mask and keep device open for debugfs verification.\n"
" -g get the ptp clock time\n"
" -h prints this message\n"
" -i val index for event/trigger\n"
@@ -133,6 +134,8 @@ static void usage(char *progname)
" 0 - none\n"
" 1 - external time stamp\n"
" 2 - periodic output\n"
+ " -n val shift the ptp clock time by 'val' nanoseconds\n"
+ " -o val phase offset (in nanoseconds) to be provided to the PHC servo\n"
" -p val enable output with a period of 'val' nanoseconds\n"
" -H val set output phase to 'val' nanoseconds (requires -p)\n"
" -w val set output pulse width to 'val' nanoseconds (requires -p)\n"
@@ -141,8 +144,10 @@ static void usage(char *progname)
" -S set the system time from the ptp clock time\n"
" -t val shift the ptp clock time by 'val' seconds\n"
" -T val set the ptp clock time to 'val' seconds\n"
+ " -x val get an extended ptp clock time with the desired number of samples (up to %d)\n"
+ " -X get a ptp clock cross timestamp\n"
" -z test combinations of rising/falling external time stamp flags\n",
- progname);
+ progname, PTP_MAX_SAMPLES);
}
int main(int argc, char *argv[])
@@ -156,6 +161,8 @@ int main(int argc, char *argv[])
struct timex tx;
struct ptp_clock_time *pct;
struct ptp_sys_offset *sysoff;
+ struct ptp_sys_offset_extended *soe;
+ struct ptp_sys_offset_precise *xts;
char *progname;
unsigned int i;
@@ -165,6 +172,8 @@ int main(int argc, char *argv[])
clockid_t clkid;
int adjfreq = 0x7fffffff;
int adjtime = 0;
+ int adjns = 0;
+ int adjphase = 0;
int capabilities = 0;
int extts = 0;
int flagtest = 0;
@@ -172,11 +181,14 @@ int main(int argc, char *argv[])
int index = 0;
int list_pins = 0;
int pct_offset = 0;
+ int getextended = 0;
+ int getcross = 0;
int n_samples = 0;
int pin_index = -1, pin_func;
int pps = -1;
int seconds = 0;
int settime = 0;
+ int channel = -1;
int64_t t1, t2, tp;
int64_t interval, offset;
@@ -186,7 +198,7 @@ int main(int argc, char *argv[])
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
- while (EOF != (c = getopt(argc, argv, "cd:e:f:ghH:i:k:lL:p:P:sSt:T:w:z"))) {
+ while (EOF != (c = getopt(argc, argv, "cd:e:f:F:ghH:i:k:lL:n:o:p:P:sSt:T:w:x:Xz"))) {
switch (c) {
case 'c':
capabilities = 1;
@@ -200,6 +212,9 @@ int main(int argc, char *argv[])
case 'f':
adjfreq = atoi(optarg);
break;
+ case 'F':
+ channel = atoi(optarg);
+ break;
case 'g':
gettime = 1;
break;
@@ -223,6 +238,12 @@ int main(int argc, char *argv[])
return -1;
}
break;
+ case 'n':
+ adjns = atoi(optarg);
+ break;
+ case 'o':
+ adjphase = atoi(optarg);
+ break;
case 'p':
perout = atoll(optarg);
break;
@@ -245,6 +266,18 @@ int main(int argc, char *argv[])
case 'w':
pulsewidth = atoi(optarg);
break;
+ case 'x':
+ getextended = atoi(optarg);
+ if (getextended < 1 || getextended > PTP_MAX_SAMPLES) {
+ fprintf(stderr,
+ "number of extended timestamp samples must be between 1 and %d; was asked for %d\n",
+ PTP_MAX_SAMPLES, getextended);
+ return -1;
+ }
+ break;
+ case 'X':
+ getcross = 1;
+ break;
case 'z':
flagtest = 1;
break;
@@ -282,7 +315,8 @@ int main(int argc, char *argv[])
" %d pulse per second\n"
" %d programmable pins\n"
" %d cross timestamping\n"
- " %d adjust_phase\n",
+ " %d adjust_phase\n"
+ " %d maximum phase adjustment (ns)\n",
caps.max_adj,
caps.n_alarm,
caps.n_ext_ts,
@@ -290,7 +324,8 @@ int main(int argc, char *argv[])
caps.pps,
caps.n_pins,
caps.cross_timestamping,
- caps.adjust_phase);
+ caps.adjust_phase,
+ caps.max_phase_adj);
}
}
@@ -305,11 +340,16 @@ int main(int argc, char *argv[])
}
}
- if (adjtime) {
+ if (adjtime || adjns) {
memset(&tx, 0, sizeof(tx));
- tx.modes = ADJ_SETOFFSET;
+ tx.modes = ADJ_SETOFFSET | ADJ_NANO;
tx.time.tv_sec = adjtime;
- tx.time.tv_usec = 0;
+ tx.time.tv_usec = adjns;
+ while (tx.time.tv_usec < 0) {
+ tx.time.tv_sec -= 1;
+ tx.time.tv_usec += NSEC_PER_SEC;
+ }
+
if (clock_adjtime(clkid, &tx) < 0) {
perror("clock_adjtime");
} else {
@@ -317,6 +357,18 @@ int main(int argc, char *argv[])
}
}
+ if (adjphase) {
+ memset(&tx, 0, sizeof(tx));
+ tx.modes = ADJ_OFFSET | ADJ_NANO;
+ tx.offset = adjphase;
+
+ if (clock_adjtime(clkid, &tx) < 0) {
+ perror("clock_adjtime");
+ } else {
+ puts("phase adjustment okay");
+ }
+ }
+
if (gettime) {
if (clock_gettime(clkid, &ts)) {
perror("clock_gettime");
@@ -354,6 +406,18 @@ int main(int argc, char *argv[])
}
}
+ if (pin_index >= 0) {
+ memset(&desc, 0, sizeof(desc));
+ desc.index = pin_index;
+ desc.func = pin_func;
+ desc.chan = index;
+ if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) {
+ perror("PTP_PIN_SETFUNC");
+ } else {
+ puts("set pin function okay");
+ }
+ }
+
if (extts) {
memset(&extts_request, 0, sizeof(extts_request));
extts_request.index = index;
@@ -444,18 +508,6 @@ int main(int argc, char *argv[])
}
}
- if (pin_index >= 0) {
- memset(&desc, 0, sizeof(desc));
- desc.index = pin_index;
- desc.func = pin_func;
- desc.chan = index;
- if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) {
- perror("PTP_PIN_SETFUNC");
- } else {
- puts("set pin function okay");
- }
- }
-
if (pps != -1) {
int enable = pps ? 1 : 0;
if (ioctl(fd, PTP_ENABLE_PPS, enable)) {
@@ -492,11 +544,11 @@ int main(int argc, char *argv[])
interval = t2 - t1;
offset = (t2 + t1) / 2 - tp;
- printf("system time: %lld.%u\n",
+ printf("system time: %lld.%09u\n",
(pct+2*i)->sec, (pct+2*i)->nsec);
- printf("phc time: %lld.%u\n",
+ printf("phc time: %lld.%09u\n",
(pct+2*i+1)->sec, (pct+2*i+1)->nsec);
- printf("system time: %lld.%u\n",
+ printf("system time: %lld.%09u\n",
(pct+2*i+2)->sec, (pct+2*i+2)->nsec);
printf("system/phc clock time offset is %" PRId64 " ns\n"
"system clock time delay is %" PRId64 " ns\n",
@@ -506,6 +558,69 @@ int main(int argc, char *argv[])
free(sysoff);
}
+ if (getextended) {
+ soe = calloc(1, sizeof(*soe));
+ if (!soe) {
+ perror("calloc");
+ return -1;
+ }
+
+ soe->n_samples = getextended;
+
+ if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, soe)) {
+ perror("PTP_SYS_OFFSET_EXTENDED");
+ } else {
+ printf("extended timestamp request returned %d samples\n",
+ getextended);
+
+ for (i = 0; i < getextended; i++) {
+ printf("sample #%2d: system time before: %lld.%09u\n",
+ i, soe->ts[i][0].sec, soe->ts[i][0].nsec);
+ printf(" phc time: %lld.%09u\n",
+ soe->ts[i][1].sec, soe->ts[i][1].nsec);
+ printf(" system time after: %lld.%09u\n",
+ soe->ts[i][2].sec, soe->ts[i][2].nsec);
+ }
+ }
+
+ free(soe);
+ }
+
+ if (getcross) {
+ xts = calloc(1, sizeof(*xts));
+ if (!xts) {
+ perror("calloc");
+ return -1;
+ }
+
+ if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, xts)) {
+ perror("PTP_SYS_OFFSET_PRECISE");
+ } else {
+ puts("system and phc crosstimestamping request okay");
+
+ printf("device time: %lld.%09u\n",
+ xts->device.sec, xts->device.nsec);
+ printf("system time: %lld.%09u\n",
+ xts->sys_realtime.sec, xts->sys_realtime.nsec);
+ printf("monoraw time: %lld.%09u\n",
+ xts->sys_monoraw.sec, xts->sys_monoraw.nsec);
+ }
+
+ free(xts);
+ }
+
+ if (channel >= 0) {
+ if (ioctl(fd, PTP_MASK_CLEAR_ALL)) {
+ perror("PTP_MASK_CLEAR_ALL");
+ } else if (ioctl(fd, PTP_MASK_EN_SINGLE, (unsigned int *)&channel)) {
+ perror("PTP_MASK_EN_SINGLE");
+ } else {
+ printf("Channel %d exclusively enabled. Check on debugfs.\n", channel);
+ printf("Press any key to continue\n.");
+ getchar();
+ }
+ }
+
close(fd);
return 0;
}