Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

LinuxPPS: core support

This patch adds the kernel side of the PPS support currently named
"LinuxPPS".

PPS means "pulse per second" and a PPS source is just a device which
provides a high precision signal each second so that an application can
use it to adjust system clock time.

Common use is the combination of the NTPD as userland program with a GPS
receiver as PPS source to obtain a wallclock-time with sub-millisecond
synchronisation to UTC.

To obtain this goal the userland programs shoud use the PPS API
specification (RFC 2783 - Pulse-Per-Second API for UNIX-like Operating
Systems, Version 1.0) which in part is implemented by this patch. It
provides a set of chars devices, one per PPS source, which can be used to
get the time signal. The RFC's functions can be implemented by accessing
to these char devices.

Signed-off-by: Rodolfo Giometti <giometti@linux.it>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Greg KH <greg@kroah.com>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Michael Kerrisk <mtk.manpages@googlemail.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Rodolfo Giometti and committed by
Linus Torvalds
eae9d2ba 8820f27a

+1249
+73
Documentation/ABI/testing/sysfs-pps
··· 1 + What: /sys/class/pps/ 2 + Date: February 2008 3 + Contact: Rodolfo Giometti <giometti@linux.it> 4 + Description: 5 + The /sys/class/pps/ directory will contain files and 6 + directories that will provide a unified interface to 7 + the PPS sources. 8 + 9 + What: /sys/class/pps/ppsX/ 10 + Date: February 2008 11 + Contact: Rodolfo Giometti <giometti@linux.it> 12 + Description: 13 + The /sys/class/pps/ppsX/ directory is related to X-th 14 + PPS source into the system. Each directory will 15 + contain files to manage and control its PPS source. 16 + 17 + What: /sys/class/pps/ppsX/assert 18 + Date: February 2008 19 + Contact: Rodolfo Giometti <giometti@linux.it> 20 + Description: 21 + The /sys/class/pps/ppsX/assert file reports the assert events 22 + and the assert sequence number of the X-th source in the form: 23 + 24 + <secs>.<nsec>#<sequence> 25 + 26 + If the source has no assert events the content of this file 27 + is empty. 28 + 29 + What: /sys/class/pps/ppsX/clear 30 + Date: February 2008 31 + Contact: Rodolfo Giometti <giometti@linux.it> 32 + Description: 33 + The /sys/class/pps/ppsX/clear file reports the clear events 34 + and the clear sequence number of the X-th source in the form: 35 + 36 + <secs>.<nsec>#<sequence> 37 + 38 + If the source has no clear events the content of this file 39 + is empty. 40 + 41 + What: /sys/class/pps/ppsX/mode 42 + Date: February 2008 43 + Contact: Rodolfo Giometti <giometti@linux.it> 44 + Description: 45 + The /sys/class/pps/ppsX/mode file reports the functioning 46 + mode of the X-th source in hexadecimal encoding. 47 + 48 + Please, refer to linux/include/linux/pps.h for further 49 + info. 50 + 51 + What: /sys/class/pps/ppsX/echo 52 + Date: February 2008 53 + Contact: Rodolfo Giometti <giometti@linux.it> 54 + Description: 55 + The /sys/class/pps/ppsX/echo file reports if the X-th does 56 + or does not support an "echo" function. 57 + 58 + What: /sys/class/pps/ppsX/name 59 + Date: February 2008 60 + Contact: Rodolfo Giometti <giometti@linux.it> 61 + Description: 62 + The /sys/class/pps/ppsX/name file reports the name of the 63 + X-th source. 64 + 65 + What: /sys/class/pps/ppsX/path 66 + Date: February 2008 67 + Contact: Rodolfo Giometti <giometti@linux.it> 68 + Description: 69 + The /sys/class/pps/ppsX/path file reports the path name of 70 + the device connected with the X-th source. 71 + 72 + If the source is not connected with any device the content 73 + of this file is empty.
+2
Documentation/ioctl/ioctl-number.txt
··· 149 149 'p' 40-7F linux/nvram.h 150 150 'p' 80-9F user-space parport 151 151 <mailto:tim@cyberelk.net> 152 + 'p' a1-a4 linux/pps.h LinuxPPS 153 + <mailto:giometti@linux.it> 152 154 'q' 00-1F linux/serio.h 153 155 'q' 80-FF Internet PhoneJACK, Internet LineJACK 154 156 <http://www.quicknet.net>
+172
Documentation/pps/pps.txt
··· 1 + 2 + PPS - Pulse Per Second 3 + ---------------------- 4 + 5 + (C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com> 6 + 7 + This program is free software; you can redistribute it and/or modify 8 + it under the terms of the GNU General Public License as published by 9 + the Free Software Foundation; either version 2 of the License, or 10 + (at your option) any later version. 11 + 12 + This program is distributed in the hope that it will be useful, 13 + but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + GNU General Public License for more details. 16 + 17 + 18 + 19 + Overview 20 + -------- 21 + 22 + LinuxPPS provides a programming interface (API) to define in the 23 + system several PPS sources. 24 + 25 + PPS means "pulse per second" and a PPS source is just a device which 26 + provides a high precision signal each second so that an application 27 + can use it to adjust system clock time. 28 + 29 + A PPS source can be connected to a serial port (usually to the Data 30 + Carrier Detect pin) or to a parallel port (ACK-pin) or to a special 31 + CPU's GPIOs (this is the common case in embedded systems) but in each 32 + case when a new pulse arrives the system must apply to it a timestamp 33 + and record it for userland. 34 + 35 + Common use is the combination of the NTPD as userland program, with a 36 + GPS receiver as PPS source, to obtain a wallclock-time with 37 + sub-millisecond synchronisation to UTC. 38 + 39 + 40 + RFC considerations 41 + ------------------ 42 + 43 + While implementing a PPS API as RFC 2783 defines and using an embedded 44 + CPU GPIO-Pin as physical link to the signal, I encountered a deeper 45 + problem: 46 + 47 + At startup it needs a file descriptor as argument for the function 48 + time_pps_create(). 49 + 50 + This implies that the source has a /dev/... entry. This assumption is 51 + ok for the serial and parallel port, where you can do something 52 + useful besides(!) the gathering of timestamps as it is the central 53 + task for a PPS-API. But this assumption does not work for a single 54 + purpose GPIO line. In this case even basic file-related functionality 55 + (like read() and write()) makes no sense at all and should not be a 56 + precondition for the use of a PPS-API. 57 + 58 + The problem can be simply solved if you consider that a PPS source is 59 + not always connected with a GPS data source. 60 + 61 + So your programs should check if the GPS data source (the serial port 62 + for instance) is a PPS source too, and if not they should provide the 63 + possibility to open another device as PPS source. 64 + 65 + In LinuxPPS the PPS sources are simply char devices usually mapped 66 + into files /dev/pps0, /dev/pps1, etc.. 67 + 68 + 69 + Coding example 70 + -------------- 71 + 72 + To register a PPS source into the kernel you should define a struct 73 + pps_source_info_s as follows: 74 + 75 + static struct pps_source_info pps_ktimer_info = { 76 + .name = "ktimer", 77 + .path = "", 78 + .mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \ 79 + PPS_ECHOASSERT | \ 80 + PPS_CANWAIT | PPS_TSFMT_TSPEC, 81 + .echo = pps_ktimer_echo, 82 + .owner = THIS_MODULE, 83 + }; 84 + 85 + and then calling the function pps_register_source() in your 86 + intialization routine as follows: 87 + 88 + source = pps_register_source(&pps_ktimer_info, 89 + PPS_CAPTUREASSERT | PPS_OFFSETASSERT); 90 + 91 + The pps_register_source() prototype is: 92 + 93 + int pps_register_source(struct pps_source_info_s *info, int default_params) 94 + 95 + where "info" is a pointer to a structure that describes a particular 96 + PPS source, "default_params" tells the system what the initial default 97 + parameters for the device should be (it is obvious that these parameters 98 + must be a subset of ones defined in the struct 99 + pps_source_info_s which describe the capabilities of the driver). 100 + 101 + Once you have registered a new PPS source into the system you can 102 + signal an assert event (for example in the interrupt handler routine) 103 + just using: 104 + 105 + pps_event(source, &ts, PPS_CAPTUREASSERT, ptr) 106 + 107 + where "ts" is the event's timestamp. 108 + 109 + The same function may also run the defined echo function 110 + (pps_ktimer_echo(), passing to it the "ptr" pointer) if the user 111 + asked for that... etc.. 112 + 113 + Please see the file drivers/pps/clients/ktimer.c for example code. 114 + 115 + 116 + SYSFS support 117 + ------------- 118 + 119 + If the SYSFS filesystem is enabled in the kernel it provides a new class: 120 + 121 + $ ls /sys/class/pps/ 122 + pps0/ pps1/ pps2/ 123 + 124 + Every directory is the ID of a PPS sources defined in the system and 125 + inside you find several files: 126 + 127 + $ ls /sys/class/pps/pps0/ 128 + assert clear echo mode name path subsystem@ uevent 129 + 130 + Inside each "assert" and "clear" file you can find the timestamp and a 131 + sequence number: 132 + 133 + $ cat /sys/class/pps/pps0/assert 134 + 1170026870.983207967#8 135 + 136 + Where before the "#" is the timestamp in seconds; after it is the 137 + sequence number. Other files are: 138 + 139 + * echo: reports if the PPS source has an echo function or not; 140 + 141 + * mode: reports available PPS functioning modes; 142 + 143 + * name: reports the PPS source's name; 144 + 145 + * path: reports the PPS source's device path, that is the device the 146 + PPS source is connected to (if it exists). 147 + 148 + 149 + Testing the PPS support 150 + ----------------------- 151 + 152 + In order to test the PPS support even without specific hardware you can use 153 + the ktimer driver (see the client subsection in the PPS configuration menu) 154 + and the userland tools provided into Documentaion/pps/ directory. 155 + 156 + Once you have enabled the compilation of ktimer just modprobe it (if 157 + not statically compiled): 158 + 159 + # modprobe ktimer 160 + 161 + and the run ppstest as follow: 162 + 163 + $ ./ppstest /dev/pps0 164 + trying PPS source "/dev/pps1" 165 + found PPS source "/dev/pps1" 166 + ok, found 1 source(s), now start fetching data... 167 + source 0 - assert 1186592699.388832443, sequence: 364 - clear 0.000000000, sequence: 0 168 + source 0 - assert 1186592700.388931295, sequence: 365 - clear 0.000000000, sequence: 0 169 + source 0 - assert 1186592701.389032765, sequence: 366 - clear 0.000000000, sequence: 0 170 + 171 + Please, note that to compile userland programs you need the file timepps.h 172 + (see Documentation/pps/).
+7
MAINTAINERS
··· 4577 4577 F: drivers/net/pppol2tp.c 4578 4578 F: include/linux/if_pppol2tp.h 4579 4579 4580 + PPS SUPPORT 4581 + P: Rodolfo Giometti 4582 + M: giometti@enneenne.com 4583 + W: http://wiki.enneenne.com/index.php/LinuxPPS_support 4584 + L: linuxpps@ml.enneenne.com (subscribers-only) 4585 + S: Maintained 4586 + 4580 4587 PREEMPTIBLE KERNEL 4581 4588 P: Robert Love 4582 4589 M: rml@tech9.net
+2
drivers/Kconfig
··· 52 52 53 53 source "drivers/spi/Kconfig" 54 54 55 + source "drivers/pps/Kconfig" 56 + 55 57 source "drivers/gpio/Kconfig" 56 58 57 59 source "drivers/w1/Kconfig"
+1
drivers/Makefile
··· 72 72 obj-$(CONFIG_I2O) += message/ 73 73 obj-$(CONFIG_RTC_LIB) += rtc/ 74 74 obj-y += i2c/ media/ 75 + obj-$(CONFIG_PPS) += pps/ 75 76 obj-$(CONFIG_W1) += w1/ 76 77 obj-$(CONFIG_POWER_SUPPLY) += power/ 77 78 obj-$(CONFIG_HWMON) += hwmon/
+33
drivers/pps/Kconfig
··· 1 + # 2 + # PPS support configuration 3 + # 4 + 5 + menu "PPS support" 6 + 7 + config PPS 8 + tristate "PPS support" 9 + depends on EXPERIMENTAL 10 + ---help--- 11 + PPS (Pulse Per Second) is a special pulse provided by some GPS 12 + antennae. Userland can use it to get a high-precision time 13 + reference. 14 + 15 + Some antennae's PPS signals are connected with the CD (Carrier 16 + Detect) pin of the serial line they use to communicate with the 17 + host. In this case use the SERIAL_LINE client support. 18 + 19 + Some antennae's PPS signals are connected with some special host 20 + inputs so you have to enable the corresponding client support. 21 + 22 + To compile this driver as a module, choose M here: the module 23 + will be called pps_core.ko. 24 + 25 + config PPS_DEBUG 26 + bool "PPS debugging messages" 27 + depends on PPS 28 + help 29 + Say Y here if you want the PPS support to produce a bunch of debug 30 + messages to the system log. Select this if you are having a 31 + problem with PPS support and want to see more of what is going on. 32 + 33 + endmenu
+8
drivers/pps/Makefile
··· 1 + # 2 + # Makefile for the PPS core. 3 + # 4 + 5 + pps_core-y := pps.o kapi.o sysfs.o 6 + obj-$(CONFIG_PPS) := pps_core.o 7 + 8 + ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
+329
drivers/pps/kapi.c
··· 1 + /* 2 + * kernel API 3 + * 4 + * 5 + * Copyright (C) 2005-2009 Rodolfo Giometti <giometti@linux.it> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 + */ 21 + 22 + 23 + #include <linux/kernel.h> 24 + #include <linux/module.h> 25 + #include <linux/init.h> 26 + #include <linux/sched.h> 27 + #include <linux/time.h> 28 + #include <linux/spinlock.h> 29 + #include <linux/idr.h> 30 + #include <linux/fs.h> 31 + #include <linux/pps_kernel.h> 32 + 33 + /* 34 + * Global variables 35 + */ 36 + 37 + DEFINE_SPINLOCK(pps_idr_lock); 38 + DEFINE_IDR(pps_idr); 39 + 40 + /* 41 + * Local functions 42 + */ 43 + 44 + static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset) 45 + { 46 + ts->nsec += offset->nsec; 47 + while (ts->nsec >= NSEC_PER_SEC) { 48 + ts->nsec -= NSEC_PER_SEC; 49 + ts->sec++; 50 + } 51 + while (ts->nsec < 0) { 52 + ts->nsec += NSEC_PER_SEC; 53 + ts->sec--; 54 + } 55 + ts->sec += offset->sec; 56 + } 57 + 58 + /* 59 + * Exported functions 60 + */ 61 + 62 + /* pps_get_source - find a PPS source 63 + * @source: the PPS source ID. 64 + * 65 + * This function is used to find an already registered PPS source into the 66 + * system. 67 + * 68 + * The function returns NULL if found nothing, otherwise it returns a pointer 69 + * to the PPS source data struct (the refcounter is incremented by 1). 70 + */ 71 + 72 + struct pps_device *pps_get_source(int source) 73 + { 74 + struct pps_device *pps; 75 + unsigned long flags; 76 + 77 + spin_lock_irqsave(&pps_idr_lock, flags); 78 + 79 + pps = idr_find(&pps_idr, source); 80 + if (pps != NULL) 81 + atomic_inc(&pps->usage); 82 + 83 + spin_unlock_irqrestore(&pps_idr_lock, flags); 84 + 85 + return pps; 86 + } 87 + 88 + /* pps_put_source - free the PPS source data 89 + * @pps: a pointer to the PPS source. 90 + * 91 + * This function is used to free a PPS data struct if its refcount is 0. 92 + */ 93 + 94 + void pps_put_source(struct pps_device *pps) 95 + { 96 + unsigned long flags; 97 + 98 + spin_lock_irqsave(&pps_idr_lock, flags); 99 + BUG_ON(atomic_read(&pps->usage) == 0); 100 + 101 + if (!atomic_dec_and_test(&pps->usage)) { 102 + pps = NULL; 103 + goto exit; 104 + } 105 + 106 + /* No more reference to the PPS source. We can safely remove the 107 + * PPS data struct. 108 + */ 109 + idr_remove(&pps_idr, pps->id); 110 + 111 + exit: 112 + spin_unlock_irqrestore(&pps_idr_lock, flags); 113 + kfree(pps); 114 + } 115 + 116 + /* pps_register_source - add a PPS source in the system 117 + * @info: the PPS info struct 118 + * @default_params: the default PPS parameters of the new source 119 + * 120 + * This function is used to add a new PPS source in the system. The new 121 + * source is described by info's fields and it will have, as default PPS 122 + * parameters, the ones specified into default_params. 123 + * 124 + * The function returns, in case of success, the PPS source ID. 125 + */ 126 + 127 + int pps_register_source(struct pps_source_info *info, int default_params) 128 + { 129 + struct pps_device *pps; 130 + int id; 131 + int err; 132 + 133 + /* Sanity checks */ 134 + if ((info->mode & default_params) != default_params) { 135 + printk(KERN_ERR "pps: %s: unsupported default parameters\n", 136 + info->name); 137 + err = -EINVAL; 138 + goto pps_register_source_exit; 139 + } 140 + if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 && 141 + info->echo == NULL) { 142 + printk(KERN_ERR "pps: %s: echo function is not defined\n", 143 + info->name); 144 + err = -EINVAL; 145 + goto pps_register_source_exit; 146 + } 147 + if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { 148 + printk(KERN_ERR "pps: %s: unspecified time format\n", 149 + info->name); 150 + err = -EINVAL; 151 + goto pps_register_source_exit; 152 + } 153 + 154 + /* Allocate memory for the new PPS source struct */ 155 + pps = kzalloc(sizeof(struct pps_device), GFP_KERNEL); 156 + if (pps == NULL) { 157 + err = -ENOMEM; 158 + goto pps_register_source_exit; 159 + } 160 + 161 + /* These initializations must be done before calling idr_get_new() 162 + * in order to avoid reces into pps_event(). 163 + */ 164 + pps->params.api_version = PPS_API_VERS; 165 + pps->params.mode = default_params; 166 + pps->info = *info; 167 + 168 + init_waitqueue_head(&pps->queue); 169 + spin_lock_init(&pps->lock); 170 + atomic_set(&pps->usage, 1); 171 + 172 + /* Get new ID for the new PPS source */ 173 + if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) { 174 + err = -ENOMEM; 175 + goto kfree_pps; 176 + } 177 + 178 + spin_lock_irq(&pps_idr_lock); 179 + 180 + /* Now really allocate the PPS source. 181 + * After idr_get_new() calling the new source will be freely available 182 + * into the kernel. 183 + */ 184 + err = idr_get_new(&pps_idr, pps, &id); 185 + if (err < 0) { 186 + spin_unlock_irq(&pps_idr_lock); 187 + goto kfree_pps; 188 + } 189 + 190 + id = id & MAX_ID_MASK; 191 + if (id >= PPS_MAX_SOURCES) { 192 + spin_unlock_irq(&pps_idr_lock); 193 + 194 + printk(KERN_ERR "pps: %s: too many PPS sources in the system\n", 195 + info->name); 196 + err = -EBUSY; 197 + goto free_idr; 198 + } 199 + pps->id = id; 200 + 201 + spin_unlock_irq(&pps_idr_lock); 202 + 203 + /* Create the char device */ 204 + err = pps_register_cdev(pps); 205 + if (err < 0) { 206 + printk(KERN_ERR "pps: %s: unable to create char device\n", 207 + info->name); 208 + goto free_idr; 209 + } 210 + 211 + pr_info("new PPS source %s at ID %d\n", info->name, id); 212 + 213 + return id; 214 + 215 + free_idr: 216 + spin_lock_irq(&pps_idr_lock); 217 + idr_remove(&pps_idr, id); 218 + spin_unlock_irq(&pps_idr_lock); 219 + 220 + kfree_pps: 221 + kfree(pps); 222 + 223 + pps_register_source_exit: 224 + printk(KERN_ERR "pps: %s: unable to register source\n", info->name); 225 + 226 + return err; 227 + } 228 + EXPORT_SYMBOL(pps_register_source); 229 + 230 + /* pps_unregister_source - remove a PPS source from the system 231 + * @source: the PPS source ID 232 + * 233 + * This function is used to remove a previously registered PPS source from 234 + * the system. 235 + */ 236 + 237 + void pps_unregister_source(int source) 238 + { 239 + struct pps_device *pps; 240 + 241 + spin_lock_irq(&pps_idr_lock); 242 + pps = idr_find(&pps_idr, source); 243 + 244 + if (!pps) { 245 + BUG(); 246 + spin_unlock_irq(&pps_idr_lock); 247 + return; 248 + } 249 + spin_unlock_irq(&pps_idr_lock); 250 + 251 + pps_unregister_cdev(pps); 252 + pps_put_source(pps); 253 + } 254 + EXPORT_SYMBOL(pps_unregister_source); 255 + 256 + /* pps_event - register a PPS event into the system 257 + * @source: the PPS source ID 258 + * @ts: the event timestamp 259 + * @event: the event type 260 + * @data: userdef pointer 261 + * 262 + * This function is used by each PPS client in order to register a new 263 + * PPS event into the system (it's usually called inside an IRQ handler). 264 + * 265 + * If an echo function is associated with the PPS source it will be called 266 + * as: 267 + * pps->info.echo(source, event, data); 268 + */ 269 + 270 + void pps_event(int source, struct pps_ktime *ts, int event, void *data) 271 + { 272 + struct pps_device *pps; 273 + unsigned long flags; 274 + 275 + if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { 276 + printk(KERN_ERR "pps: unknown event (%x) for source %d\n", 277 + event, source); 278 + return; 279 + } 280 + 281 + pps = pps_get_source(source); 282 + if (!pps) 283 + return; 284 + 285 + pr_debug("PPS event on source %d at %llu.%06u\n", 286 + pps->id, (unsigned long long) ts->sec, ts->nsec); 287 + 288 + spin_lock_irqsave(&pps->lock, flags); 289 + 290 + /* Must call the echo function? */ 291 + if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) 292 + pps->info.echo(source, event, data); 293 + 294 + /* Check the event */ 295 + pps->current_mode = pps->params.mode; 296 + if (event & PPS_CAPTUREASSERT) { 297 + /* We have to add an offset? */ 298 + if (pps->params.mode & PPS_OFFSETASSERT) 299 + pps_add_offset(ts, &pps->params.assert_off_tu); 300 + 301 + /* Save the time stamp */ 302 + pps->assert_tu = *ts; 303 + pps->assert_sequence++; 304 + pr_debug("capture assert seq #%u for source %d\n", 305 + pps->assert_sequence, source); 306 + } 307 + if (event & PPS_CAPTURECLEAR) { 308 + /* We have to add an offset? */ 309 + if (pps->params.mode & PPS_OFFSETCLEAR) 310 + pps_add_offset(ts, &pps->params.clear_off_tu); 311 + 312 + /* Save the time stamp */ 313 + pps->clear_tu = *ts; 314 + pps->clear_sequence++; 315 + pr_debug("capture clear seq #%u for source %d\n", 316 + pps->clear_sequence, source); 317 + } 318 + 319 + pps->go = ~0; 320 + wake_up_interruptible(&pps->queue); 321 + 322 + kill_fasync(&pps->async_queue, SIGIO, POLL_IN); 323 + 324 + spin_unlock_irqrestore(&pps->lock, flags); 325 + 326 + /* Now we can release the PPS source for (possible) deregistration */ 327 + pps_put_source(pps); 328 + } 329 + EXPORT_SYMBOL(pps_event);
+312
drivers/pps/pps.c
··· 1 + /* 2 + * PPS core file 3 + * 4 + * 5 + * Copyright (C) 2005-2009 Rodolfo Giometti <giometti@linux.it> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 + */ 21 + 22 + 23 + #include <linux/kernel.h> 24 + #include <linux/module.h> 25 + #include <linux/init.h> 26 + #include <linux/sched.h> 27 + #include <linux/uaccess.h> 28 + #include <linux/idr.h> 29 + #include <linux/cdev.h> 30 + #include <linux/poll.h> 31 + #include <linux/pps_kernel.h> 32 + 33 + /* 34 + * Local variables 35 + */ 36 + 37 + static dev_t pps_devt; 38 + static struct class *pps_class; 39 + 40 + /* 41 + * Char device methods 42 + */ 43 + 44 + static unsigned int pps_cdev_poll(struct file *file, poll_table *wait) 45 + { 46 + struct pps_device *pps = file->private_data; 47 + 48 + poll_wait(file, &pps->queue, wait); 49 + 50 + return POLLIN | POLLRDNORM; 51 + } 52 + 53 + static int pps_cdev_fasync(int fd, struct file *file, int on) 54 + { 55 + struct pps_device *pps = file->private_data; 56 + return fasync_helper(fd, file, on, &pps->async_queue); 57 + } 58 + 59 + static long pps_cdev_ioctl(struct file *file, 60 + unsigned int cmd, unsigned long arg) 61 + { 62 + struct pps_device *pps = file->private_data; 63 + struct pps_kparams params; 64 + struct pps_fdata fdata; 65 + unsigned long ticks; 66 + void __user *uarg = (void __user *) arg; 67 + int __user *iuarg = (int __user *) arg; 68 + int err; 69 + 70 + switch (cmd) { 71 + case PPS_GETPARAMS: 72 + pr_debug("PPS_GETPARAMS: source %d\n", pps->id); 73 + 74 + /* Return current parameters */ 75 + err = copy_to_user(uarg, &pps->params, 76 + sizeof(struct pps_kparams)); 77 + if (err) 78 + return -EFAULT; 79 + 80 + break; 81 + 82 + case PPS_SETPARAMS: 83 + pr_debug("PPS_SETPARAMS: source %d\n", pps->id); 84 + 85 + /* Check the capabilities */ 86 + if (!capable(CAP_SYS_TIME)) 87 + return -EPERM; 88 + 89 + err = copy_from_user(&params, uarg, sizeof(struct pps_kparams)); 90 + if (err) 91 + return -EFAULT; 92 + if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) { 93 + pr_debug("capture mode unspecified (%x)\n", 94 + params.mode); 95 + return -EINVAL; 96 + } 97 + 98 + /* Check for supported capabilities */ 99 + if ((params.mode & ~pps->info.mode) != 0) { 100 + pr_debug("unsupported capabilities (%x)\n", 101 + params.mode); 102 + return -EINVAL; 103 + } 104 + 105 + spin_lock_irq(&pps->lock); 106 + 107 + /* Save the new parameters */ 108 + pps->params = params; 109 + 110 + /* Restore the read only parameters */ 111 + if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { 112 + /* section 3.3 of RFC 2783 interpreted */ 113 + pr_debug("time format unspecified (%x)\n", 114 + params.mode); 115 + pps->params.mode |= PPS_TSFMT_TSPEC; 116 + } 117 + if (pps->info.mode & PPS_CANWAIT) 118 + pps->params.mode |= PPS_CANWAIT; 119 + pps->params.api_version = PPS_API_VERS; 120 + 121 + spin_unlock_irq(&pps->lock); 122 + 123 + break; 124 + 125 + case PPS_GETCAP: 126 + pr_debug("PPS_GETCAP: source %d\n", pps->id); 127 + 128 + err = put_user(pps->info.mode, iuarg); 129 + if (err) 130 + return -EFAULT; 131 + 132 + break; 133 + 134 + case PPS_FETCH: 135 + pr_debug("PPS_FETCH: source %d\n", pps->id); 136 + 137 + err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata)); 138 + if (err) 139 + return -EFAULT; 140 + 141 + pps->go = 0; 142 + 143 + /* Manage the timeout */ 144 + if (fdata.timeout.flags & PPS_TIME_INVALID) 145 + err = wait_event_interruptible(pps->queue, pps->go); 146 + else { 147 + pr_debug("timeout %lld.%09d\n", 148 + (long long) fdata.timeout.sec, 149 + fdata.timeout.nsec); 150 + ticks = fdata.timeout.sec * HZ; 151 + ticks += fdata.timeout.nsec / (NSEC_PER_SEC / HZ); 152 + 153 + if (ticks != 0) { 154 + err = wait_event_interruptible_timeout( 155 + pps->queue, pps->go, ticks); 156 + if (err == 0) 157 + return -ETIMEDOUT; 158 + } 159 + } 160 + 161 + /* Check for pending signals */ 162 + if (err == -ERESTARTSYS) { 163 + pr_debug("pending signal caught\n"); 164 + return -EINTR; 165 + } 166 + 167 + /* Return the fetched timestamp */ 168 + spin_lock_irq(&pps->lock); 169 + 170 + fdata.info.assert_sequence = pps->assert_sequence; 171 + fdata.info.clear_sequence = pps->clear_sequence; 172 + fdata.info.assert_tu = pps->assert_tu; 173 + fdata.info.clear_tu = pps->clear_tu; 174 + fdata.info.current_mode = pps->current_mode; 175 + 176 + spin_unlock_irq(&pps->lock); 177 + 178 + err = copy_to_user(uarg, &fdata, sizeof(struct pps_fdata)); 179 + if (err) 180 + return -EFAULT; 181 + 182 + break; 183 + 184 + default: 185 + return -ENOTTY; 186 + break; 187 + } 188 + 189 + return 0; 190 + } 191 + 192 + static int pps_cdev_open(struct inode *inode, struct file *file) 193 + { 194 + struct pps_device *pps = container_of(inode->i_cdev, 195 + struct pps_device, cdev); 196 + int found; 197 + 198 + found = pps_get_source(pps->id) != 0; 199 + if (!found) 200 + return -ENODEV; 201 + 202 + file->private_data = pps; 203 + 204 + return 0; 205 + } 206 + 207 + static int pps_cdev_release(struct inode *inode, struct file *file) 208 + { 209 + struct pps_device *pps = file->private_data; 210 + 211 + /* Free the PPS source and wake up (possible) deregistration */ 212 + pps_put_source(pps); 213 + 214 + return 0; 215 + } 216 + 217 + /* 218 + * Char device stuff 219 + */ 220 + 221 + static const struct file_operations pps_cdev_fops = { 222 + .owner = THIS_MODULE, 223 + .llseek = no_llseek, 224 + .poll = pps_cdev_poll, 225 + .fasync = pps_cdev_fasync, 226 + .unlocked_ioctl = pps_cdev_ioctl, 227 + .open = pps_cdev_open, 228 + .release = pps_cdev_release, 229 + }; 230 + 231 + int pps_register_cdev(struct pps_device *pps) 232 + { 233 + int err; 234 + 235 + pps->devno = MKDEV(MAJOR(pps_devt), pps->id); 236 + cdev_init(&pps->cdev, &pps_cdev_fops); 237 + pps->cdev.owner = pps->info.owner; 238 + 239 + err = cdev_add(&pps->cdev, pps->devno, 1); 240 + if (err) { 241 + printk(KERN_ERR "pps: %s: failed to add char device %d:%d\n", 242 + pps->info.name, MAJOR(pps_devt), pps->id); 243 + return err; 244 + } 245 + pps->dev = device_create(pps_class, pps->info.dev, pps->devno, NULL, 246 + "pps%d", pps->id); 247 + if (err) 248 + goto del_cdev; 249 + dev_set_drvdata(pps->dev, pps); 250 + 251 + pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, 252 + MAJOR(pps_devt), pps->id); 253 + 254 + return 0; 255 + 256 + del_cdev: 257 + cdev_del(&pps->cdev); 258 + 259 + return err; 260 + } 261 + 262 + void pps_unregister_cdev(struct pps_device *pps) 263 + { 264 + device_destroy(pps_class, pps->devno); 265 + cdev_del(&pps->cdev); 266 + } 267 + 268 + /* 269 + * Module stuff 270 + */ 271 + 272 + static void __exit pps_exit(void) 273 + { 274 + class_destroy(pps_class); 275 + unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES); 276 + } 277 + 278 + static int __init pps_init(void) 279 + { 280 + int err; 281 + 282 + pps_class = class_create(THIS_MODULE, "pps"); 283 + if (!pps_class) { 284 + printk(KERN_ERR "pps: failed to allocate class\n"); 285 + return -ENOMEM; 286 + } 287 + pps_class->dev_attrs = pps_attrs; 288 + 289 + err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps"); 290 + if (err < 0) { 291 + printk(KERN_ERR "pps: failed to allocate char device region\n"); 292 + goto remove_class; 293 + } 294 + 295 + pr_info("LinuxPPS API ver. %d registered\n", PPS_API_VERS); 296 + pr_info("Software ver. %s - Copyright 2005-2007 Rodolfo Giometti " 297 + "<giometti@linux.it>\n", PPS_VERSION); 298 + 299 + return 0; 300 + 301 + remove_class: 302 + class_destroy(pps_class); 303 + 304 + return err; 305 + } 306 + 307 + subsys_initcall(pps_init); 308 + module_exit(pps_exit); 309 + 310 + MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); 311 + MODULE_DESCRIPTION("LinuxPPS support (RFC 2783) - ver. " PPS_VERSION); 312 + MODULE_LICENSE("GPL");
+98
drivers/pps/sysfs.c
··· 1 + /* 2 + * PPS sysfs support 3 + * 4 + * 5 + * Copyright (C) 2007-2009 Rodolfo Giometti <giometti@linux.it> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 + */ 21 + 22 + 23 + #include <linux/device.h> 24 + #include <linux/module.h> 25 + #include <linux/string.h> 26 + #include <linux/pps_kernel.h> 27 + 28 + /* 29 + * Attribute functions 30 + */ 31 + 32 + static ssize_t pps_show_assert(struct device *dev, 33 + struct device_attribute *attr, char *buf) 34 + { 35 + struct pps_device *pps = dev_get_drvdata(dev); 36 + 37 + if (!(pps->info.mode & PPS_CAPTUREASSERT)) 38 + return 0; 39 + 40 + return sprintf(buf, "%lld.%09d#%d\n", 41 + (long long) pps->assert_tu.sec, pps->assert_tu.nsec, 42 + pps->assert_sequence); 43 + } 44 + 45 + static ssize_t pps_show_clear(struct device *dev, 46 + struct device_attribute *attr, char *buf) 47 + { 48 + struct pps_device *pps = dev_get_drvdata(dev); 49 + 50 + if (!(pps->info.mode & PPS_CAPTURECLEAR)) 51 + return 0; 52 + 53 + return sprintf(buf, "%lld.%09d#%d\n", 54 + (long long) pps->clear_tu.sec, pps->clear_tu.nsec, 55 + pps->clear_sequence); 56 + } 57 + 58 + static ssize_t pps_show_mode(struct device *dev, 59 + struct device_attribute *attr, char *buf) 60 + { 61 + struct pps_device *pps = dev_get_drvdata(dev); 62 + 63 + return sprintf(buf, "%4x\n", pps->info.mode); 64 + } 65 + 66 + static ssize_t pps_show_echo(struct device *dev, 67 + struct device_attribute *attr, char *buf) 68 + { 69 + struct pps_device *pps = dev_get_drvdata(dev); 70 + 71 + return sprintf(buf, "%d\n", !!pps->info.echo); 72 + } 73 + 74 + static ssize_t pps_show_name(struct device *dev, 75 + struct device_attribute *attr, char *buf) 76 + { 77 + struct pps_device *pps = dev_get_drvdata(dev); 78 + 79 + return sprintf(buf, "%s\n", pps->info.name); 80 + } 81 + 82 + static ssize_t pps_show_path(struct device *dev, 83 + struct device_attribute *attr, char *buf) 84 + { 85 + struct pps_device *pps = dev_get_drvdata(dev); 86 + 87 + return sprintf(buf, "%s\n", pps->info.path); 88 + } 89 + 90 + struct device_attribute pps_attrs[] = { 91 + __ATTR(assert, S_IRUGO, pps_show_assert, NULL), 92 + __ATTR(clear, S_IRUGO, pps_show_clear, NULL), 93 + __ATTR(mode, S_IRUGO, pps_show_mode, NULL), 94 + __ATTR(echo, S_IRUGO, pps_show_echo, NULL), 95 + __ATTR(name, S_IRUGO, pps_show_name, NULL), 96 + __ATTR(path, S_IRUGO, pps_show_path, NULL), 97 + __ATTR_NULL, 98 + };
+1
include/linux/Kbuild
··· 308 308 unifdef-y += poll.h 309 309 unifdef-y += ppp_defs.h 310 310 unifdef-y += ppp-comp.h 311 + unifdef-y += pps.h 311 312 unifdef-y += ptrace.h 312 313 unifdef-y += quota.h 313 314 unifdef-y += random.h
+122
include/linux/pps.h
··· 1 + /* 2 + * PPS API header 3 + * 4 + * Copyright (C) 2005-2009 Rodolfo Giometti <giometti@linux.it> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 + */ 20 + 21 + 22 + #ifndef _PPS_H_ 23 + #define _PPS_H_ 24 + 25 + #define PPS_VERSION "5.3.6" 26 + #define PPS_MAX_SOURCES 16 /* should be enough... */ 27 + 28 + /* Implementation note: the logical states ``assert'' and ``clear'' 29 + * are implemented in terms of the chip register, i.e. ``assert'' 30 + * means the bit is set. */ 31 + 32 + /* 33 + * 3.2 New data structures 34 + */ 35 + 36 + #define PPS_API_VERS_1 1 37 + #define PPS_API_VERS PPS_API_VERS_1 /* we use API version 1 */ 38 + #define PPS_MAX_NAME_LEN 32 39 + 40 + /* 32-bit vs. 64-bit compatibility. 41 + * 42 + * 0n i386, the alignment of a uint64_t is only 4 bytes, while on most other 43 + * architectures it's 8 bytes. On i386, there will be no padding between the 44 + * two consecutive 'struct pps_ktime' members of struct pps_kinfo and struct 45 + * pps_kparams. But on most platforms there will be padding to ensure correct 46 + * alignment. 47 + * 48 + * The simple fix is probably to add an explicit padding. 49 + * [David Woodhouse] 50 + */ 51 + struct pps_ktime { 52 + __s64 sec; 53 + __s32 nsec; 54 + __u32 flags; 55 + }; 56 + #define PPS_TIME_INVALID (1<<0) /* used to specify timeout==NULL */ 57 + 58 + struct pps_kinfo { 59 + __u32 assert_sequence; /* seq. num. of assert event */ 60 + __u32 clear_sequence; /* seq. num. of clear event */ 61 + struct pps_ktime assert_tu; /* time of assert event */ 62 + struct pps_ktime clear_tu; /* time of clear event */ 63 + int current_mode; /* current mode bits */ 64 + }; 65 + 66 + struct pps_kparams { 67 + int api_version; /* API version # */ 68 + int mode; /* mode bits */ 69 + struct pps_ktime assert_off_tu; /* offset compensation for assert */ 70 + struct pps_ktime clear_off_tu; /* offset compensation for clear */ 71 + }; 72 + 73 + /* 74 + * 3.3 Mode bit definitions 75 + */ 76 + 77 + /* Device/implementation parameters */ 78 + #define PPS_CAPTUREASSERT 0x01 /* capture assert events */ 79 + #define PPS_CAPTURECLEAR 0x02 /* capture clear events */ 80 + #define PPS_CAPTUREBOTH 0x03 /* capture assert and clear events */ 81 + 82 + #define PPS_OFFSETASSERT 0x10 /* apply compensation for assert ev. */ 83 + #define PPS_OFFSETCLEAR 0x20 /* apply compensation for clear ev. */ 84 + 85 + #define PPS_CANWAIT 0x100 /* can we wait for an event? */ 86 + #define PPS_CANPOLL 0x200 /* bit reserved for future use */ 87 + 88 + /* Kernel actions */ 89 + #define PPS_ECHOASSERT 0x40 /* feed back assert event to output */ 90 + #define PPS_ECHOCLEAR 0x80 /* feed back clear event to output */ 91 + 92 + /* Timestamp formats */ 93 + #define PPS_TSFMT_TSPEC 0x1000 /* select timespec format */ 94 + #define PPS_TSFMT_NTPFP 0x2000 /* select NTP format */ 95 + 96 + /* 97 + * 3.4.4 New functions: disciplining the kernel timebase 98 + */ 99 + 100 + /* Kernel consumers */ 101 + #define PPS_KC_HARDPPS 0 /* hardpps() (or equivalent) */ 102 + #define PPS_KC_HARDPPS_PLL 1 /* hardpps() constrained to 103 + use a phase-locked loop */ 104 + #define PPS_KC_HARDPPS_FLL 2 /* hardpps() constrained to 105 + use a frequency-locked loop */ 106 + /* 107 + * Here begins the implementation-specific part! 108 + */ 109 + 110 + struct pps_fdata { 111 + struct pps_kinfo info; 112 + struct pps_ktime timeout; 113 + }; 114 + 115 + #include <linux/ioctl.h> 116 + 117 + #define PPS_GETPARAMS _IOR('p', 0xa1, struct pps_kparams *) 118 + #define PPS_SETPARAMS _IOW('p', 0xa2, struct pps_kparams *) 119 + #define PPS_GETCAP _IOR('p', 0xa3, int *) 120 + #define PPS_FETCH _IOWR('p', 0xa4, struct pps_fdata *) 121 + 122 + #endif /* _PPS_H_ */
+89
include/linux/pps_kernel.h
··· 1 + /* 2 + * PPS API kernel header 3 + * 4 + * Copyright (C) 2009 Rodolfo Giometti <giometti@linux.it> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 + */ 20 + 21 + #include <linux/pps.h> 22 + 23 + #include <linux/cdev.h> 24 + #include <linux/device.h> 25 + #include <linux/time.h> 26 + 27 + /* 28 + * Global defines 29 + */ 30 + 31 + /* The specific PPS source info */ 32 + struct pps_source_info { 33 + char name[PPS_MAX_NAME_LEN]; /* simbolic name */ 34 + char path[PPS_MAX_NAME_LEN]; /* path of connected device */ 35 + int mode; /* PPS's allowed mode */ 36 + 37 + void (*echo)(int source, int event, void *data); /* PPS echo function */ 38 + 39 + struct module *owner; 40 + struct device *dev; 41 + }; 42 + 43 + /* The main struct */ 44 + struct pps_device { 45 + struct pps_source_info info; /* PSS source info */ 46 + 47 + struct pps_kparams params; /* PPS's current params */ 48 + 49 + __u32 assert_sequence; /* PPS' assert event seq # */ 50 + __u32 clear_sequence; /* PPS' clear event seq # */ 51 + struct pps_ktime assert_tu; 52 + struct pps_ktime clear_tu; 53 + int current_mode; /* PPS mode at event time */ 54 + 55 + int go; /* PPS event is arrived? */ 56 + wait_queue_head_t queue; /* PPS event queue */ 57 + 58 + unsigned int id; /* PPS source unique ID */ 59 + struct cdev cdev; 60 + struct device *dev; 61 + int devno; 62 + struct fasync_struct *async_queue; /* fasync method */ 63 + spinlock_t lock; 64 + 65 + atomic_t usage; /* usage count */ 66 + }; 67 + 68 + /* 69 + * Global variables 70 + */ 71 + 72 + extern spinlock_t pps_idr_lock; 73 + extern struct idr pps_idr; 74 + extern struct timespec pps_irq_ts[]; 75 + 76 + extern struct device_attribute pps_attrs[]; 77 + 78 + /* 79 + * Exported functions 80 + */ 81 + 82 + struct pps_device *pps_get_source(int source); 83 + extern void pps_put_source(struct pps_device *pps); 84 + extern int pps_register_source(struct pps_source_info *info, 85 + int default_params); 86 + extern void pps_unregister_source(int source); 87 + extern int pps_register_cdev(struct pps_device *pps); 88 + extern void pps_unregister_cdev(struct pps_device *pps); 89 + extern void pps_event(int source, struct pps_ktime *ts, int event, void *data);