[RFC PATCH 3/3] pps: Timestamp pps events per PPS_SETCLOCK clock
From: Gerik Kubiak
Date: Sat Jun 27 2026 - 16:54:59 EST
Implements the PPS_SETCLOCK ioctl to allow userspace to set the clock
used to timestamp PPS event.
Userspace passes the clock in a pps_kclock_source structure through the
PPS_SETCLOCK ioctl. The PPS subsystem will store this clock and future
pps events will be timestamped with this clock.
The clock source is initialiaized to REALTIME to keep the existing PPS
behavior if this ioctl is not used.
Signed-off-by: Gerik Kubiak <gerikkub@xxxxxxxxx>
---
drivers/pps/kapi.c | 27 ++++++++++++++++++++-------
drivers/pps/pps.c | 22 ++++++++++++++++++++++
include/linux/pps_kernel.h | 1 +
3 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index 1bf0335a1b41..c1af445d3e57 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -94,6 +94,7 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
*/
pps->params.api_version = PPS_API_VERS;
pps->params.mode = default_params;
+ pps->clock_source.clock_id = CLOCK_REALTIME;
pps->info = *info;
/* check for default echo function */
@@ -158,14 +159,26 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
{
unsigned long flags;
int captured = 0;
- struct pps_ktime ts_real = { .sec = 0, .nsec = 0, .flags = 0 };
+ struct pps_ktime ts_ev = { .sec = 0, .nsec = 0, .flags = 0 };
/* check event type */
BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
- dev_dbg(&pps->dev, "PPS event at %ptSp\n", &ts->ts_real);
+ switch (pps->clock_source.clock_id) {
+ case CLOCK_REALTIME:
+ timespec_to_pps_ktime(&ts_ev, ts->ts_real);
+ break;
+ case CLOCK_MONOTONIC_RAW:
+ timespec_to_pps_ktime(&ts_ev, ts->ts_raw);
+ break;
+ case CLOCK_BOOTTIME:
+ timespec_to_pps_ktime(&ts_ev, ts->ts_boot);
+ break;
+ default:
+ WARN_ON_ONCE(true);
+ }
- timespec_to_pps_ktime(&ts_real, ts->ts_real);
+ dev_dbg(&pps->dev, "PPS event at %ptSp\n", &ts_ev);
spin_lock_irqsave(&pps->lock, flags);
@@ -178,11 +191,11 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
if (event & pps->params.mode & PPS_CAPTUREASSERT) {
/* We have to add an offset? */
if (pps->params.mode & PPS_OFFSETASSERT)
- pps_add_offset(&ts_real,
+ pps_add_offset(&ts_ev,
&pps->params.assert_off_tu);
/* Save the time stamp */
- pps->assert_tu = ts_real;
+ pps->assert_tu = ts_ev;
pps->assert_sequence++;
dev_dbg(&pps->dev, "capture assert seq #%u\n",
pps->assert_sequence);
@@ -192,11 +205,11 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
if (event & pps->params.mode & PPS_CAPTURECLEAR) {
/* We have to add an offset? */
if (pps->params.mode & PPS_OFFSETCLEAR)
- pps_add_offset(&ts_real,
+ pps_add_offset(&ts_ev,
&pps->params.clear_off_tu);
/* Save the time stamp */
- pps->clear_tu = ts_real;
+ pps->clear_tu = ts_ev;
pps->clear_sequence++;
dev_dbg(&pps->dev, "capture clear seq #%u\n",
pps->clear_sequence);
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index de1122bb69ea..2349aebeb65e 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -246,6 +246,28 @@ static long pps_cdev_ioctl(struct file *file,
break;
}
+ case PPS_SETCLOCK: {
+ struct pps_kclock_source source_args;
+
+ dev_dbg(&pps->dev, "PPS_SETCLOCK\n");
+
+ if (copy_from_user(&source_args, uarg,
+ sizeof(struct pps_kclock_source)))
+ return -EFAULT;
+
+ switch (source_args.clock_id) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC_RAW:
+ case CLOCK_BOOTTIME:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pps->clock_source = source_args;
+
+ break;
+ }
default:
return -ENOTTY;
}
diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h
index b13cac7fa6b5..2c8367de12e3 100644
--- a/include/linux/pps_kernel.h
+++ b/include/linux/pps_kernel.h
@@ -43,6 +43,7 @@ struct pps_device {
struct pps_source_info info; /* PSS source info */
struct pps_kparams params; /* PPS current params */
+ struct pps_kclock_source clock_source; /* Capture clock id */
__u32 assert_sequence; /* PPS assert event seq # */
__u32 clear_sequence; /* PPS clear event seq # */
--
2.54.0