1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * pps_gen_parport.c -- kernel parallel port PPS signal generator 4 * 5 * Copyright (C) 2009 Alexander Gordeev <lasaine@lvk.cs.msu.su> 6 */ 7 8 9 /* 10 * TODO: 11 * fix issues when realtime clock is adjusted in a leap 12 */ 13 14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/init.h> 19 #include <linux/time.h> 20 #include <linux/hrtimer.h> 21 #include <linux/parport.h> 22 23 #define DRVDESC "parallel port PPS signal generator" 24 25 #define SIGNAL 0 26 #define NO_SIGNAL PARPORT_CONTROL_STROBE 27 28 /* module parameters */ 29 30 #define SEND_DELAY_MAX 100000 31 32 static unsigned int send_delay = 30000; 33 MODULE_PARM_DESC(delay, 34 "Delay between setting and dropping the signal (ns)"); 35 module_param_named(delay, send_delay, uint, 0); 36 37 38 #define SAFETY_INTERVAL 3000 /* set the hrtimer earlier for safety (ns) */ 39 40 /* internal per port structure */ 41 struct pps_generator_pp { 42 struct pardevice *pardev; /* parport device */ 43 struct hrtimer timer; 44 long port_write_time; /* calibrated port write time (ns) */ 45 }; 46 47 static struct pps_generator_pp device = { 48 .pardev = NULL, 49 }; 50 51 static int attached; 52 53 /* calibrated time between a hrtimer event and the reaction */ 54 static long hrtimer_error = SAFETY_INTERVAL; 55 56 /* the kernel hrtimer event */ 57 static enum hrtimer_restart hrtimer_event(struct hrtimer *timer) 58 { 59 struct timespec64 expire_time, ts1, ts2, ts3, dts; 60 struct pps_generator_pp *dev; 61 struct parport *port; 62 long lim, delta; 63 unsigned long flags; 64 65 /* We have to disable interrupts here. The idea is to prevent 66 * other interrupts on the same processor to introduce random 67 * lags while polling the clock. ktime_get_real_ts64() takes <1us on 68 * most machines while other interrupt handlers can take much 69 * more potentially. 70 * 71 * NB: approx time with blocked interrupts = 72 * send_delay + 3 * SAFETY_INTERVAL 73 */ 74 local_irq_save(flags); 75 76 /* first of all we get the time stamp... */ 77 ktime_get_real_ts64(&ts1); 78 expire_time = ktime_to_timespec64(hrtimer_get_softexpires(timer)); 79 dev = container_of(timer, struct pps_generator_pp, timer); 80 lim = NSEC_PER_SEC - send_delay - dev->port_write_time; 81 82 /* check if we are late */ 83 if (expire_time.tv_sec != ts1.tv_sec || ts1.tv_nsec > lim) { 84 local_irq_restore(flags); 85 pr_err("we are late this time %lld.%09ld\n", 86 (s64)ts1.tv_sec, ts1.tv_nsec); 87 goto done; 88 } 89 90 /* busy loop until the time is right for an assert edge */ 91 do { 92 ktime_get_real_ts64(&ts2); 93 } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); 94 95 /* set the signal */ 96 port = dev->pardev->port; 97 port->ops->write_control(port, SIGNAL); 98 99 /* busy loop until the time is right for a clear edge */ 100 lim = NSEC_PER_SEC - dev->port_write_time; 101 do { 102 ktime_get_real_ts64(&ts2); 103 } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); 104 105 /* unset the signal */ 106 port->ops->write_control(port, NO_SIGNAL); 107 108 ktime_get_real_ts64(&ts3); 109 110 local_irq_restore(flags); 111 112 /* update calibrated port write time */ 113 dts = timespec64_sub(ts3, ts2); 114 dev->port_write_time = 115 (dev->port_write_time + timespec64_to_ns(&dts)) >> 1; 116 117 done: 118 /* update calibrated hrtimer error */ 119 dts = timespec64_sub(ts1, expire_time); 120 delta = timespec64_to_ns(&dts); 121 /* If the new error value is bigger then the old, use the new 122 * value, if not then slowly move towards the new value. This 123 * way it should be safe in bad conditions and efficient in 124 * good conditions. 125 */ 126 if (delta >= hrtimer_error) 127 hrtimer_error = delta; 128 else 129 hrtimer_error = (3 * hrtimer_error + delta) >> 2; 130 131 /* update the hrtimer expire time */ 132 hrtimer_set_expires(timer, 133 ktime_set(expire_time.tv_sec + 1, 134 NSEC_PER_SEC - (send_delay + 135 dev->port_write_time + SAFETY_INTERVAL + 136 2 * hrtimer_error))); 137 138 return HRTIMER_RESTART; 139 } 140 141 /* calibrate port write time */ 142 #define PORT_NTESTS_SHIFT 5 143 static void calibrate_port(struct pps_generator_pp *dev) 144 { 145 struct parport *port = dev->pardev->port; 146 int i; 147 long acc = 0; 148 149 for (i = 0; i < (1 << PORT_NTESTS_SHIFT); i++) { 150 struct timespec64 a, b; 151 unsigned long irq_flags; 152 153 local_irq_save(irq_flags); 154 ktime_get_real_ts64(&a); 155 port->ops->write_control(port, NO_SIGNAL); 156 ktime_get_real_ts64(&b); 157 local_irq_restore(irq_flags); 158 159 b = timespec64_sub(b, a); 160 acc += timespec64_to_ns(&b); 161 } 162 163 dev->port_write_time = acc >> PORT_NTESTS_SHIFT; 164 pr_info("port write takes %ldns\n", dev->port_write_time); 165 } 166 167 static inline ktime_t next_intr_time(struct pps_generator_pp *dev) 168 { 169 struct timespec64 ts; 170 171 ktime_get_real_ts64(&ts); 172 173 return ktime_set(ts.tv_sec + 174 ((ts.tv_nsec > 990 * NSEC_PER_MSEC) ? 1 : 0), 175 NSEC_PER_SEC - (send_delay + 176 dev->port_write_time + 3 * SAFETY_INTERVAL)); 177 } 178 179 static void parport_attach(struct parport *port) 180 { 181 struct pardev_cb pps_cb; 182 183 if (attached) { 184 /* we already have a port */ 185 return; 186 } 187 188 memset(&pps_cb, 0, sizeof(pps_cb)); 189 pps_cb.private = &device; 190 pps_cb.flags = PARPORT_FLAG_EXCL; 191 device.pardev = parport_register_dev_model(port, KBUILD_MODNAME, 192 &pps_cb, 0); 193 if (!device.pardev) { 194 pr_err("couldn't register with %s\n", port->name); 195 return; 196 } 197 198 if (parport_claim_or_block(device.pardev) < 0) { 199 pr_err("couldn't claim %s\n", port->name); 200 goto err_unregister_dev; 201 } 202 203 pr_info("attached to %s\n", port->name); 204 attached = 1; 205 206 calibrate_port(&device); 207 208 hrtimer_init(&device.timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); 209 device.timer.function = hrtimer_event; 210 hrtimer_start(&device.timer, next_intr_time(&device), HRTIMER_MODE_ABS); 211 212 return; 213 214 err_unregister_dev: 215 parport_unregister_device(device.pardev); 216 } 217 218 static void parport_detach(struct parport *port) 219 { 220 if (port->cad != device.pardev) 221 return; /* not our port */ 222 223 hrtimer_cancel(&device.timer); 224 parport_release(device.pardev); 225 parport_unregister_device(device.pardev); 226 } 227 228 static struct parport_driver pps_gen_parport_driver = { 229 .name = KBUILD_MODNAME, 230 .match_port = parport_attach, 231 .detach = parport_detach, 232 .devmodel = true, 233 }; 234 235 /* module staff */ 236 237 static int __init pps_gen_parport_init(void) 238 { 239 int ret; 240 241 pr_info(DRVDESC "\n"); 242 243 if (send_delay > SEND_DELAY_MAX) { 244 pr_err("delay value should be not greater" 245 " then %d\n", SEND_DELAY_MAX); 246 return -EINVAL; 247 } 248 249 ret = parport_register_driver(&pps_gen_parport_driver); 250 if (ret) { 251 pr_err("unable to register with parport\n"); 252 return ret; 253 } 254 255 return 0; 256 } 257 258 static void __exit pps_gen_parport_exit(void) 259 { 260 parport_unregister_driver(&pps_gen_parport_driver); 261 pr_info("hrtimer avg error is %ldns\n", hrtimer_error); 262 } 263 264 module_init(pps_gen_parport_init); 265 module_exit(pps_gen_parport_exit); 266 267 MODULE_AUTHOR("Alexander Gordeev <lasaine@lvk.cs.msu.su>"); 268 MODULE_DESCRIPTION(DRVDESC); 269 MODULE_LICENSE("GPL"); 270