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
Vladimir Oltean 2020-08-01 14:28:50 +03:00
parent 3045a49855
commit d5b3b1e07b
5 changed files with 64 additions and 1 deletions

View File

@ -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)
{
fprintf(stderr,
@ -695,8 +731,15 @@ int main(int argc, char *argv[])
pr_err("poll failed");
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_cleanup(&priv);

View File

@ -38,3 +38,11 @@ int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *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;
}

View File

@ -51,4 +51,6 @@ void ts2phc_master_destroy(struct ts2phc_master *master);
*/
int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *ts);
struct clock *ts2phc_master_get_clock(struct ts2phc_master *m);
#endif

View File

@ -15,6 +15,7 @@
struct ts2phc_master {
void (*destroy)(struct ts2phc_master *ts2phc_master);
int (*getppstime)(struct ts2phc_master *master, struct timespec *ts);
struct clock *(*get_clock)(struct ts2phc_master *m);
};
#endif

View File

@ -83,6 +83,14 @@ static int ts2phc_phc_master_getppstime(struct ts2phc_master *m,
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,
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.getppstime = ts2phc_phc_master_getppstime;
master->master.get_clock = ts2phc_phc_master_get_clock;
master->clock = clock_add(priv, dev);
if (!master->clock) {