1 diff --git a/Documentation/pps/Makefile b/Documentation/pps/Makefile
5 +++ b/Documentation/pps/Makefile
7 +TARGETS = ppstest ppsctl
9 +CFLAGS += -Wall -O2 -D_GNU_SOURCE
13 +# -- Actions section ----------------------------------------------------------
15 +.PHONY : all depend dep
17 +all : .depend $(TARGETS)
20 + $(CC) $(CFLAGS) -M $(TARGETS:=.c) > .depend
22 +ifeq (.depend,$(wildcard .depend))
27 +# -- Clean section ------------------------------------------------------------
32 + rm -f *.o *~ core .depend
34 diff --git a/Documentation/pps/pps.txt b/Documentation/pps/pps.txt
36 index 0000000..9538925
38 +++ b/Documentation/pps/pps.txt
41 + PPS - Pulse Per Second
42 + ----------------------
44 +(C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com>
46 +This program is free software; you can redistribute it and/or modify
47 +it under the terms of the GNU General Public License as published by
48 +the Free Software Foundation; either version 2 of the License, or
49 +(at your option) any later version.
51 +This program is distributed in the hope that it will be useful,
52 +but WITHOUT ANY WARRANTY; without even the implied warranty of
53 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54 +GNU General Public License for more details.
61 +LinuxPPS provides a programming interface (API) to define into the
62 +system several PPS sources.
64 +PPS means "pulse per second" and a PPS source is just a device which
65 +provides a high precision signal each second so that an application
66 +can use it to adjust system clock time.
68 +A PPS source can be connected to a serial port (usually to the Data
69 +Carrier Detect pin) or to a parallel port (ACK-pin) or to a special
70 +CPU's GPIOs (this is the common case in embedded systems) but in each
71 +case when a new pulse comes the system must apply to it a timestamp
72 +and record it for the userland.
74 +Common use is the combination of the NTPD as userland program with a
75 +GPS receiver as PPS source to obtain a wallclock-time with
76 +sub-millisecond synchronisation to UTC.
82 +While implementing a PPS API as RFC 2783 defines and using an embedded
83 +CPU GPIO-Pin as physical link to the signal, I encountered a deeper
86 + At startup it needs a file descriptor as argument for the function
89 +This implies that the source has a /dev/... entry. This assumption is
90 +ok for the serial and parallel port, where you can do something
91 +useful besides(!) the gathering of timestamps as it is the central
92 +task for a PPS-API. But this assumption does not work for a single
93 +purpose GPIO line. In this case even basic file-related functionality
94 +(like read() and write()) makes no sense at all and should not be a
95 +precondition for the use of a PPS-API.
97 +The problem can be simply solved if you consider that a PPS source is
98 +not always connected with a GPS data source.
100 +So your programs should check if the GPS data source (the serial port
101 +for instance) is a PPS source too, otherwise they should provide the
102 +possibility to open another device as PPS source.
104 +In LinuxPPS the PPS sources are simply char devices usually mapped
105 +into files /dev/pps0, /dev/pps1, etc..
111 +To register a PPS source into the kernel you should define a struct
112 +pps_source_info_s as follow:
114 + static struct pps_source_info_s pps_ktimer_info = {
117 + mode : PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
119 + PPS_CANWAIT | PPS_TSFMT_TSPEC,
120 + echo : pps_ktimer_echo,
121 + owner : THIS_MODULE,
124 +and then calling the function pps_register_source() in your
125 +intialization routine as follow:
127 + source = pps_register_source(&pps_ktimer_info,
128 + PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
130 +The pps_register_source() prototype is:
132 + int pps_register_source(struct pps_source_info_s *info, int default_params)
134 +where "info" is a pointer to a structure that describes a particular
135 +PPS source, "default_params" tells the system what the initial default
136 +parameters for the device should be (is obvious that these parameters
137 +must be a subset of ones defined into the struct
138 +pps_source_info_s which describe the capabilities of the driver).
140 +Once you have registered a new PPS source into the system you can
141 +signal an assert event (for example in the interrupt handler routine)
144 + pps_event(source, PPS_CAPTUREASSERT, ptr);
146 +The same function may also run the defined echo function
147 +(pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
148 +asked for that... etc..
150 +Please see the file drivers/pps/clients/ktimer.c for an example code.
156 +If the SYSFS filesystem is enabled in the kernel it provides a new class:
158 + $ ls /sys/class/pps/
161 +Every directory is the ID of a PPS sources defined into the system and
162 +inside you find several files:
164 + $ ls /sys/class/pps/pps0/
165 + assert clear echo mode name path subsystem@ uevent
167 +Inside each "assert" and "clear" file you can find the timestamp and a
170 + $ cat /sys/class/pps/pps0/assert
171 + 1170026870.983207967#8
173 +Where before the "#" is the timestamp in seconds and after it is the
174 +sequence number. Other files are:
176 +* echo: reports if the PPS source has an echo function or not;
178 +* mode: reports available PPS functioning modes;
180 +* name: reports the PPS source's name;
182 +* path: reports the PPS source's device path, that is the device the
183 + PPS source is connected to (if it exists).
186 +Testing the PPS support
187 +-----------------------
189 +In order to test the PPS support even without specific hardware you can use
190 +the ktimer driver (see the client subsection in the PPS configuration menu)
191 +and the userland tools provided into Documentaion/pps/ directory.
193 +Once you have enabled the compilation of ktimer just modprobe it (if
194 +not statically compiled):
198 +and the run ppstest as follow:
200 + $ ./ppstest /dev/pps0
201 + trying PPS source "/dev/pps1"
202 + found PPS source "/dev/pps1"
203 + ok, found 1 source(s), now start fetching data...
204 + source 0 - assert 1186592699.388832443, sequence: 364 - clear 0.000000000, sequence: 0
205 + source 0 - assert 1186592700.388931295, sequence: 365 - clear 0.000000000, sequence: 0
206 + source 0 - assert 1186592701.389032765, sequence: 366 - clear 0.000000000, sequence: 0
208 +Please, note that to compile userland programs you need the file timepps.h
209 +(see Documentation/pps/).
210 diff --git a/Documentation/pps/ppsctl.c b/Documentation/pps/ppsctl.c
212 index 0000000..83fd08a
214 +++ b/Documentation/pps/ppsctl.c
220 +#include <sys/ioctl.h>
221 +#include <sys/types.h>
222 +#include <sys/stat.h>
225 +#include <linux/serial.h>
227 +void usage(char *name)
229 + fprintf(stderr, "usage: %s <ttyS> [enable|disable]\n", name);
231 + exit(EXIT_FAILURE);
234 +int main(int argc, char *argv[])
238 + struct serial_struct ss;
243 + fd = open(argv[1], O_RDWR);
246 + exit(EXIT_FAILURE);
249 + ret = ioctl(fd, TIOCGSERIAL, &ss);
251 + perror("ioctl(TIOCGSERIAL)");
252 + exit(EXIT_FAILURE);
255 + if (argc < 3) { /* just read PPS status */
256 + printf("PPS is %sabled\n",
257 + ss.flags & ASYNC_HARDPPS_CD ? "en" : "dis");
258 + exit(EXIT_SUCCESS);
261 + if (argv[2][0] == 'e' || argv[2][0] == '1')
262 + ss.flags |= ASYNC_HARDPPS_CD;
263 + else if (argv[2][0] == 'd' || argv[2][0] == '0')
264 + ss.flags &= ~ASYNC_HARDPPS_CD;
266 + fprintf(stderr, "invalid state argument \"%s\"\n", argv[2]);
267 + exit(EXIT_FAILURE);
270 + ret = ioctl(fd, TIOCSSERIAL, &ss);
272 + perror("ioctl(TIOCSSERIAL)");
273 + exit(EXIT_FAILURE);
278 diff --git a/Documentation/pps/ppsfind b/Documentation/pps/ppsfind
280 index 0000000..93c0e17
282 +++ b/Documentation/pps/ppsfind
286 +SYS="/sys/class/pps/"
288 +if [ $# -lt 1 ] ; then
289 + echo "usage: ppsfind <name>" >&2
293 +for d in $(ls $SYS) ; do
294 + if grep $1 $SYS/$d/name >& /dev/null || \
295 + grep $1 $SYS/$d/path >& /dev/null ; then
296 + echo "$d: name=$(cat $SYS/$d/name) path=$(cat $SYS/$d/path)"
301 diff --git a/Documentation/pps/ppstest.c b/Documentation/pps/ppstest.c
303 index 0000000..d125ffa
305 +++ b/Documentation/pps/ppstest.c
312 +#include <sys/types.h>
313 +#include <sys/stat.h>
316 +#include <timepps.h>
318 +int find_source(char *path, pps_handle_t *handle, int *avail_mode)
320 + pps_params_t params;
323 + printf("trying PPS source \"%s\"\n", path);
325 + /* Try to find the source by using the supplied "path" name */
326 + ret = open(path, O_RDWR);
328 + fprintf(stderr, "unable to open device \"%s\" (%m)\n", path);
332 + /* Open the PPS source (and check the file descriptor) */
333 + ret = time_pps_create(ret, handle);
335 + fprintf(stderr, "cannot create a PPS source from device "
336 + "\"%s\" (%m)\n", path);
339 + printf("found PPS source \"%s\"\n", path);
341 + /* Find out what features are supported */
342 + ret = time_pps_getcap(*handle, avail_mode);
344 + fprintf(stderr, "cannot get capabilities (%m)\n");
347 + if ((*avail_mode & PPS_CAPTUREASSERT) == 0) {
348 + fprintf(stderr, "cannot CAPTUREASSERT\n");
351 + if ((*avail_mode & PPS_OFFSETASSERT) == 0) {
352 + fprintf(stderr, "cannot OFFSETASSERT\n");
356 + /* Capture assert timestamps, and compensate for a 675 nsec
357 + * propagation delay */
358 + ret = time_pps_getparams(*handle, ¶ms);
360 + fprintf(stderr, "cannot get parameters (%m)\n");
363 + params.assert_offset.tv_sec = 0;
364 + params.assert_offset.tv_nsec = 675;
365 + params.mode |= PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
366 + ret = time_pps_setparams(*handle, ¶ms);
368 + fprintf(stderr, "cannot set parameters (%m)\n");
375 +int fetch_source(int i, pps_handle_t *handle, int *avail_mode)
377 + struct timespec timeout;
378 + pps_info_t infobuf;
381 + /* create a zero-valued timeout */
382 + timeout.tv_sec = 3;
383 + timeout.tv_nsec = 0;
386 + if (*avail_mode & PPS_CANWAIT) /* waits for the next event */
387 + ret = time_pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,
391 + ret = time_pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,
395 + if (ret == -EINTR) {
396 + fprintf(stderr, "time_pps_fetch() got a signal!\n");
400 + fprintf(stderr, "time_pps_fetch() error %d (%m)\n", ret);
404 + printf("source %d - "
405 + "assert %ld.%09ld, sequence: %ld - "
406 + "clear %ld.%09ld, sequence: %ld\n",
408 + infobuf.assert_timestamp.tv_sec,
409 + infobuf.assert_timestamp.tv_nsec,
410 + infobuf.assert_sequence,
411 + infobuf.clear_timestamp.tv_sec,
412 + infobuf.clear_timestamp.tv_nsec, infobuf.clear_sequence);
417 +void usage(char *name)
419 + fprintf(stderr, "usage: %s <ppsdev> [<ppsdev> ...]\n", name);
420 + exit(EXIT_FAILURE);
423 +int main(int argc, char *argv[])
426 + pps_handle_t handle[4];
431 + /* Check the command line */
435 + for (i = 1; i < argc && i <= 4; i++) {
436 + ret = find_source(argv[i], &handle[i - 1], &avail_mode[i - 1]);
438 + exit(EXIT_FAILURE);
442 + printf("ok, found %d source(s), now start fetching data...\n", num);
444 + /* loop, printing the most recent timestamp every second or so */
446 + for (i = 0; i < num; i++) {
447 + ret = fetch_source(i, &handle[i], &avail_mode[i]);
448 + if (ret < 0 && errno != ETIMEDOUT)
449 + exit(EXIT_FAILURE);
453 + for (; i >= 0; i--)
454 + time_pps_destroy(handle[i]);
458 diff --git a/Documentation/pps/timepps.h b/Documentation/pps/timepps.h
460 index 0000000..28ebf4c
462 +++ b/Documentation/pps/timepps.h
465 + * timepps.h -- PPS API main header
467 + * Copyright (C) 2005-2007 Rodolfo Giometti <giometti@linux.it>
469 + * This program is free software; you can redistribute it and/or modify
470 + * it under the terms of the GNU General Public License as published by
471 + * the Free Software Foundation; either version 2 of the License, or
472 + * (at your option) any later version.
474 + * This program is distributed in the hope that it will be useful,
475 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
476 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
477 + * GNU General Public License for more details.
479 + * You should have received a copy of the GNU General Public License
480 + * along with this program; if not, write to the Free Software
481 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
484 +#ifndef _SYS_TIMEPPS_H_
485 +#define _SYS_TIMEPPS_H_
487 +#include <sys/syscall.h>
490 +#include <linux/pps.h>
493 + * New data structures
497 + unsigned int integral;
498 + unsigned int fractional;
502 + struct timespec tspec;
503 + struct ntp_fp ntpfp;
504 + unsigned long longpad[3];
508 + unsigned long assert_sequence; /* seq. num. of assert event */
509 + unsigned long clear_sequence; /* seq. num. of clear event */
510 + union pps_timeu assert_tu; /* time of assert event */
511 + union pps_timeu clear_tu; /* time of clear event */
512 + int current_mode; /* current mode bits */
516 + int api_version; /* API version # */
517 + int mode; /* mode bits */
518 + union pps_timeu assert_off_tu; /* offset compensation for assert */
519 + union pps_timeu clear_off_tu; /* offset compensation for clear */
522 +typedef int pps_handle_t; /* represents a PPS source */
523 +typedef unsigned long pps_seq_t; /* sequence number */
524 +typedef struct ntp_fp ntp_fp_t; /* NTP-compatible time stamp */
525 +typedef union pps_timeu pps_timeu_t; /* generic data type for time stamps */
526 +typedef struct pps_info pps_info_t;
527 +typedef struct pps_params pps_params_t;
529 +#define assert_timestamp assert_tu.tspec
530 +#define clear_timestamp clear_tu.tspec
532 +#define assert_timestamp_ntpfp assert_tu.ntpfp
533 +#define clear_timestamp_ntpfp clear_tu.ntpfp
535 +#define assert_offset assert_off_tu.tspec
536 +#define clear_offset clear_off_tu.tspec
538 +#define assert_offset_ntpfp assert_off_tu.ntpfp
539 +#define clear_offset_ntpfp clear_off_tu.ntpfp
545 +static __inline int time_pps_create(int source, pps_handle_t *handle)
554 + /* First we check if current device is a PPS valid PPS one...
556 + ret = ioctl(source, PPS_CHECK);
558 + errno = EOPNOTSUPP;
562 + /* ... then since in LinuxPPS there are no differences between a
563 + * "PPS source" and a "PPS handle", we simply return the same value.
570 +static __inline int time_pps_destroy(pps_handle_t handle)
572 + return close(handle);
575 +static __inline int time_pps_getparams(pps_handle_t handle,
576 + pps_params_t *ppsparams)
579 + struct pps_kparams __ppsparams;
581 + ret = ioctl(handle, PPS_GETPARAMS, &__ppsparams);
583 + ppsparams->api_version = __ppsparams.api_version;
584 + ppsparams->mode = __ppsparams.mode;
585 + ppsparams->assert_off_tu.tspec.tv_sec = __ppsparams.assert_off_tu.sec;
586 + ppsparams->assert_off_tu.tspec.tv_nsec = __ppsparams.assert_off_tu.nsec;
587 + ppsparams->clear_off_tu.tspec.tv_sec = __ppsparams.clear_off_tu.sec;
588 + ppsparams->clear_off_tu.tspec.tv_nsec = __ppsparams.clear_off_tu.nsec;
593 +static __inline int time_pps_setparams(pps_handle_t handle,
594 + const pps_params_t *ppsparams)
596 + struct pps_kparams __ppsparams;
598 + __ppsparams.api_version = ppsparams->api_version;
599 + __ppsparams.mode = ppsparams->mode;
600 + __ppsparams.assert_off_tu.sec = ppsparams->assert_off_tu.tspec.tv_sec;
601 + __ppsparams.assert_off_tu.nsec = ppsparams->assert_off_tu.tspec.tv_nsec;
602 + __ppsparams.clear_off_tu.sec = ppsparams->clear_off_tu.tspec.tv_sec;
603 + __ppsparams.clear_off_tu.nsec = ppsparams->clear_off_tu.tspec.tv_nsec;
605 + return ioctl(handle, PPS_SETPARAMS, &__ppsparams);
608 +/* Get capabilities for handle */
609 +static __inline int time_pps_getcap(pps_handle_t handle, int *mode)
611 + return ioctl(handle, PPS_GETCAP, mode);
614 +static __inline int time_pps_fetch(pps_handle_t handle, const int tsformat,
615 + pps_info_t *ppsinfobuf,
616 + const struct timespec *timeout)
618 + struct pps_fdata __fdata;
621 + /* Sanity checks */
622 + if (tsformat != PPS_TSFMT_TSPEC) {
628 + __fdata.timeout.sec = timeout->tv_sec;
629 + __fdata.timeout.nsec = timeout->tv_nsec;
630 + __fdata.timeout.flags = ~PPS_TIME_INVALID;
632 + __fdata.timeout.flags = PPS_TIME_INVALID;
634 + ret = ioctl(handle, PPS_FETCH, &__fdata);
636 + ppsinfobuf->assert_sequence = __fdata.info.assert_sequence;
637 + ppsinfobuf->clear_sequence = __fdata.info.clear_sequence;
638 + ppsinfobuf->assert_tu.tspec.tv_sec = __fdata.info.assert_tu.sec;
639 + ppsinfobuf->assert_tu.tspec.tv_nsec = __fdata.info.assert_tu.nsec;
640 + ppsinfobuf->clear_tu.tspec.tv_sec = __fdata.info.clear_tu.sec;
641 + ppsinfobuf->clear_tu.tspec.tv_nsec = __fdata.info.clear_tu.nsec;
642 + ppsinfobuf->current_mode = __fdata.info.current_mode;
647 +static __inline int time_pps_kcbind(pps_handle_t handle,
648 + const int kernel_consumer,
649 + const int edge, const int tsformat)
651 + /* LinuxPPS doesn't implement kernel consumer feature */
652 + errno = EOPNOTSUPP;
656 +#endif /* _SYS_TIMEPPS_H_ */
657 diff --git a/MAINTAINERS b/MAINTAINERS
658 index 9a91d9e..f45e974 100644
661 @@ -3011,6 +3011,13 @@ P: James Chapman
662 M: jchapman@katalix.com
667 +M: giometti@enneenne.com
668 +W: http://wiki.enneenne.com/index.php/LinuxPPS_support
669 +L: linuxpps@ml.enneenne.com
675 diff --git a/drivers/Kconfig b/drivers/Kconfig
676 index 3e1c442..bffc48e 100644
677 --- a/drivers/Kconfig
678 +++ b/drivers/Kconfig
679 @@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
681 source "drivers/spi/Kconfig"
683 +source "drivers/pps/Kconfig"
685 source "drivers/w1/Kconfig"
687 source "drivers/power/Kconfig"
688 diff --git a/drivers/Makefile b/drivers/Makefile
689 index f0878b2..2e84e49 100644
690 --- a/drivers/Makefile
691 +++ b/drivers/Makefile
692 @@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT) += input/
693 obj-$(CONFIG_I2O) += message/
694 obj-$(CONFIG_RTC_LIB) += rtc/
696 +obj-$(CONFIG_PPS) += pps/
697 obj-$(CONFIG_W1) += w1/
698 obj-$(CONFIG_POWER_SUPPLY) += power/
699 obj-$(CONFIG_HWMON) += hwmon/
700 diff --git a/drivers/char/lp.c b/drivers/char/lp.c
701 index 62051f8..e0a8364 100644
702 --- a/drivers/char/lp.c
703 +++ b/drivers/char/lp.c
704 @@ -746,6 +746,27 @@ static struct console lpcons = {
706 #endif /* console on line printer */
708 +/* Support for PPS signal on the line printer */
710 +#ifdef CONFIG_PPS_CLIENT_LP
712 +static void lp_pps_echo(int source, int event, void *data)
714 + struct parport *port = data;
715 + unsigned char status = parport_read_status(port);
717 + /* echo event via SEL bit */
718 + parport_write_control(port,
719 + parport_read_control(port) | PARPORT_CONTROL_SELECT);
721 + /* signal no event */
722 + if ((status & PARPORT_STATUS_ACK) != 0)
723 + parport_write_control(port,
724 + parport_read_control(port) & ~PARPORT_CONTROL_SELECT);
729 /* --- initialisation code ------------------------------------- */
731 static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
732 @@ -817,6 +838,38 @@ static int lp_register(int nr, struct parport *port)
736 +#ifdef CONFIG_PPS_CLIENT_LP
737 + port->pps_info.owner = THIS_MODULE;
738 + port->pps_info.dev = port->dev;
739 + snprintf(port->pps_info.path, PPS_MAX_NAME_LEN, "/dev/lp%d", nr);
741 + /* No PPS support if lp port has no IRQ line */
742 + if (port->irq != PARPORT_IRQ_NONE) {
743 + strncpy(port->pps_info.name, port->name, PPS_MAX_NAME_LEN);
745 + port->pps_info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
747 + PPS_CANWAIT | PPS_TSFMT_TSPEC;
749 + port->pps_info.echo = lp_pps_echo;
751 + port->pps_source = pps_register_source(&(port->pps_info),
752 + PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
753 + if (port->pps_source < 0)
755 + "cannot register PPS source \"%s\"\n",
756 + port->pps_info.path);
758 + dev_info(port->dev, "PPS source #%d \"%s\" added\n",
759 + port->pps_source, port->pps_info.path);
761 + port->pps_source = -1;
762 + dev_err(port->dev, "PPS support disabled due port \"%s\" is "
763 + "in polling mode\n",
764 + port->pps_info.path);
771 @@ -860,6 +913,14 @@ static void lp_detach (struct parport *port)
772 console_registered = NULL;
774 #endif /* CONFIG_LP_CONSOLE */
776 +#ifdef CONFIG_PPS_CLIENT_LP
777 + if (port->pps_source >= 0) {
778 + pps_unregister_source(port->pps_source);
779 + dev_dbg(port->dev, "PPS source #%d \"%s\" removed\n",
780 + port->pps_source, port->pps_info.path);
785 static struct parport_driver lp_driver = {
786 diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig
788 index 0000000..bfe6621
790 +++ b/drivers/pps/Kconfig
793 +# PPS support configuration
799 + tristate "PPS support"
800 + depends on EXPERIMENTAL
802 + PPS (Pulse Per Second) is a special pulse provided by some GPS
803 + antennae. Userland can use it to get an high time reference.
805 + Some antennae's PPS signals are connected with the CD (Carrier
806 + Detect) pin of the serial line they use to communicate with the
807 + host. In this case use the SERIAL_LINE client support.
809 + Some antennae's PPS signals are connected with some special host
810 + inputs so you have to enable the corresponding client support.
812 + To compile this driver as a module, choose M here: the module
813 + will be called pps_core.ko.
816 + bool "PPS debugging messages"
819 + Say Y here if you want the PPS support to produce a bunch of debug
820 + messages to the system log. Select this if you are having a
821 + problem with PPS support and want to see more of what is going on.
823 +source drivers/pps/clients/Kconfig
826 diff --git a/drivers/pps/Makefile b/drivers/pps/Makefile
828 index 0000000..d8ec308
830 +++ b/drivers/pps/Makefile
833 +# Makefile for the PPS core.
836 +pps_core-objs += pps.o kapi.o sysfs.o
837 +obj-$(CONFIG_PPS) += pps_core.o
840 +ifeq ($(CONFIG_PPS_DEBUG),y)
841 +EXTRA_CFLAGS += -DDEBUG
843 diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
845 index 0000000..09ba5c3
847 +++ b/drivers/pps/clients/Kconfig
850 +# PPS clients configuration
855 +comment "PPS clients support"
857 +config PPS_CLIENT_KTIMER
858 + tristate "Kernel timer client (Testing client, use for debug)"
860 + If you say yes here you get support for a PPS debugging client
861 + which uses a kernel timer to generate the PPS signal.
863 + This driver can also be built as a module. If so, the module
864 + will be called ktimer.ko.
866 +comment "UART serial support (forced off)"
867 + depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y))
869 +config PPS_CLIENT_UART
870 + bool "UART serial support"
871 + depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)
873 + If you say yes here you get support for a PPS source connected
874 + with the CD (Carrier Detect) pin of your serial port.
876 +comment "Parallel printer support (forced off)"
877 + depends on !( PRINTER != n && !(PPS = m && PRINTER = y))
879 +config PPS_CLIENT_LP
880 + bool "Parallel printer support"
881 + depends on PRINTER != n && !(PPS = m && PRINTER = y)
883 + If you say yes here you get support for a PPS source connected
884 + with the interrupt pin of your parallel port.
887 diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
889 index 0000000..f3c1e39
891 +++ b/drivers/pps/clients/Makefile
894 +# Makefile for PPS clients.
897 +obj-$(CONFIG_PPS_CLIENT_KTIMER) += ktimer.o
899 +ifeq ($(CONFIG_PPS_DEBUG),y)
900 +EXTRA_CFLAGS += -DDEBUG
902 diff --git a/drivers/pps/clients/ktimer.c b/drivers/pps/clients/ktimer.c
904 index 0000000..4d613ab
906 +++ b/drivers/pps/clients/ktimer.c
909 + * ktimer.c -- kernel timer test client
912 + * Copyright (C) 2005-2006 Rodolfo Giometti <giometti@linux.it>
914 + * This program is free software; you can redistribute it and/or modify
915 + * it under the terms of the GNU General Public License as published by
916 + * the Free Software Foundation; either version 2 of the License, or
917 + * (at your option) any later version.
919 + * This program is distributed in the hope that it will be useful,
920 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
921 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
922 + * GNU General Public License for more details.
924 + * You should have received a copy of the GNU General Public License
925 + * along with this program; if not, write to the Free Software
926 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
930 +#include <linux/kernel.h>
931 +#include <linux/module.h>
932 +#include <linux/init.h>
933 +#include <linux/time.h>
934 +#include <linux/timer.h>
936 +#include <linux/pps.h>
943 +static struct timer_list ktimer;
949 +static void pps_ktimer_event(unsigned long ptr)
951 + pr_info("PPS event at %lu\n", jiffies);
953 + pps_event(source, PPS_CAPTUREASSERT, NULL);
955 + mod_timer(&ktimer, jiffies + HZ);
959 + * The echo function
962 +static void pps_ktimer_echo(int source, int event, void *data)
964 + pr_info("echo %s %s for source %d\n",
965 + event & PPS_CAPTUREASSERT ? "assert" : "",
966 + event & PPS_CAPTURECLEAR ? "clear" : "",
971 + * The PPS info struct
974 +static struct pps_source_info pps_ktimer_info = {
977 + mode : PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
979 + PPS_CANWAIT | PPS_TSFMT_TSPEC,
980 + echo : pps_ktimer_echo,
981 + owner : THIS_MODULE,
988 +static void __exit pps_ktimer_exit(void)
990 + del_timer_sync(&ktimer);
991 + pps_unregister_source(source);
993 + pr_info("ktimer PPS source unregistered\n");
996 +static int __init pps_ktimer_init(void)
1000 + ret = pps_register_source(&pps_ktimer_info,
1001 + PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
1003 + printk(KERN_ERR "cannot register ktimer source\n");
1008 + setup_timer(&ktimer, pps_ktimer_event, 0);
1009 + mod_timer(&ktimer, jiffies + HZ);
1011 + pr_info("ktimer PPS source registered at %d\n", source);
1016 +module_init(pps_ktimer_init);
1017 +module_exit(pps_ktimer_exit);
1019 +MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
1020 +MODULE_DESCRIPTION("dummy PPS source by using a kernel timer (just for debug)");
1021 +MODULE_LICENSE("GPL");
1022 diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
1023 new file mode 100644
1024 index 0000000..67290d5
1026 +++ b/drivers/pps/kapi.c
1029 + * kapi.c -- kernel API
1032 + * Copyright (C) 2005-2007 Rodolfo Giometti <giometti@linux.it>
1034 + * This program is free software; you can redistribute it and/or modify
1035 + * it under the terms of the GNU General Public License as published by
1036 + * the Free Software Foundation; either version 2 of the License, or
1037 + * (at your option) any later version.
1039 + * This program is distributed in the hope that it will be useful,
1040 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1041 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1042 + * GNU General Public License for more details.
1044 + * You should have received a copy of the GNU General Public License
1045 + * along with this program; if not, write to the Free Software
1046 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1050 +#include <linux/kernel.h>
1051 +#include <linux/module.h>
1052 +#include <linux/init.h>
1053 +#include <linux/sched.h>
1054 +#include <linux/time.h>
1055 +#include <linux/spinlock.h>
1056 +#include <linux/idr.h>
1057 +#include <linux/fs.h>
1058 +#include <linux/pps.h>
1064 +static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED;
1065 +static DEFINE_IDR(pps_idr);
1071 +static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
1073 + ts->nsec += offset->nsec;
1074 + if (ts->nsec >= NSEC_PER_SEC) {
1075 + ts->nsec -= NSEC_PER_SEC;
1077 + } else if (ts->nsec < 0) {
1078 + ts->nsec += NSEC_PER_SEC;
1081 + ts->sec += offset->sec;
1085 + * Exported functions
1088 +int pps_register_source(struct pps_source_info *info, int default_params)
1090 + struct pps_device *pps;
1094 + /* Sanity checks */
1095 + if ((info->mode & default_params) != default_params) {
1096 + printk(KERN_ERR "pps: %s: unsupported default parameters\n",
1099 + goto pps_register_source_exit;
1101 + if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 &&
1102 + info->echo == NULL) {
1103 + printk(KERN_ERR "pps: %s: echo function is not defined\n",
1106 + goto pps_register_source_exit;
1108 + if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
1109 + printk(KERN_ERR "pps: %s: unspecified time format\n",
1112 + goto pps_register_source_exit;
1115 + /* Allocate memory for the new PPS source struct */
1116 + pps = kzalloc(sizeof(struct pps_device), GFP_KERNEL);
1117 + if (pps == NULL) {
1119 + goto pps_register_source_exit;
1122 + /* Get new ID for the new PPS source */
1123 + if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) {
1128 + spin_lock_irq(&idr_lock);
1129 + err = idr_get_new(&pps_idr, pps, &id);
1130 + spin_unlock_irq(&idr_lock);
1135 + id = id & MAX_ID_MASK;
1136 + if (id >= PPS_MAX_SOURCES) {
1137 + printk(KERN_ERR "pps: %s: too much PPS sources in the system\n",
1144 + pps->params.api_version = PPS_API_VERS;
1145 + pps->params.mode = default_params;
1146 + pps->info = *info;
1148 + init_waitqueue_head(&pps->queue);
1149 + spin_lock_init(&pps->lock);
1150 + atomic_set(&pps->usage, 0);
1151 + init_waitqueue_head(&pps->usage_queue);
1153 + /* Create the char device */
1154 + err = pps_register_cdev(pps);
1156 + printk(KERN_ERR "pps: %s: unable to create char device\n",
1161 + /* Create the sysfs entry */
1162 + err = pps_sysfs_create_source_entry(pps);
1164 + printk(KERN_ERR "pps: %s: unable to create sysfs entries\n",
1166 + goto unregister_cdev;
1169 + pr_info("new PPS source %s at ID %d\n", info->name, id);
1174 + pps_unregister_cdev(pps);
1177 + spin_lock_irq(&idr_lock);
1178 + idr_remove(&pps_idr, id);
1179 + spin_unlock_irq(&idr_lock);
1184 +pps_register_source_exit:
1185 + printk(KERN_ERR "pps: %s: unable to register source\n", info->name);
1189 +EXPORT_SYMBOL(pps_register_source);
1191 +void pps_unregister_source(int source)
1193 + struct pps_device *pps;
1195 + spin_lock_irq(&idr_lock);
1196 + pps = idr_find(&pps_idr, source);
1199 + spin_unlock_irq(&idr_lock);
1203 + /* This should be done first in order to deny IRQ handlers
1204 + * to access PPS structs
1207 + idr_remove(&pps_idr, pps->id);
1208 + spin_unlock_irq(&idr_lock);
1210 + wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0);
1212 + pps_sysfs_remove_source_entry(pps);
1213 + pps_unregister_cdev(pps);
1216 +EXPORT_SYMBOL(pps_unregister_source);
1218 +void pps_event(int source, int event, void *data)
1220 + struct pps_device *pps;
1221 + struct timespec __ts;
1222 + struct pps_ktime ts;
1223 + unsigned long flags;
1225 + /* First of all we get the time stamp... */
1226 + getnstimeofday(&__ts);
1228 + /* ... and translate it to PPS time data struct */
1229 + ts.sec = __ts.tv_sec;
1230 + ts.nsec = __ts.tv_nsec;
1232 + if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0 ) {
1233 + printk(KERN_ERR "pps: unknown event (%x) for source %d\n",
1238 + spin_lock_irqsave(&idr_lock, flags);
1239 + pps = idr_find(&pps_idr, source);
1241 + /* If we find a valid PPS source we lock it before leaving
1245 + atomic_inc(&pps->usage);
1246 + spin_unlock_irqrestore(&idr_lock, flags);
1251 + pr_debug("PPS event on source %d at at %llu.%06u\n",
1252 + pps->id, ts.sec, ts.nsec);
1254 + spin_lock_irqsave(&pps->lock, flags);
1256 + /* Must call the echo function? */
1257 + if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)))
1258 + pps->info.echo(source, event, data);
1260 + /* Check the event */
1261 + pps->current_mode = pps->params.mode;
1262 + if (event & PPS_CAPTUREASSERT) {
1263 + /* We have to add an offset? */
1264 + if (pps->params.mode & PPS_OFFSETASSERT)
1265 + pps_add_offset(&ts, &pps->params.assert_off_tu);
1267 + /* Save the time stamp */
1268 + pps->assert_tu = ts;
1269 + pps->assert_sequence++;
1270 + pr_debug("capture assert seq #%u for source %d\n",
1271 + pps->assert_sequence, source);
1273 + if (event & PPS_CAPTURECLEAR) {
1274 + /* We have to add an offset? */
1275 + if (pps->params.mode & PPS_OFFSETCLEAR)
1276 + pps_add_offset(&ts, &pps->params.clear_off_tu);
1278 + /* Save the time stamp */
1279 + pps->clear_tu = ts;
1280 + pps->clear_sequence++;
1281 + pr_debug("capture clear seq #%u for source %d\n",
1282 + pps->clear_sequence, source);
1286 + wake_up_interruptible(&pps->queue);
1288 + kill_fasync(&pps->async_queue, SIGIO, POLL_IN);
1290 + spin_unlock_irqrestore(&pps->lock, flags);
1292 + /* Now we can release the PPS source for (possible) deregistration */
1293 + spin_lock_irqsave(&idr_lock, flags);
1294 + atomic_dec(&pps->usage);
1295 + wake_up_all(&pps->usage_queue);
1296 + spin_unlock_irqrestore(&idr_lock, flags);
1298 +EXPORT_SYMBOL(pps_event);
1299 diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
1300 new file mode 100644
1301 index 0000000..52de2f1
1303 +++ b/drivers/pps/pps.c
1306 + * pps.c -- Main PPS support file
1309 + * Copyright (C) 2005-2007 Rodolfo Giometti <giometti@linux.it>
1311 + * This program is free software; you can redistribute it and/or modify
1312 + * it under the terms of the GNU General Public License as published by
1313 + * the Free Software Foundation; either version 2 of the License, or
1314 + * (at your option) any later version.
1316 + * This program is distributed in the hope that it will be useful,
1317 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1318 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1319 + * GNU General Public License for more details.
1321 + * You should have received a copy of the GNU General Public License
1322 + * along with this program; if not, write to the Free Software
1323 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1327 +#include <linux/kernel.h>
1328 +#include <linux/version.h>
1329 +#include <linux/module.h>
1330 +#include <linux/init.h>
1331 +#include <linux/sched.h>
1332 +#include <linux/uaccess.h>
1333 +#include <linux/cdev.h>
1334 +#include <linux/poll.h>
1335 +#include <linux/pps.h>
1341 +static dev_t pps_devt;
1342 +static struct class *pps_class;
1345 + * Char device methods
1348 +static unsigned int pps_cdev_poll(struct file *file, poll_table *wait)
1350 + struct pps_device *pps = file->private_data;
1352 + poll_wait(file, &pps->queue, wait);
1354 + return POLLIN | POLLRDNORM;
1357 +static int pps_cdev_fasync(int fd, struct file *file, int on)
1359 + struct pps_device *pps = file->private_data;
1360 + return fasync_helper(fd, file, on, &pps->async_queue);
1363 +static int pps_cdev_ioctl(struct inode *inode, struct file *file,
1364 + unsigned int cmd, unsigned long arg)
1366 + struct pps_device *pps = file->private_data;
1367 + struct pps_kparams params;
1368 + struct pps_fdata fdata;
1369 + unsigned long ticks;
1370 + void __user *uarg = (void __user *) arg;
1371 + int __user *iuarg = (int __user *) arg;
1377 + /* This does nothing but signal we are a PPS source... */
1381 + case PPS_GETPARAMS:
1382 + pr_debug("PPS_GETPARAMS: source %d\n", pps->id);
1384 + /* Sanity checks */
1388 + /* Return current parameters */
1389 + err = copy_to_user(uarg, &pps->params,
1390 + sizeof(struct pps_kparams));
1396 + case PPS_SETPARAMS:
1397 + pr_debug("PPS_SETPARAMS: source %d\n", pps->id);
1399 + /* Check the capabilities */
1400 + if (!capable(CAP_SYS_TIME))
1403 + /* Sanity checks */
1406 + err = copy_from_user(¶ms, uarg, sizeof(struct pps_kparams));
1409 + if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
1410 + pr_debug("capture mode unspecified (%x)\n",
1415 + /* Check for supported capabilities */
1416 + if ((params.mode & ~pps->info.mode) != 0) {
1417 + pr_debug("unsupported capabilities (%x)\n",
1422 + spin_lock_irq(&pps->lock);
1424 + /* Save the new parameters */
1425 + pps->params = params;
1427 + /* Restore the read only parameters */
1428 + if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
1429 + /* section 3.3 of RFC 2783 interpreted */
1430 + pr_debug("time format unspecified (%x)\n",
1432 + pps->params.mode |= PPS_TSFMT_TSPEC;
1434 + if (pps->info.mode & PPS_CANWAIT)
1435 + pps->params.mode |= PPS_CANWAIT;
1436 + pps->params.api_version = PPS_API_VERS;
1438 + spin_unlock_irq(&pps->lock);
1443 + pr_debug("PPS_GETCAP: source %d\n", pps->id);
1445 + /* Sanity checks */
1449 + err = put_user(pps->info.mode, iuarg);
1456 + pr_debug("PPS_FETCH: source %d\n", pps->id);
1460 + err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
1466 + /* Manage the timeout */
1467 + if (fdata.timeout.flags & PPS_TIME_INVALID)
1468 + err = wait_event_interruptible(pps->queue, pps->go);
1470 + pr_debug("timeout %lld.%09d\n",
1471 + fdata.timeout.sec, fdata.timeout.nsec);
1472 + ticks = fdata.timeout.sec * HZ;
1473 + ticks += fdata.timeout.nsec / (NSEC_PER_SEC / HZ);
1476 + err = wait_event_interruptible_timeout(
1477 + pps->queue, pps->go, ticks);
1479 + return -ETIMEDOUT;
1483 + /* Check for pending signals */
1484 + if (err == -ERESTARTSYS) {
1485 + pr_debug("pending signal caught\n");
1489 + /* Return the fetched timestamp */
1490 + spin_lock_irq(&pps->lock);
1492 + fdata.info.assert_sequence = pps->assert_sequence;
1493 + fdata.info.clear_sequence = pps->clear_sequence;
1494 + fdata.info.assert_tu = pps->assert_tu;
1495 + fdata.info.clear_tu = pps->clear_tu;
1496 + fdata.info.current_mode = pps->current_mode;
1498 + spin_unlock_irq(&pps->lock);
1500 + err = copy_to_user(uarg, &fdata, sizeof(struct pps_fdata));
1514 +static int pps_cdev_open(struct inode *inode, struct file *file)
1516 + struct pps_device *pps = container_of(inode->i_cdev,
1517 + struct pps_device, cdev);
1519 + /* Lock the PPS source against (possible) deregistration */
1520 + atomic_inc(&pps->usage);
1522 + file->private_data = pps;
1527 +static int pps_cdev_release(struct inode *inode, struct file *file)
1529 + struct pps_device *pps = file->private_data;
1531 + /* Free the PPS source and wake up (possible) deregistration */
1532 + atomic_dec(&pps->usage);
1533 + wake_up_all(&pps->usage_queue);
1539 + * Char device stuff
1542 +static const struct file_operations pps_cdev_fops = {
1543 + .owner = THIS_MODULE,
1544 + .llseek = no_llseek,
1545 + .poll = pps_cdev_poll,
1546 + .fasync = pps_cdev_fasync,
1547 + .ioctl = pps_cdev_ioctl,
1548 + .open = pps_cdev_open,
1549 + .release = pps_cdev_release,
1552 +int pps_register_cdev(struct pps_device *pps)
1556 + pps->devno = MKDEV(MAJOR(pps_devt), pps->id);
1557 + cdev_init(&pps->cdev, &pps_cdev_fops);
1558 + pps->cdev.owner = pps->info.owner;
1560 + err = cdev_add(&pps->cdev, pps->devno, 1);
1562 + printk(KERN_ERR "pps: %s: failed to add char device %d:%d\n",
1563 + pps->info.name, MAJOR(pps_devt), pps->id);
1566 + pps->dev = device_create(pps_class, pps->info.dev, pps->devno,
1567 + "pps%d", pps->id);
1570 + dev_set_drvdata(pps->dev, pps);
1572 + pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
1573 + MAJOR(pps_devt), pps->id);
1578 + cdev_del(&pps->cdev);
1583 +void pps_unregister_cdev(struct pps_device *pps)
1585 + device_destroy(pps_class, pps->devno);
1586 + cdev_del(&pps->cdev);
1593 +static void __exit pps_exit(void)
1595 + class_destroy(pps_class);
1598 + unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
1600 + pr_info("LinuxPPS API ver. %d removed\n", PPS_API_VERS);
1603 +static int __init pps_init(void)
1607 + pps_class = class_create(THIS_MODULE, "pps");
1609 + printk(KERN_ERR "pps: ailed to allocate class\n");
1613 + err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
1615 + printk(KERN_ERR "pps: failed to allocate char device region\n");
1616 + goto remove_class;
1619 + pr_info("LinuxPPS API ver. %d registered\n", PPS_API_VERS);
1620 + pr_info("Software ver. %s - Copyright 2005-2007 Rodolfo Giometti "
1621 + "<giometti@linux.it>\n", PPS_VERSION);
1626 + class_destroy(pps_class);
1631 +subsys_initcall(pps_init);
1632 +module_exit(pps_exit);
1634 +MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
1635 +MODULE_DESCRIPTION("LinuxPPS support (RFC 2783) - ver. " PPS_VERSION);
1636 +MODULE_LICENSE("GPL");
1637 diff --git a/drivers/pps/sysfs.c b/drivers/pps/sysfs.c
1638 new file mode 100644
1639 index 0000000..8541be7
1641 +++ b/drivers/pps/sysfs.c
1644 + * sysfs.c -- sysfs support
1647 + * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
1649 + * This program is free software; you can redistribute it and/or modify
1650 + * it under the terms of the GNU General Public License as published by
1651 + * the Free Software Foundation; either version 2 of the License, or
1652 + * (at your option) any later version.
1654 + * This program is distributed in the hope that it will be useful,
1655 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1656 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1657 + * GNU General Public License for more details.
1659 + * You should have received a copy of the GNU General Public License
1660 + * along with this program; if not, write to the Free Software
1661 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1665 +#include <linux/device.h>
1666 +#include <linux/module.h>
1667 +#include <linux/string.h>
1668 +#include <linux/pps.h>
1671 + * Attribute functions
1674 +static ssize_t pps_show_assert(struct device *dev,
1675 + struct device_attribute *attr, char *buf)
1677 + struct pps_device *pps = dev_get_drvdata(dev);
1679 + return sprintf(buf, "%lld.%09d#%d\n",
1680 + pps->assert_tu.sec, pps->assert_tu.nsec,
1681 + pps->assert_sequence);
1683 +DEVICE_ATTR(assert, S_IRUGO, pps_show_assert, NULL);
1685 +static ssize_t pps_show_clear(struct device *dev,
1686 + struct device_attribute *attr, char *buf)
1688 + struct pps_device *pps = dev_get_drvdata(dev);
1690 + return sprintf(buf, "%lld.%09d#%d\n",
1691 + pps->clear_tu.sec, pps->clear_tu.nsec,
1692 + pps->clear_sequence);
1694 +DEVICE_ATTR(clear, S_IRUGO, pps_show_clear, NULL);
1696 +static ssize_t pps_show_mode(struct device *dev,
1697 + struct device_attribute *attr, char *buf)
1699 + struct pps_device *pps = dev_get_drvdata(dev);
1701 + return sprintf(buf, "%4x\n", pps->info.mode);
1703 +DEVICE_ATTR(mode, S_IRUGO, pps_show_mode, NULL);
1705 +static ssize_t pps_show_echo(struct device *dev,
1706 + struct device_attribute *attr, char *buf)
1708 + struct pps_device *pps = dev_get_drvdata(dev);
1710 + return sprintf(buf, "%d\n", !!pps->info.echo);
1712 +DEVICE_ATTR(echo, S_IRUGO, pps_show_echo, NULL);
1714 +static ssize_t pps_show_name(struct device *dev,
1715 + struct device_attribute *attr, char *buf)
1717 + struct pps_device *pps = dev_get_drvdata(dev);
1719 + return sprintf(buf, "%s\n", pps->info.name);
1721 +DEVICE_ATTR(name, S_IRUGO, pps_show_name, NULL);
1723 +static ssize_t pps_show_path(struct device *dev,
1724 + struct device_attribute *attr, char *buf)
1726 + struct pps_device *pps = dev_get_drvdata(dev);
1728 + return sprintf(buf, "%s\n", pps->info.path);
1730 +DEVICE_ATTR(path, S_IRUGO, pps_show_path, NULL);
1733 + * Public functions
1736 +void pps_sysfs_remove_source_entry(struct pps_device *pps)
1738 + /* Delete info files */
1739 + if (pps->info.mode & PPS_CAPTUREASSERT)
1740 + device_remove_file(pps->dev, &dev_attr_assert);
1742 + if (pps->info.mode & PPS_CAPTURECLEAR)
1743 + device_remove_file(pps->dev, &dev_attr_clear);
1745 + device_remove_file(pps->dev, &dev_attr_mode);
1746 + device_remove_file(pps->dev, &dev_attr_echo);
1747 + device_remove_file(pps->dev, &dev_attr_name);
1748 + device_remove_file(pps->dev, &dev_attr_path);
1751 +int pps_sysfs_create_source_entry(struct pps_device *pps)
1753 + /* Create file "assert" and "clear" according to source capability */
1754 + if (pps->info.mode & PPS_CAPTUREASSERT)
1755 + device_create_file(pps->dev, &dev_attr_assert);
1757 + if (pps->info.mode & PPS_CAPTURECLEAR)
1758 + device_create_file(pps->dev, &dev_attr_clear);
1760 + device_create_file(pps->dev, &dev_attr_mode);
1761 + device_create_file(pps->dev, &dev_attr_echo);
1762 + device_create_file(pps->dev, &dev_attr_name);
1763 + device_create_file(pps->dev, &dev_attr_path);
1767 diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
1768 index f94109c..a5e83f8 100644
1769 --- a/drivers/serial/8250.c
1770 +++ b/drivers/serial/8250.c
1771 @@ -2118,6 +2118,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
1772 up->ier |= UART_IER_MSI;
1773 if (up->capabilities & UART_CAP_UUE)
1774 up->ier |= UART_IER_UUE | UART_IER_RTOIE;
1775 + if (up->port.flags & UPF_HARDPPS_CD)
1776 + up->ier |= UART_IER_MSI; /* enable interrupts */
1778 serial_out(up, UART_IER, up->ier);
1780 diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
1781 index a055f58..a40b87c 100644
1782 --- a/drivers/serial/serial_core.c
1783 +++ b/drivers/serial/serial_core.c
1785 #include <linux/serial.h> /* for serial_state and serial_icounter_struct */
1786 #include <linux/delay.h>
1787 #include <linux/mutex.h>
1788 +#include <linux/pps.h>
1790 #include <asm/irq.h>
1791 #include <asm/uaccess.h>
1792 @@ -633,6 +634,54 @@ static int uart_get_info(struct uart_state *state,
1796 +#ifdef CONFIG_PPS_CLIENT_UART
1799 +uart_register_pps_port(struct uart_state *state, struct uart_port *port)
1801 + struct tty_driver *drv = port->info->tty->driver;
1804 + state->pps_info.owner = THIS_MODULE;
1805 + state->pps_info.dev = port->dev;
1806 + snprintf(state->pps_info.name, PPS_MAX_NAME_LEN, "%s%d",
1807 + drv->driver_name, port->line);
1808 + snprintf(state->pps_info.path, PPS_MAX_NAME_LEN, "/dev/%s%d",
1809 + drv->name, port->line);
1811 + state->pps_info.mode = PPS_CAPTUREBOTH | \
1812 + PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
1813 + PPS_CANWAIT | PPS_TSFMT_TSPEC;
1815 + ret = pps_register_source(&state->pps_info, PPS_CAPTUREBOTH | \
1816 + PPS_OFFSETASSERT | PPS_OFFSETCLEAR);
1818 + dev_err(port->dev, "cannot register PPS source \"%s\"\n",
1819 + state->pps_info.path);
1822 + port->pps_source = ret;
1823 + dev_dbg(port->dev, "PPS source #%d \"%s\" added\n",
1824 + port->pps_source, state->pps_info.path);
1830 +uart_unregister_pps_port(struct uart_state *state, struct uart_port *port)
1832 + pps_unregister_source(port->pps_source);
1833 + dev_dbg(port->dev, "PPS source #%d \"%s\" removed\n",
1834 + port->pps_source, state->pps_info.path);
1839 +#define uart_register_pps_port(state, port) do { } while (0)
1840 +#define uart_unregister_pps_port(state, port) do { } while (0)
1842 +#endif /* CONFIG_PPS_CLIENT_UART */
1844 static int uart_set_info(struct uart_state *state,
1845 struct serial_struct __user *newinfo)
1847 @@ -807,11 +856,19 @@ static int uart_set_info(struct uart_state *state,
1848 (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
1851 + /* PPS support enabled/disabled? */
1852 + if ((old_flags & UPF_HARDPPS_CD) != (new_flags & UPF_HARDPPS_CD)) {
1853 + if (new_flags & UPF_HARDPPS_CD)
1854 + uart_register_pps_port(state, port);
1856 + uart_unregister_pps_port(state, port);
1860 if (port->type == PORT_UNKNOWN)
1862 if (state->info->flags & UIF_INITIALIZED) {
1863 - if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
1864 + if (((old_flags ^ port->flags) & (UPF_SPD_MASK|UPF_HARDPPS_CD)) ||
1865 old_custom_divisor != port->custom_divisor) {
1867 * If they're setting up a custom divisor or speed,
1868 @@ -2110,6 +2167,12 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
1869 port->ops->config_port(port, flags);
1873 + * Add the PPS support for the current port.
1875 + if (port->flags & UPF_HARDPPS_CD)
1876 + uart_register_pps_port(state, port);
1878 if (port->type != PORT_UNKNOWN) {
1879 unsigned long flags;
1881 @@ -2359,6 +2422,12 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
1882 mutex_unlock(&state->mutex);
1885 + * Remove PPS support from the current port.
1887 + if (port->flags & UPF_HARDPPS_CD)
1888 + uart_unregister_pps_port(state, port);
1891 * Remove the devices from the tty layer
1893 tty_unregister_device(drv->tty_driver, port->line);
1894 diff --git a/include/linux/Kbuild b/include/linux/Kbuild
1895 index 818cc3a..0a9394f 100644
1896 --- a/include/linux/Kbuild
1897 +++ b/include/linux/Kbuild
1898 @@ -295,6 +295,7 @@ unifdef-y += pmu.h
1900 unifdef-y += ppp_defs.h
1901 unifdef-y += ppp-comp.h
1903 unifdef-y += ptrace.h
1904 unifdef-y += qnx4_fs.h
1905 unifdef-y += quota.h
1906 diff --git a/include/linux/parport.h b/include/linux/parport.h
1907 index 9cdd694..549de6e 100644
1908 --- a/include/linux/parport.h
1909 +++ b/include/linux/parport.h
1910 @@ -100,6 +100,7 @@ typedef enum {
1911 #include <linux/proc_fs.h>
1912 #include <linux/spinlock.h>
1913 #include <linux/wait.h>
1914 +#include <linux/pps.h>
1915 #include <asm/system.h>
1916 #include <asm/ptrace.h>
1917 #include <asm/semaphore.h>
1918 @@ -327,6 +328,11 @@ struct parport {
1920 struct list_head full_list;
1921 struct parport *slaves[3];
1923 +#ifdef CONFIG_PPS_CLIENT_LP
1924 + struct pps_source_info pps_info;
1925 + int pps_source; /* PPS source ID */
1929 #define DEFAULT_SPIN_TIME 500 /* us */
1930 @@ -517,6 +523,12 @@ extern int parport_daisy_select (struct parport *port, int daisy, int mode);
1931 /* Lowlevel drivers _can_ call this support function to handle irqs. */
1932 static __inline__ void parport_generic_irq(int irq, struct parport *port)
1934 +#ifdef CONFIG_PPS_CLIENT_LP
1935 + pps_event(port->pps_source, PPS_CAPTUREASSERT, port);
1936 + dev_dbg(port->dev, "PPS assert at %lu on source #%d\n",
1937 + jiffies, port->pps_source);
1940 parport_ieee1284_interrupt (irq, port);
1941 read_lock(&port->cad_lock);
1942 if (port->cad && port->cad->irq_func)
1943 diff --git a/include/linux/pps.h b/include/linux/pps.h
1944 new file mode 100644
1945 index 0000000..5bdb593
1947 +++ b/include/linux/pps.h
1950 + * pps.h -- PPS API kernel header.
1953 + * Copyright (C) 2005-2007 Rodolfo Giometti <giometti@linux.it>
1955 + * This program is free software; you can redistribute it and/or modify
1956 + * it under the terms of the GNU General Public License as published by
1957 + * the Free Software Foundation; either version 2 of the License, or
1958 + * (at your option) any later version.
1960 + * This program is distributed in the hope that it will be useful,
1961 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1962 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1963 + * GNU General Public License for more details.
1965 + * You should have received a copy of the GNU General Public License
1966 + * along with this program; if not, write to the Free Software
1967 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1974 +/* Implementation note: the logical states ``assert'' and ``clear''
1975 + * are implemented in terms of the chip register, i.e. ``assert''
1976 + * means the bit is set. */
1979 + * 3.2 New data structures
1983 +#include <linux/types.h>
1984 +#include <sys/time.h>
1985 +#include <sys/ioctl.h>
1987 +#include <linux/time.h>
1990 +#define PPS_API_VERS 1
1991 +#define PPS_MAX_NAME_LEN 32
1993 +/* 32-bit vs. 64-bit compatibility.
1995 + * 0n i386, the alignment of a uint64_t is only 4 bytes, while on most other
1996 + * architectures it's 8 bytes. On i386, there will be no padding between the
1997 + * two consecutive 'struct pps_ktime' members of struct pps_kinfo and struct
1998 + * pps_kparams. But on most platforms there will be padding to ensure correct
2001 + * The simple fix is probably to add an explicit padding.
2002 + * [David Woodhouse]
2009 +#define PPS_TIME_INVALID (1<<0) /* used to specify timeout==NULL */
2012 + __u32 assert_sequence; /* seq. num. of assert event */
2013 + __u32 clear_sequence; /* seq. num. of clear event */
2014 + struct pps_ktime assert_tu; /* time of assert event */
2015 + struct pps_ktime clear_tu; /* time of clear event */
2016 + int current_mode; /* current mode bits */
2019 +struct pps_kparams {
2020 + int api_version; /* API version # */
2021 + int mode; /* mode bits */
2022 + struct pps_ktime assert_off_tu; /* offset compensation for assert */
2023 + struct pps_ktime clear_off_tu; /* offset compensation for clear */
2027 + * 3.3 Mode bit definitions
2030 +/* Device/implementation parameters */
2031 +#define PPS_CAPTUREASSERT 0x01 /* capture assert events */
2032 +#define PPS_CAPTURECLEAR 0x02 /* capture clear events */
2033 +#define PPS_CAPTUREBOTH 0x03 /* capture assert and clear events */
2035 +#define PPS_OFFSETASSERT 0x10 /* apply compensation for assert ev. */
2036 +#define PPS_OFFSETCLEAR 0x20 /* apply compensation for clear ev. */
2038 +#define PPS_CANWAIT 0x100 /* can we wait for an event? */
2039 +#define PPS_CANPOLL 0x200 /* bit reserved for future use */
2041 +/* Kernel actions */
2042 +#define PPS_ECHOASSERT 0x40 /* feed back assert event to output */
2043 +#define PPS_ECHOCLEAR 0x80 /* feed back clear event to output */
2045 +/* Timestamp formats */
2046 +#define PPS_TSFMT_TSPEC 0x1000 /* select timespec format */
2047 +#define PPS_TSFMT_NTPFP 0x2000 /* select NTP format */
2050 + * 3.4.4 New functions: disciplining the kernel timebase
2053 +/* Kernel consumers */
2054 +#define PPS_KC_HARDPPS 0 /* hardpps() (or equivalent) */
2055 +#define PPS_KC_HARDPPS_PLL 1 /* hardpps() constrained to
2056 + use a phase-locked loop */
2057 +#define PPS_KC_HARDPPS_FLL 2 /* hardpps() constrained to
2058 + use a frequency-locked loop */
2060 + * Here begins the implementation-specific part!
2064 + struct pps_kinfo info;
2065 + struct pps_ktime timeout;
2068 +#include <linux/ioctl.h>
2070 +#define PPS_CHECK _IO('P', 0)
2071 +#define PPS_GETPARAMS _IOR('P', 1, struct pps_kparams *)
2072 +#define PPS_SETPARAMS _IOW('P', 2, struct pps_kparams *)
2073 +#define PPS_GETCAP _IOR('P', 3, int *)
2074 +#define PPS_FETCH _IOWR('P', 4, struct pps_fdata *)
2078 +#include <linux/cdev.h>
2079 +#include <linux/device.h>
2081 +#define PPS_VERSION "5.0.0-rc2"
2082 +#define PPS_MAX_SOURCES 16 /* should be enought... */
2088 +/* The specific PPS source info */
2089 +struct pps_source_info {
2090 + char name[PPS_MAX_NAME_LEN]; /* simbolic name */
2091 + char path[PPS_MAX_NAME_LEN]; /* path of connected device */
2092 + int mode; /* PPS's allowed mode */
2094 + void (*echo)(int source, int event, void *data); /* PPS echo function */
2096 + struct module *owner;
2097 + struct device *dev;
2100 +/* The main struct */
2101 +struct pps_device {
2102 + struct pps_source_info info; /* PSS source info */
2104 + struct pps_kparams params; /* PPS's current params */
2106 + __u32 assert_sequence; /* PPS' assert event seq # */
2107 + __u32 clear_sequence; /* PPS' clear event seq # */
2108 + struct pps_ktime assert_tu;
2109 + struct pps_ktime clear_tu;
2110 + int current_mode; /* PPS mode at event time */
2112 + int go; /* PPS event is arrived? */
2113 + wait_queue_head_t queue; /* PPS event queue */
2115 + unsigned int id; /* PPS source unique ID */
2117 + struct device *dev;
2119 + struct fasync_struct *async_queue; /* fasync method */
2122 + atomic_t usage; /* usage count */
2123 + wait_queue_head_t usage_queue;
2125 + struct class_device class_dev;
2129 + * Exported functions
2132 +extern int pps_register_source(struct pps_source_info *info,
2133 + int default_params);
2134 +extern void pps_unregister_source(int source);
2135 +extern int pps_register_cdev(struct pps_device *pps);
2136 +extern void pps_unregister_cdev(struct pps_device *pps);
2137 +extern void pps_event(int source, int event, void *data);
2139 +extern int pps_sysfs_create_source_entry(struct pps_device *pps);
2140 +extern void pps_sysfs_remove_source_entry(struct pps_device *pps);
2142 +#endif /* __KERNEL__ */
2144 +#endif /* _PPS_H_ */
2145 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
2146 index 09d17b0..f9aefad 100644
2147 --- a/include/linux/serial_core.h
2148 +++ b/include/linux/serial_core.h
2150 #include <linux/tty.h>
2151 #include <linux/mutex.h>
2152 #include <linux/sysrq.h>
2153 +#include <linux/pps.h>
2157 @@ -236,6 +237,9 @@ struct uart_port {
2158 unsigned char regshift; /* reg offset shift */
2159 unsigned char iotype; /* io access style */
2160 unsigned char unused1;
2161 +#ifdef CONFIG_PPS_CLIENT_UART
2162 + int pps_source; /* PPS source ID */
2165 #define UPIO_PORT (0)
2166 #define UPIO_HUB6 (1)
2167 @@ -280,7 +284,8 @@ struct uart_port {
2168 #define UPF_IOREMAP ((__force upf_t) (1 << 31))
2170 #define UPF_CHANGE_MASK ((__force upf_t) (0x17fff))
2171 -#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
2172 +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY\
2175 unsigned int mctrl; /* current modem ctrl settings */
2176 unsigned int timeout; /* character-based timeout */
2177 @@ -312,6 +317,10 @@ struct uart_state {
2178 struct uart_info *info;
2179 struct uart_port *port;
2181 +#ifdef CONFIG_PPS_CLIENT_UART
2182 + struct pps_source_info pps_info;
2188 @@ -476,13 +485,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status)
2190 struct uart_info *info = port->info;
2192 - port->icount.dcd++;
2194 -#ifdef CONFIG_HARD_PPS
2195 - if ((port->flags & UPF_HARDPPS_CD) && status)
2197 +#ifdef CONFIG_PPS_CLIENT_UART
2198 + if (port->flags & UPF_HARDPPS_CD) {
2200 + pps_event(port->pps_source, PPS_CAPTUREASSERT, port);
2201 + dev_dbg(port->dev, "PPS assert at %lu on source #%d\n",
2202 + jiffies, port->pps_source);
2204 + pps_event(port->pps_source, PPS_CAPTURECLEAR, port);
2205 + dev_dbg(port->dev, "PPS clear at %lu on source #%d\n",
2206 + jiffies, port->pps_source);
2211 + port->icount.dcd++;
2213 if (info->flags & UIF_CHECK_CD) {
2215 wake_up_interruptible(&info->open_wait);