phc2sys: enable PPS output from PHC

PPS output from a PHC has to be enabled by PTP_ENABLE_PPS ioctl. Call
the ioctl when both PHC device and PPS device are specified and PPS is
supported by the PHC.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
master
Jiri Benc 2013-04-19 15:28:31 +02:00 committed by Richard Cochran
parent f0d21dd80f
commit 4004273cd8
3 changed files with 46 additions and 6 deletions

25
phc.c
View File

@ -51,15 +51,23 @@ void phc_close(clockid_t clkid)
close(CLOCKID_TO_FD(clkid)); close(CLOCKID_TO_FD(clkid));
} }
static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps)
{
int fd = CLOCKID_TO_FD(clkid), err;
err = ioctl(fd, PTP_CLOCK_GETCAPS, caps);
if (err)
perror("PTP_CLOCK_GETCAPS");
return err;
}
int phc_max_adj(clockid_t clkid) int phc_max_adj(clockid_t clkid)
{ {
int fd = CLOCKID_TO_FD(clkid), max; int max;
struct ptp_clock_caps caps; struct ptp_clock_caps caps;
if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) { if (phc_get_caps(clkid, &caps))
perror("PTP_CLOCK_GETCAPS");
return 0; return 0;
}
max = caps.max_adj; max = caps.max_adj;
@ -68,3 +76,12 @@ int phc_max_adj(clockid_t clkid)
return max; return max;
} }
int phc_has_pps(clockid_t clkid)
{
struct ptp_clock_caps caps;
if (phc_get_caps(clkid, &caps))
return 0;
return caps.pps;
}

10
phc.h
View File

@ -46,4 +46,14 @@ void phc_close(clockid_t clkid);
*/ */
int phc_max_adj(clockid_t clkid); int phc_max_adj(clockid_t clkid);
/**
* Checks whether the given PTP hardware clock device supports PPS output.
*
* @param clkid A clock ID obtained using phc_open().
*
* @return Zero if PPS output is not supported by the clock, non-zero
* otherwise.
*/
int phc_has_pps(clockid_t clkid);
#endif #endif

View File

@ -206,6 +206,16 @@ static void update_clock(struct clock *clock,
} }
} }
static void enable_pps_output(clockid_t src)
{
int enable = 1;
if (!phc_has_pps(src))
return;
if (ioctl(CLOCKID_TO_FD(src), PTP_ENABLE_PPS, enable) < 0)
pr_warning("failed to enable PPS output");
}
static int read_pps(int fd, int64_t *offset, uint64_t *ts) static int read_pps(int fd, int64_t *offset, uint64_t *ts)
{ {
struct pps_fdata pfd; struct pps_fdata pfd;
@ -236,9 +246,12 @@ static int do_pps_loop(struct clock *clock, int fd,
clock->source_label = "pps"; clock->source_label = "pps";
if (src == CLOCK_INVALID) {
/* The sync offset can't be applied with PPS alone. */ /* The sync offset can't be applied with PPS alone. */
if (src == CLOCK_INVALID)
clock->sync_offset_direction = 0; clock->sync_offset_direction = 0;
} else {
enable_pps_output(src);
}
while (1) { while (1) {
if (!read_pps(fd, &pps_offset, &pps_ts)) { if (!read_pps(fd, &pps_offset, &pps_ts)) {