[LinuxPPS] [PATCH 3/3] pps: add hardpps implementation

Alexander Gordeev lasaine at lvk.cs.msu.su
Thu Oct 1 22:37:03 CEST 2009


This implementation uses adjtimex to adjust clock phase and frequency.
It doesn't yet include any grooming algorithms like median ot
exponential average filter so the clock stability might be lower than
when PLL/FLL is used. However it also means that the clock sticks to PPS
signal quite good.

Signed-off-by: Alexander Gordeev <lasaine at lvk.cs.msu.su>
---
 drivers/pps/kapi.c |   26 ++++++++++++++++++++++++++
 kernel/time/ntp.c  |    2 ++
 2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index 8e0bcec..4d382fd 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -282,6 +282,32 @@ EXPORT_SYMBOL(pps_unregister_source);
  */
 void hardpps(const struct timespec *p_ts, long nsec)
 {
+	long offset = p_ts->tv_nsec;
+	struct timex txc;
+
+	/* first, correct the phase */
+	txc.modes = ADJ_ADJTIME | ADJ_OFFSET_SINGLESHOT;
+	txc.freq = 0;
+
+	if (offset > NSEC_PER_SEC - 128L * NSEC_PER_MSEC)
+		offset -= NSEC_PER_SEC;
+	offset /= NSEC_PER_USEC;
+	txc.offset = -offset;
+	if (offset < 128L * USEC_PER_MSEC)
+		if (do_adjtimex(&txc) < 0)
+			pr_err("hardpps: phase correction failed\n");
+
+	/* then correct the frequency */
+	if ((nsec < 900 * NSEC_PER_MSEC || nsec > 1100 * NSEC_PER_MSEC) && nsec != 0) {
+		pr_err("hardpps: nsec out of range\n");
+		return;
+	}
+
+	txc.modes = ADJ_FREQUENCY;
+	txc.offset = 0;
+	txc.freq = div_s64(((s64)(NSEC_PER_SEC - nsec)) << 16, 1000);
+	if (do_adjtimex(&txc) < 0)
+		pr_err("hardpps: frequency correction failed\n");
 }
 
 /* pps_event - register a PPS event into the system
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 7fc6437..d5a27d8 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -14,6 +14,7 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 
 /*
  * NTP timekeeping variables:
@@ -538,6 +539,7 @@ int do_adjtimex(struct timex *txc)
 
 	return result;
 }
+EXPORT_SYMBOL(do_adjtimex);
 
 static int __init ntp_tick_adj_setup(char *str)
 {
-- 
1.6.3.3




More information about the LinuxPPS mailing list