ts2phc: allow the PHC PPS master to be synchronized
Now that we are registering a clock even for the PPS master when it supports that (i.e. when it is a PHC), introduce a new API to retrieve its clock in order to add timestamps to it. The PHC master can be synchronized to the extts events of a PHC slave, when in automatic mode. Signed-off-by: Vladimir Oltean <olteanv@gmail.com>master
parent
3045a49855
commit
d5b3b1e07b
45
ts2phc.c
45
ts2phc.c
|
@ -477,6 +477,42 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ts2phc_collect_master_tstamp(struct ts2phc_private *priv)
|
||||||
|
{
|
||||||
|
struct clock *master_clock;
|
||||||
|
struct timespec master_ts;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
master_clock = ts2phc_master_get_clock(priv->master);
|
||||||
|
/*
|
||||||
|
* Master isn't a PHC (it may be a generic or a GPS master),
|
||||||
|
* don't error out, just don't do anything. If it doesn't have a PHC,
|
||||||
|
* there is nothing to synchronize, which is the only point of
|
||||||
|
* collecting its perout timestamp in the first place.
|
||||||
|
*/
|
||||||
|
if (!master_clock)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = ts2phc_master_getppstime(priv->master, &master_ts);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_err("source ts not valid");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As long as the kernel doesn't support a proper API for reporting
|
||||||
|
* a precise perout timestamp, we'll have to use this crude
|
||||||
|
* approximation.
|
||||||
|
*/
|
||||||
|
if (master_ts.tv_nsec > NS_PER_SEC / 2)
|
||||||
|
master_ts.tv_sec++;
|
||||||
|
master_ts.tv_nsec = 0;
|
||||||
|
|
||||||
|
clock_add_tstamp(master_clock, timespec_to_tmv(master_ts));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void usage(char *progname)
|
static void usage(char *progname)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -695,8 +731,15 @@ int main(int argc, char *argv[])
|
||||||
pr_err("poll failed");
|
pr_err("poll failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (err > 0)
|
if (err > 0) {
|
||||||
|
err = ts2phc_collect_master_tstamp(&priv);
|
||||||
|
if (err) {
|
||||||
|
pr_err("failed to collect master tstamp");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ts2phc_synchronize_clocks(&priv, autocfg);
|
ts2phc_synchronize_clocks(&priv, autocfg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ts2phc_cleanup(&priv);
|
ts2phc_cleanup(&priv);
|
||||||
|
|
|
@ -38,3 +38,11 @@ int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *ts)
|
||||||
{
|
{
|
||||||
return master->getppstime(master, ts);
|
return master->getppstime(master, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct clock *ts2phc_master_get_clock(struct ts2phc_master *m)
|
||||||
|
{
|
||||||
|
if (m->get_clock)
|
||||||
|
return m->get_clock(m);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -51,4 +51,6 @@ void ts2phc_master_destroy(struct ts2phc_master *master);
|
||||||
*/
|
*/
|
||||||
int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *ts);
|
int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *ts);
|
||||||
|
|
||||||
|
struct clock *ts2phc_master_get_clock(struct ts2phc_master *m);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
struct ts2phc_master {
|
struct ts2phc_master {
|
||||||
void (*destroy)(struct ts2phc_master *ts2phc_master);
|
void (*destroy)(struct ts2phc_master *ts2phc_master);
|
||||||
int (*getppstime)(struct ts2phc_master *master, struct timespec *ts);
|
int (*getppstime)(struct ts2phc_master *master, struct timespec *ts);
|
||||||
|
struct clock *(*get_clock)(struct ts2phc_master *m);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -83,6 +83,14 @@ static int ts2phc_phc_master_getppstime(struct ts2phc_master *m,
|
||||||
return clock_gettime(master->clock->clkid, ts);
|
return clock_gettime(master->clock->clkid, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct clock *ts2phc_phc_master_get_clock(struct ts2phc_master *m)
|
||||||
|
{
|
||||||
|
struct ts2phc_phc_master *master =
|
||||||
|
container_of(m, struct ts2phc_phc_master, master);
|
||||||
|
|
||||||
|
return master->clock;
|
||||||
|
}
|
||||||
|
|
||||||
struct ts2phc_master *ts2phc_phc_master_create(struct ts2phc_private *priv,
|
struct ts2phc_master *ts2phc_phc_master_create(struct ts2phc_private *priv,
|
||||||
const char *dev)
|
const char *dev)
|
||||||
{
|
{
|
||||||
|
@ -94,6 +102,7 @@ struct ts2phc_master *ts2phc_phc_master_create(struct ts2phc_private *priv,
|
||||||
}
|
}
|
||||||
master->master.destroy = ts2phc_phc_master_destroy;
|
master->master.destroy = ts2phc_phc_master_destroy;
|
||||||
master->master.getppstime = ts2phc_phc_master_getppstime;
|
master->master.getppstime = ts2phc_phc_master_getppstime;
|
||||||
|
master->master.get_clock = ts2phc_phc_master_get_clock;
|
||||||
|
|
||||||
master->clock = clock_add(priv, dev);
|
master->clock = clock_add(priv, dev);
|
||||||
if (!master->clock) {
|
if (!master->clock) {
|
||||||
|
|
Loading…
Reference in New Issue