Added support for opening POSIX clock devices
I have reduced the requirements for the -p option to accept any type of device. With this it should be possible to use ptp4l to syncronize any clock device that implements the kernel POSIX clock interface. [ RC - Initialize struct timex. ] Signed-off-by: Dimitrios Katsaros <patcherwork@gmail.com> Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
d1ce07d5cb
commit
a5da8c4b71
11
clock.c
11
clock.c
|
@ -979,8 +979,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||||
phc_index = -1;
|
phc_index = -1;
|
||||||
} else if (phc_device) {
|
} else if (phc_device) {
|
||||||
if (1 != sscanf(phc_device, "/dev/ptp%d", &phc_index)) {
|
if (1 != sscanf(phc_device, "/dev/ptp%d", &phc_index)) {
|
||||||
pr_err("bad ptp device string");
|
phc_index = -1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
} else if (iface->ts_info.valid) {
|
} else if (iface->ts_info.valid) {
|
||||||
phc_index = iface->ts_info.phc_index;
|
phc_index = iface->ts_info.phc_index;
|
||||||
|
@ -1053,6 +1052,14 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
clockadj_init(c->clkid);
|
clockadj_init(c->clkid);
|
||||||
|
} else if (phc_device) {
|
||||||
|
c->clkid = phc_open(phc_device);
|
||||||
|
if (c->clkid == CLOCK_INVALID) {
|
||||||
|
pr_err("Failed to open %s: %m", phc_device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
max_adj = clockadj_max_freq(c->clkid);
|
||||||
|
clockadj_init(c->clkid);
|
||||||
} else {
|
} else {
|
||||||
c->clkid = CLOCK_REALTIME;
|
c->clkid = CLOCK_REALTIME;
|
||||||
c->utc_timescale = 1;
|
c->utc_timescale = 1;
|
||||||
|
|
43
clockadj.c
43
clockadj.c
|
@ -103,6 +103,30 @@ void clockadj_step(clockid_t clkid, int64_t step)
|
||||||
pr_err("failed to step clock: %m");
|
pr_err("failed to step clock: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int clockadj_max_freq(clockid_t clkid)
|
||||||
|
{
|
||||||
|
int f = 0;
|
||||||
|
struct timex tx;
|
||||||
|
|
||||||
|
memset(&tx, 0, sizeof(tx));
|
||||||
|
if (clock_adjtime(clkid, &tx) < 0)
|
||||||
|
pr_err("failed to read out the clock maximum adjustment: %m");
|
||||||
|
else
|
||||||
|
f = tx.tolerance / 65.536;
|
||||||
|
if (!f)
|
||||||
|
f = 500000;
|
||||||
|
|
||||||
|
/* The kernel allows the tick length to be adjusted up to 10%. But use
|
||||||
|
* it only if the overall frequency of the clock can be adjusted
|
||||||
|
* continuously with the tick and freq fields (i.e. hz <= 1000).
|
||||||
|
*/
|
||||||
|
if (clkid == CLOCK_REALTIME && (realtime_nominal_tick && 2 * f >=
|
||||||
|
1000 * realtime_hz))
|
||||||
|
f = realtime_nominal_tick / 10 * 1000 * realtime_hz;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
void sysclk_set_leap(int leap)
|
void sysclk_set_leap(int leap)
|
||||||
{
|
{
|
||||||
clockid_t clkid = CLOCK_REALTIME;
|
clockid_t clkid = CLOCK_REALTIME;
|
||||||
|
@ -142,24 +166,7 @@ void sysclk_set_tai_offset(int offset)
|
||||||
|
|
||||||
int sysclk_max_freq(void)
|
int sysclk_max_freq(void)
|
||||||
{
|
{
|
||||||
clockid_t clkid = CLOCK_REALTIME;
|
return clockadj_max_freq(CLOCK_REALTIME);
|
||||||
int f = 0;
|
|
||||||
struct timex tx;
|
|
||||||
memset(&tx, 0, sizeof(tx));
|
|
||||||
if (clock_adjtime(clkid, &tx) < 0)
|
|
||||||
pr_err("failed to read out the clock maximum adjustment: %m");
|
|
||||||
else
|
|
||||||
f = tx.tolerance / 65.536;
|
|
||||||
if (!f)
|
|
||||||
f = 500000;
|
|
||||||
|
|
||||||
/* The kernel allows the tick length to be adjusted up to 10%. But use
|
|
||||||
it only if the overall frequency of the clock can be adjusted
|
|
||||||
continuously with the tick and freq fields (i.e. hz <= 1000). */
|
|
||||||
if (realtime_nominal_tick && 2 * f >= 1000 * realtime_hz)
|
|
||||||
f = realtime_nominal_tick / 10 * 1000 * realtime_hz;
|
|
||||||
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sysclk_set_sync(void)
|
void sysclk_set_sync(void)
|
||||||
|
|
|
@ -50,6 +50,12 @@ double clockadj_get_freq(clockid_t clkid);
|
||||||
*/
|
*/
|
||||||
void clockadj_step(clockid_t clkid, int64_t step);
|
void clockadj_step(clockid_t clkid, int64_t step);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read maximum frequency adjustment of the target clock.
|
||||||
|
* @return The maximum frequency adjustment in parts per billion (ppb).
|
||||||
|
*/
|
||||||
|
int clockadj_max_freq(clockid_t clkid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the system clock to insert/delete leap second at midnight.
|
* Set the system clock to insert/delete leap second at midnight.
|
||||||
* @param leap +1 to insert leap second, -1 to delete leap second,
|
* @param leap +1 to insert leap second, -1 to delete leap second,
|
||||||
|
|
25
phc.c
25
phc.c
|
@ -16,11 +16,12 @@
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <linux/ptp_clock.h>
|
#include <linux/ptp_clock.h>
|
||||||
|
@ -38,18 +39,26 @@
|
||||||
|
|
||||||
static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);
|
static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);
|
||||||
|
|
||||||
clockid_t phc_open(char *phc)
|
clockid_t phc_open(const char *phc)
|
||||||
{
|
{
|
||||||
clockid_t clkid;
|
clockid_t clkid;
|
||||||
struct ptp_clock_caps caps;
|
struct timespec ts;
|
||||||
int fd = open(phc, O_RDWR);
|
struct timex tx;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memset(&tx, 0, sizeof(tx));
|
||||||
|
|
||||||
|
fd = open(phc, O_RDWR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return CLOCK_INVALID;
|
return CLOCK_INVALID;
|
||||||
|
|
||||||
clkid = FD_TO_CLOCKID(fd);
|
clkid = FD_TO_CLOCKID(fd);
|
||||||
/* check if clkid is valid */
|
/* check if clkid is valid */
|
||||||
if (phc_get_caps(clkid, &caps)) {
|
if (clock_gettime(clkid, &ts)) {
|
||||||
|
close(fd);
|
||||||
|
return CLOCK_INVALID;
|
||||||
|
}
|
||||||
|
if (clock_adjtime(clkid, &tx)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return CLOCK_INVALID;
|
return CLOCK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
2
phc.h
2
phc.h
|
@ -28,7 +28,7 @@
|
||||||
*
|
*
|
||||||
* @return A valid clock ID on success, CLOCK_INVALID otherwise.
|
* @return A valid clock ID on success, CLOCK_INVALID otherwise.
|
||||||
*/
|
*/
|
||||||
clockid_t phc_open(char *phc);
|
clockid_t phc_open(const char *phc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes a PTP hardware clock device.
|
* Closes a PTP hardware clock device.
|
||||||
|
|
2
ptp4l.c
2
ptp4l.c
|
@ -56,7 +56,7 @@ static void usage(char *progname)
|
||||||
" -f [file] read configuration from 'file'\n"
|
" -f [file] read configuration from 'file'\n"
|
||||||
" -i [dev] interface device to use, for example 'eth0'\n"
|
" -i [dev] interface device to use, for example 'eth0'\n"
|
||||||
" (may be specified multiple times)\n"
|
" (may be specified multiple times)\n"
|
||||||
" -p [dev] PTP hardware clock device to use, default auto\n"
|
" -p [dev] Clock device to use, default auto\n"
|
||||||
" (ignored for SOFTWARE/LEGACY HW time stamping)\n"
|
" (ignored for SOFTWARE/LEGACY HW time stamping)\n"
|
||||||
" -s slave only mode (overrides configuration file)\n"
|
" -s slave only mode (overrides configuration file)\n"
|
||||||
" -t transparent clock\n"
|
" -t transparent clock\n"
|
||||||
|
|
Loading…
Reference in New Issue