--- zzzz-none-000/linux-3.10.107/Documentation/ptp/testptp.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/Documentation/ptp/testptp.c 2021-02-04 17:41:59.000000000 +0000 @@ -17,8 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define _GNU_SOURCE +#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ #include #include +#include #include #include #include @@ -45,12 +48,14 @@ #define CLOCK_INVALID -1 #endif -/* When glibc offers the syscall, this will go away. */ +/* clock_adjtime is not available in GLIBC < 2.14 */ +#if !__GLIBC_PREREQ(2, 14) #include static int clock_adjtime(clockid_t id, struct timex *tx) { return syscall(__NR_clock_adjtime, id, tx); } +#endif static clockid_t get_clockid(int fd) { @@ -100,6 +105,11 @@ return (long) (ppb * 65.536); } +static int64_t pctns(struct ptp_clock_time *t) +{ + return t->sec * 1000000000LL + t->nsec; +} + static void usage(char *progname) { fprintf(stderr, @@ -112,11 +122,22 @@ " -f val adjust the ptp clock frequency by 'val' ppb\n" " -g get the ptp clock time\n" " -h prints this message\n" + " -i val index for event/trigger\n" + " -k val measure the time offset between system and phc clock\n" + " for 'val' times (Maximum 25)\n" + " -l list the current pin configuration\n" + " -L pin,val configure pin index 'pin' with function 'val'\n" + " the channel index is taken from the '-i' option\n" + " 'val' specifies the auxiliary function:\n" + " 0 - none\n" + " 1 - external time stamp\n" + " 2 - periodic output\n" " -p val enable output with a period of 'val' nanoseconds\n" " -P val enable or disable (val=1|0) the system clock PPS\n" " -s set the ptp clock time from the system time\n" " -S set the system time from the ptp clock time\n" - " -t val shift the ptp clock time by 'val' seconds\n", + " -t val shift the ptp clock time by 'val' seconds\n" + " -T val set the ptp clock time to 'val' seconds\n", progname); } @@ -126,6 +147,7 @@ struct ptp_extts_event event; struct ptp_extts_request extts_request; struct ptp_perout_request perout_request; + struct ptp_pin_desc desc; struct timespec ts; struct timex tx; @@ -133,8 +155,12 @@ struct itimerspec timeout; struct sigevent sigevent; + struct ptp_clock_time *pct; + struct ptp_sys_offset *sysoff; + + char *progname; - int c, cnt, fd; + int i, c, cnt, fd; char *device = DEVICE; clockid_t clkid; @@ -143,15 +169,24 @@ int capabilities = 0; int extts = 0; int gettime = 0; + int index = 0; + int list_pins = 0; int oneshot = 0; + int pct_offset = 0; + int n_samples = 0; int periodic = 0; int perout = -1; + int pin_index = -1, pin_func; int pps = -1; + int seconds = 0; int settime = 0; + int64_t t1, t2, tp; + int64_t interval, offset; + progname = strrchr(argv[0], '/'); progname = progname ? 1+progname : argv[0]; - while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghp:P:sSt:v"))) { + while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:T:v"))) { switch (c) { case 'a': oneshot = atoi(optarg); @@ -174,6 +209,23 @@ case 'g': gettime = 1; break; + case 'i': + index = atoi(optarg); + break; + case 'k': + pct_offset = 1; + n_samples = atoi(optarg); + break; + case 'l': + list_pins = 1; + break; + case 'L': + cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func); + if (cnt != 2) { + usage(progname); + return -1; + } + break; case 'p': perout = atoi(optarg); break; @@ -189,6 +241,10 @@ case 't': adjtime = atoi(optarg); break; + case 'T': + settime = 3; + seconds = atoi(optarg); + break; case 'h': usage(progname); return 0; @@ -220,12 +276,14 @@ " %d programmable alarms\n" " %d external time stamp channels\n" " %d programmable periodic signals\n" - " %d pulse per second\n", + " %d pulse per second\n" + " %d programmable pins\n", caps.max_adj, caps.n_alarm, caps.n_ext_ts, caps.n_per_out, - caps.pps); + caps.pps, + caps.n_pins); } } @@ -279,9 +337,19 @@ } } + if (settime == 3) { + ts.tv_sec = seconds; + ts.tv_nsec = 0; + if (clock_settime(clkid, &ts)) { + perror("clock_settime"); + } else { + puts("set time okay"); + } + } + if (extts) { memset(&extts_request, 0, sizeof(extts_request)); - extts_request.index = 0; + extts_request.index = index; extts_request.flags = PTP_ENABLE_FEATURE; if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) { perror("PTP_EXTTS_REQUEST"); @@ -306,6 +374,24 @@ } } + if (list_pins) { + int n_pins = 0; + if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) { + perror("PTP_CLOCK_GETCAPS"); + } else { + n_pins = caps.n_pins; + } + for (i = 0; i < n_pins; i++) { + desc.index = i; + if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) { + perror("PTP_PIN_GETFUNC"); + break; + } + printf("name %s index %u func %u chan %u\n", + desc.name, desc.index, desc.func, desc.chan); + } + } + if (oneshot) { install_handler(SIGALRM, handle_alarm); /* Create a timer. */ @@ -355,7 +441,7 @@ return -1; } memset(&perout_request, 0, sizeof(perout_request)); - perout_request.index = 0; + perout_request.index = index; perout_request.start.sec = ts.tv_sec + 2; perout_request.start.nsec = 0; perout_request.period.sec = 0; @@ -367,6 +453,18 @@ } } + 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)) { @@ -376,6 +474,47 @@ } } + if (pct_offset) { + if (n_samples <= 0 || n_samples > 25) { + puts("n_samples should be between 1 and 25"); + usage(progname); + return -1; + } + + sysoff = calloc(1, sizeof(*sysoff)); + if (!sysoff) { + perror("calloc"); + return -1; + } + sysoff->n_samples = n_samples; + + if (ioctl(fd, PTP_SYS_OFFSET, sysoff)) + perror("PTP_SYS_OFFSET"); + else + puts("system and phc clock time offset request okay"); + + pct = &sysoff->ts[0]; + for (i = 0; i < sysoff->n_samples; i++) { + t1 = pctns(pct+2*i); + tp = pctns(pct+2*i+1); + t2 = pctns(pct+2*i+2); + interval = t2 - t1; + offset = (t2 + t1) / 2 - tp; + + printf("system time: %lld.%u\n", + (pct+2*i)->sec, (pct+2*i)->nsec); + printf("phc time: %lld.%u\n", + (pct+2*i+1)->sec, (pct+2*i+1)->nsec); + printf("system time: %lld.%u\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", + offset, interval); + } + + free(sysoff); + } + close(fd); return 0; }