Add stub driver for ADM6996F switches (configured through MII) The driver currently...
[oweals/openwrt.git] / target / linux / generic-2.6 / patches-2.6.23 / 230-pps_support.patch
1 diff --git a/Documentation/pps/Makefile b/Documentation/pps/Makefile
2 new file mode 100644
3 index 0000000..a2660a2
4 --- /dev/null
5 +++ b/Documentation/pps/Makefile
6 @@ -0,0 +1,27 @@
7 +TARGETS = ppstest ppsctl
8 +
9 +CFLAGS += -Wall -O2 -D_GNU_SOURCE
10 +CFLAGS += -I .
11 +CFLAGS += -ggdb
12 +
13 +# -- Actions section ----------------------------------------------------------
14 +
15 +.PHONY : all depend dep
16 +
17 +all : .depend $(TARGETS)
18 +
19 +.depend depend dep :
20 +       $(CC) $(CFLAGS) -M $(TARGETS:=.c) > .depend
21 +
22 +ifeq (.depend,$(wildcard .depend))
23 +include .depend
24 +endif
25 +
26 +
27 +# -- Clean section ------------------------------------------------------------
28 +
29 +.PHONY : clean
30 +
31 +clean :
32 +       rm -f *.o *~ core .depend
33 +       rm -f ${TARGETS}
34 diff --git a/Documentation/pps/pps.txt b/Documentation/pps/pps.txt
35 new file mode 100644
36 index 0000000..9538925
37 --- /dev/null
38 +++ b/Documentation/pps/pps.txt
39 @@ -0,0 +1,170 @@
40 +
41 +                       PPS - Pulse Per Second
42 +                       ----------------------
43 +
44 +(C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com>
45 +
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.
50 +
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.
55 +
56 +
57 +
58 +Overview
59 +--------
60 +
61 +LinuxPPS provides a programming interface (API) to define into the
62 +system several PPS sources.
63 +
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.
67 +
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.
73 +
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.
77 +
78 +
79 +RFC considerations
80 +------------------
81 +
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
84 +problem:
85 +
86 +   At startup it needs a file descriptor as argument for the function
87 +   time_pps_create().
88 +
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.
96 +
97 +The problem can be simply solved if you consider that a PPS source is
98 +not always connected with a GPS data source.
99 +
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.
103 +
104 +In LinuxPPS the PPS sources are simply char devices usually mapped
105 +into files /dev/pps0, /dev/pps1, etc..
106 +
107 +
108 +Coding example
109 +--------------
110 +
111 +To register a PPS source into the kernel you should define a struct
112 +pps_source_info_s as follow:
113 +
114 +    static struct pps_source_info_s pps_ktimer_info = {
115 +            name         : "ktimer",
116 +            path         : "",
117 +            mode         : PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
118 +                          PPS_ECHOASSERT | \
119 +                           PPS_CANWAIT | PPS_TSFMT_TSPEC,
120 +            echo         : pps_ktimer_echo,
121 +            owner        : THIS_MODULE,
122 +    };
123 +
124 +and then calling the function pps_register_source() in your
125 +intialization routine as follow:
126 +
127 +    source = pps_register_source(&pps_ktimer_info,
128 +                       PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
129 +
130 +The pps_register_source() prototype is:
131 +
132 +  int pps_register_source(struct pps_source_info_s *info, int default_params)
133 +
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).
139 +
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)
142 +just using:
143 +
144 +    pps_event(source, PPS_CAPTUREASSERT, ptr);
145 +
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..
149 +
150 +Please see the file drivers/pps/clients/ktimer.c for an example code.
151 +
152 +
153 +SYSFS support
154 +-------------
155 +
156 +If the SYSFS filesystem is enabled in the kernel it provides a new class:
157 +
158 +   $ ls /sys/class/pps/
159 +   pps0/  pps1/  pps2/
160 +
161 +Every directory is the ID of a PPS sources defined into the system and
162 +inside you find several files:
163 +
164 +    $ ls /sys/class/pps/pps0/
165 +    assert     clear  echo  mode  name  path  subsystem@  uevent
166 +
167 +Inside each "assert" and "clear" file you can find the timestamp and a
168 +sequence number:
169 +
170 +    $ cat /sys/class/pps/pps0/assert
171 +    1170026870.983207967#8
172 +
173 +Where before the "#" is the timestamp in seconds and after it is the
174 +sequence number. Other files are:
175 +
176 +* echo: reports if the PPS source has an echo function or not;
177 +
178 +* mode: reports available PPS functioning modes;
179 +
180 +* name: reports the PPS source's name;
181 +
182 +* path: reports the PPS source's device path, that is the device the
183 +  PPS source is connected to (if it exists).
184 +
185 +
186 +Testing the PPS support
187 +-----------------------
188 +
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.
192 +
193 +Once you have enabled the compilation of ktimer just modprobe it (if
194 +not statically compiled):
195 +
196 +   # modprobe ktimer
197 +
198 +and the run ppstest as follow:
199 +
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
207 +
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
211 new file mode 100644
212 index 0000000..83fd08a
213 --- /dev/null
214 +++ b/Documentation/pps/ppsctl.c
215 @@ -0,0 +1,62 @@
216 +#include <stdio.h>
217 +#include <unistd.h>
218 +#include <stdlib.h>
219 +#include <errno.h>
220 +#include <sys/ioctl.h>
221 +#include <sys/types.h>
222 +#include <sys/stat.h>
223 +#include <fcntl.h>
224 +#include <string.h>
225 +#include <linux/serial.h>
226 +
227 +void usage(char *name)
228 +{
229 +       fprintf(stderr, "usage: %s <ttyS> [enable|disable]\n", name);
230 +
231 +       exit(EXIT_FAILURE);
232 +}
233 +
234 +int main(int argc, char *argv[])
235 +{
236 +       int fd;
237 +       int ret;
238 +       struct serial_struct ss;
239 +
240 +       if (argc < 2)
241 +               usage(argv[0]);
242 +
243 +       fd = open(argv[1], O_RDWR);
244 +       if (fd < 0) {
245 +               perror("open");
246 +               exit(EXIT_FAILURE);
247 +       }
248 +
249 +       ret = ioctl(fd, TIOCGSERIAL, &ss);
250 +       if (ret < 0) {
251 +               perror("ioctl(TIOCGSERIAL)");
252 +               exit(EXIT_FAILURE);
253 +       }
254 +
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);
259 +       }
260 +
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;
265 +       else {
266 +               fprintf(stderr, "invalid state argument \"%s\"\n", argv[2]);
267 +               exit(EXIT_FAILURE);
268 +       }
269 +
270 +       ret = ioctl(fd, TIOCSSERIAL, &ss);
271 +       if (ret < 0) {
272 +               perror("ioctl(TIOCSSERIAL)");
273 +               exit(EXIT_FAILURE);
274 +       }
275 +
276 +       return 0;
277 +}
278 diff --git a/Documentation/pps/ppsfind b/Documentation/pps/ppsfind
279 new file mode 100755
280 index 0000000..93c0e17
281 --- /dev/null
282 +++ b/Documentation/pps/ppsfind
283 @@ -0,0 +1,17 @@
284 +#!/bin/sh
285 +
286 +SYS="/sys/class/pps/"
287 +
288 +if [ $# -lt 1 ] ; then
289 +       echo "usage: ppsfind <name>" >&2
290 +       exit 1
291 +fi
292 +
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)"
297 +       fi
298 +done
299 +
300 +exit 0
301 diff --git a/Documentation/pps/ppstest.c b/Documentation/pps/ppstest.c
302 new file mode 100644
303 index 0000000..d125ffa
304 --- /dev/null
305 +++ b/Documentation/pps/ppstest.c
306 @@ -0,0 +1,151 @@
307 +#include <stdio.h>
308 +#include <stdlib.h>
309 +#include <unistd.h>
310 +#include <errno.h>
311 +#include <string.h>
312 +#include <sys/types.h>
313 +#include <sys/stat.h>
314 +#include <fcntl.h>
315 +
316 +#include <timepps.h>
317 +
318 +int find_source(char *path, pps_handle_t *handle, int *avail_mode)
319 +{
320 +       pps_params_t params;
321 +       int ret;
322 +
323 +       printf("trying PPS source \"%s\"\n", path);
324 +
325 +       /* Try to find the source by using the supplied "path" name */
326 +       ret = open(path, O_RDWR);
327 +       if (ret < 0) {
328 +               fprintf(stderr, "unable to open device \"%s\" (%m)\n", path);
329 +               return ret;
330 +       }
331 +
332 +       /* Open the PPS source (and check the file descriptor) */
333 +       ret = time_pps_create(ret, handle);
334 +       if (ret < 0) {
335 +               fprintf(stderr, "cannot create a PPS source from device "
336 +                               "\"%s\" (%m)\n", path);
337 +               return -1;
338 +       }
339 +       printf("found PPS source \"%s\"\n", path);
340 +
341 +       /* Find out what features are supported */
342 +       ret = time_pps_getcap(*handle, avail_mode);
343 +       if (ret < 0) {
344 +               fprintf(stderr, "cannot get capabilities (%m)\n");
345 +               return -1;
346 +       }
347 +       if ((*avail_mode & PPS_CAPTUREASSERT) == 0) {
348 +               fprintf(stderr, "cannot CAPTUREASSERT\n");
349 +               return -1;
350 +       }
351 +       if ((*avail_mode & PPS_OFFSETASSERT) == 0) {
352 +               fprintf(stderr, "cannot OFFSETASSERT\n");
353 +               return -1;
354 +       }
355 +
356 +       /* Capture assert timestamps, and compensate for a 675 nsec
357 +        * propagation delay */
358 +       ret = time_pps_getparams(*handle, &params);
359 +       if (ret < 0) {
360 +               fprintf(stderr, "cannot get parameters (%m)\n");
361 +               return -1;
362 +       }
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, &params);
367 +       if (ret < 0) {
368 +               fprintf(stderr, "cannot set parameters (%m)\n");
369 +               return -1;
370 +       }
371 +
372 +       return 0;
373 +}
374 +
375 +int fetch_source(int i, pps_handle_t *handle, int *avail_mode)
376 +{
377 +       struct timespec timeout;
378 +       pps_info_t infobuf;
379 +       int ret;
380 +
381 +       /* create a zero-valued timeout */
382 +       timeout.tv_sec = 3;
383 +       timeout.tv_nsec = 0;
384 +
385 +retry:
386 +       if (*avail_mode & PPS_CANWAIT) /* waits for the next event */
387 +               ret = time_pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,
388 +                                  &timeout);
389 +       else {
390 +               sleep(1);
391 +               ret = time_pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,
392 +                                  &timeout);
393 +       }
394 +       if (ret < 0) {
395 +               if (ret == -EINTR) {
396 +                       fprintf(stderr, "time_pps_fetch() got a signal!\n");
397 +                       goto retry;
398 +               }
399 +
400 +               fprintf(stderr, "time_pps_fetch() error %d (%m)\n", ret);
401 +               return -1;
402 +       }
403 +
404 +       printf("source %d - "
405 +              "assert %ld.%09ld, sequence: %ld - "
406 +              "clear  %ld.%09ld, sequence: %ld\n",
407 +              i,
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);
413 +
414 +       return 0;
415 +}
416 +
417 +void usage(char *name)
418 +{
419 +       fprintf(stderr, "usage: %s <ppsdev> [<ppsdev> ...]\n", name);
420 +       exit(EXIT_FAILURE);
421 +}
422 +
423 +int main(int argc, char *argv[])
424 +{
425 +       int num;
426 +       pps_handle_t handle[4];
427 +       int avail_mode[4];
428 +       int i = 0;
429 +       int ret;
430 +
431 +       /* Check the command line */
432 +       if (argc < 2)
433 +               usage(argv[0]);
434 +
435 +       for (i = 1; i < argc && i <= 4; i++) {
436 +               ret = find_source(argv[i], &handle[i - 1], &avail_mode[i - 1]);
437 +               if (ret < 0)
438 +                       exit(EXIT_FAILURE);
439 +       }
440 +
441 +       num = i - 1;
442 +       printf("ok, found %d source(s), now start fetching data...\n", num);
443 +
444 +       /* loop, printing the most recent timestamp every second or so */
445 +       while (1) {
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);
450 +               }
451 +       }
452 +
453 +       for (; i >= 0; i--)
454 +               time_pps_destroy(handle[i]);
455 +
456 +       return 0;
457 +}
458 diff --git a/Documentation/pps/timepps.h b/Documentation/pps/timepps.h
459 new file mode 100644
460 index 0000000..28ebf4c
461 --- /dev/null
462 +++ b/Documentation/pps/timepps.h
463 @@ -0,0 +1,193 @@
464 +/*
465 + * timepps.h -- PPS API main header
466 + *
467 + * Copyright (C) 2005-2007   Rodolfo Giometti <giometti@linux.it>
468 + *
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.
473 + *
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.
478 + *
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.
482 + */
483 +
484 +#ifndef _SYS_TIMEPPS_H_
485 +#define _SYS_TIMEPPS_H_
486 +
487 +#include <sys/syscall.h>
488 +#include <unistd.h>
489 +#include <errno.h>
490 +#include <linux/pps.h>
491 +
492 +/*
493 + * New data structures
494 + */
495 +
496 +struct ntp_fp {
497 +       unsigned int integral;
498 +       unsigned int fractional;
499 +};
500 +
501 +union pps_timeu {
502 +       struct timespec tspec;
503 +       struct ntp_fp ntpfp;
504 +       unsigned long longpad[3];
505 +};
506 +
507 +struct pps_info {
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 */
513 +};
514 +
515 +struct pps_params {
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 */
520 +};
521 +
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;
528 +
529 +#define assert_timestamp        assert_tu.tspec
530 +#define clear_timestamp         clear_tu.tspec
531 +
532 +#define assert_timestamp_ntpfp  assert_tu.ntpfp
533 +#define clear_timestamp_ntpfp   clear_tu.ntpfp
534 +
535 +#define assert_offset          assert_off_tu.tspec
536 +#define clear_offset           clear_off_tu.tspec
537 +
538 +#define assert_offset_ntpfp     assert_off_tu.ntpfp
539 +#define clear_offset_ntpfp      clear_off_tu.ntpfp
540 +
541 +/*
542 + * The PPS API
543 + */
544 +
545 +static __inline int time_pps_create(int source, pps_handle_t *handle)
546 +{
547 +       int ret;
548 +
549 +       if (!handle) {
550 +               errno = EINVAL;
551 +               return -1;
552 +       }
553 +
554 +       /* First we check if current device is a PPS valid PPS one...
555 +        */
556 +       ret = ioctl(source, PPS_CHECK);
557 +       if (ret) {
558 +               errno = EOPNOTSUPP;
559 +               return -1;
560 +       }
561 +
562 +       /* ... then since in LinuxPPS there are no differences between a
563 +        * "PPS source" and a "PPS handle", we simply return the same value.
564 +        */
565 +       *handle = source;
566 +
567 +       return 0;
568 +}
569 +
570 +static __inline int time_pps_destroy(pps_handle_t handle)
571 +{
572 +       return close(handle);
573 +}
574 +
575 +static __inline int time_pps_getparams(pps_handle_t handle,
576 +                                       pps_params_t *ppsparams)
577 +{
578 +       int ret;
579 +       struct pps_kparams __ppsparams;
580 +
581 +       ret = ioctl(handle, PPS_GETPARAMS, &__ppsparams);
582 +
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;
589 +
590 +       return ret;
591 +}
592 +
593 +static __inline int time_pps_setparams(pps_handle_t handle,
594 +                                       const pps_params_t *ppsparams)
595 +{
596 +       struct pps_kparams __ppsparams;
597 +
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;
604 +
605 +       return ioctl(handle, PPS_SETPARAMS, &__ppsparams);
606 +}
607 +
608 +/* Get capabilities for handle */
609 +static __inline int time_pps_getcap(pps_handle_t handle, int *mode)
610 +{
611 +       return ioctl(handle, PPS_GETCAP, mode);
612 +}
613 +
614 +static __inline int time_pps_fetch(pps_handle_t handle, const int tsformat,
615 +                                       pps_info_t *ppsinfobuf,
616 +                                       const struct timespec *timeout)
617 +{
618 +       struct pps_fdata __fdata;
619 +       int ret;
620 +
621 +       /* Sanity checks */
622 +       if (tsformat != PPS_TSFMT_TSPEC) {
623 +               errno = EINVAL;
624 +               return -1;
625 +       }
626 +
627 +       if (timeout) {
628 +               __fdata.timeout.sec = timeout->tv_sec;
629 +               __fdata.timeout.nsec = timeout->tv_nsec;
630 +               __fdata.timeout.flags = ~PPS_TIME_INVALID;
631 +       } else
632 +               __fdata.timeout.flags = PPS_TIME_INVALID;
633 +
634 +       ret = ioctl(handle, PPS_FETCH, &__fdata);
635 +
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;
643 +
644 +       return ret;
645 +}
646 +
647 +static __inline int time_pps_kcbind(pps_handle_t handle,
648 +                                       const int kernel_consumer,
649 +                                       const int edge, const int tsformat)
650 +{
651 +       /* LinuxPPS doesn't implement kernel consumer feature */
652 +       errno = EOPNOTSUPP;
653 +       return -1;
654 +}
655 +
656 +#endif                         /* _SYS_TIMEPPS_H_ */
657 diff --git a/MAINTAINERS b/MAINTAINERS
658 index 9a91d9e..f45e974 100644
659 --- a/MAINTAINERS
660 +++ b/MAINTAINERS
661 @@ -3011,6 +3011,13 @@ P:       James Chapman
662  M:     jchapman@katalix.com
663  S:     Maintained
664  
665 +PPS SUPPORT
666 +P:     Rodolfo Giometti
667 +M:     giometti@enneenne.com
668 +W:     http://wiki.enneenne.com/index.php/LinuxPPS_support
669 +L:     linuxpps@ml.enneenne.com
670 +S:     Maintained
671 +
672  PREEMPTIBLE KERNEL
673  P:     Robert Love
674  M:     rml@tech9.net
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"
680  
681  source "drivers/spi/Kconfig"
682  
683 +source "drivers/pps/Kconfig"
684 +
685  source "drivers/w1/Kconfig"
686  
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/
695  obj-y                          += i2c/
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 = {
705  
706  #endif /* console on line printer */
707  
708 +/* Support for PPS signal on the line printer */
709 +
710 +#ifdef CONFIG_PPS_CLIENT_LP
711 +
712 +static void lp_pps_echo(int source, int event, void *data)
713 +{
714 +       struct parport *port = data;
715 +       unsigned char status = parport_read_status(port);
716 +
717 +       /* echo event via SEL bit */
718 +       parport_write_control(port,
719 +               parport_read_control(port) | PARPORT_CONTROL_SELECT);
720 +
721 +       /* signal no event */
722 +       if ((status & PARPORT_STATUS_ACK) != 0)
723 +               parport_write_control(port,
724 +                       parport_read_control(port) & ~PARPORT_CONTROL_SELECT);
725 +}
726 +
727 +#endif
728 +
729  /* --- initialisation code ------------------------------------- */
730  
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)
733         }
734  #endif
735  
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);
740 +
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);
744 +
745 +               port->pps_info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
746 +                               PPS_ECHOASSERT | \
747 +                               PPS_CANWAIT | PPS_TSFMT_TSPEC;
748 +
749 +               port->pps_info.echo = lp_pps_echo;
750 +
751 +               port->pps_source = pps_register_source(&(port->pps_info),
752 +                               PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
753 +               if (port->pps_source < 0)
754 +                       dev_err(port->dev,
755 +                                       "cannot register PPS source \"%s\"\n",
756 +                                       port->pps_info.path);
757 +               else
758 +                       dev_info(port->dev, "PPS source #%d \"%s\" added\n",
759 +                                       port->pps_source, port->pps_info.path);
760 +       } else {
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);
765 +       }
766 +#endif
767 +
768         return 0;
769  }
770  
771 @@ -860,6 +913,14 @@ static void lp_detach (struct parport *port)
772                 console_registered = NULL;
773         }
774  #endif /* CONFIG_LP_CONSOLE */
775 +
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);
781 +       }
782 +#endif
783  }
784  
785  static struct parport_driver lp_driver = {
786 diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig
787 new file mode 100644
788 index 0000000..bfe6621
789 --- /dev/null
790 +++ b/drivers/pps/Kconfig
791 @@ -0,0 +1,34 @@
792 +#
793 +# PPS support configuration
794 +#
795 +
796 +menu "PPS support"
797 +
798 +config PPS
799 +       tristate "PPS support"
800 +       depends on EXPERIMENTAL
801 +       ---help---
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.
804 +
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.
808 +
809 +         Some antennae's PPS signals are connected with some special host
810 +         inputs so you have to enable the corresponding client support.
811 +
812 +         To compile this driver as a module, choose M here: the module
813 +         will be called pps_core.ko.
814 +
815 +config PPS_DEBUG
816 +       bool "PPS debugging messages"
817 +       depends on PPS 
818 +       help
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.
822 +
823 +source drivers/pps/clients/Kconfig
824 +
825 +endmenu
826 diff --git a/drivers/pps/Makefile b/drivers/pps/Makefile
827 new file mode 100644
828 index 0000000..d8ec308
829 --- /dev/null
830 +++ b/drivers/pps/Makefile
831 @@ -0,0 +1,11 @@
832 +#
833 +# Makefile for the PPS core.
834 +#
835 +
836 +pps_core-objs                  += pps.o kapi.o sysfs.o
837 +obj-$(CONFIG_PPS)              += pps_core.o
838 +obj-y                          += clients/
839 +
840 +ifeq ($(CONFIG_PPS_DEBUG),y)
841 +EXTRA_CFLAGS += -DDEBUG
842 +endif
843 diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
844 new file mode 100644
845 index 0000000..09ba5c3
846 --- /dev/null
847 +++ b/drivers/pps/clients/Kconfig
848 @@ -0,0 +1,38 @@
849 +#
850 +# PPS clients configuration
851 +#
852 +
853 +if PPS
854 +
855 +comment "PPS clients support"
856 +
857 +config PPS_CLIENT_KTIMER
858 +       tristate "Kernel timer client (Testing client, use for debug)"
859 +       help
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.
862 +
863 +         This driver can also be built as a module.  If so, the module
864 +         will be called ktimer.ko.
865 +
866 +comment "UART serial support (forced off)"
867 +       depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y))
868 +
869 +config PPS_CLIENT_UART
870 +       bool "UART serial support"
871 +       depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)
872 +       help
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.
875 +
876 +comment "Parallel printer support (forced off)"
877 +       depends on !( PRINTER != n && !(PPS = m && PRINTER = y))
878 +
879 +config PPS_CLIENT_LP
880 +       bool "Parallel printer support"
881 +       depends on PRINTER != n && !(PPS = m && PRINTER = y)
882 +       help
883 +         If you say yes here you get support for a PPS source connected
884 +         with the interrupt pin of your parallel port.
885 +
886 +endif
887 diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
888 new file mode 100644
889 index 0000000..f3c1e39
890 --- /dev/null
891 +++ b/drivers/pps/clients/Makefile
892 @@ -0,0 +1,9 @@
893 +#
894 +# Makefile for PPS clients.
895 +#
896 +
897 +obj-$(CONFIG_PPS_CLIENT_KTIMER)        += ktimer.o
898 +
899 +ifeq ($(CONFIG_PPS_DEBUG),y)
900 +EXTRA_CFLAGS += -DDEBUG
901 +endif
902 diff --git a/drivers/pps/clients/ktimer.c b/drivers/pps/clients/ktimer.c
903 new file mode 100644
904 index 0000000..4d613ab
905 --- /dev/null
906 +++ b/drivers/pps/clients/ktimer.c
907 @@ -0,0 +1,114 @@
908 +/*
909 + * ktimer.c -- kernel timer test client
910 + *
911 + *
912 + * Copyright (C) 2005-2006   Rodolfo Giometti <giometti@linux.it>
913 + *
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.
918 + *
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.
923 + *
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.
927 + */
928 +
929 +
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>
935 +
936 +#include <linux/pps.h>
937 +
938 +/*
939 + * Global variables
940 + */
941 +
942 +static int source;
943 +static struct timer_list ktimer;
944 +
945 +/*
946 + * The kernel timer
947 + */
948 +
949 +static void pps_ktimer_event(unsigned long ptr)
950 +{
951 +       pr_info("PPS event at %lu\n", jiffies);
952 +
953 +       pps_event(source, PPS_CAPTUREASSERT, NULL);
954 +
955 +       mod_timer(&ktimer, jiffies + HZ);
956 +}
957 +
958 +/*
959 + * The echo function
960 + */
961 +
962 +static void pps_ktimer_echo(int source, int event, void *data)
963 +{
964 +       pr_info("echo %s %s for source %d\n",
965 +               event & PPS_CAPTUREASSERT ? "assert" : "",
966 +               event & PPS_CAPTURECLEAR ? "clear" : "",
967 +               source);
968 +}
969 +
970 +/*
971 + * The PPS info struct
972 + */
973 +
974 +static struct pps_source_info pps_ktimer_info = {
975 +       name            : "ktimer",
976 +       path            : "",
977 +       mode            : PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
978 +                         PPS_ECHOASSERT | \
979 +                         PPS_CANWAIT | PPS_TSFMT_TSPEC,
980 +       echo            : pps_ktimer_echo,
981 +       owner           : THIS_MODULE,
982 +};
983 +
984 +/*
985 + * Module staff
986 + */
987 +
988 +static void __exit pps_ktimer_exit(void)
989 +{
990 +       del_timer_sync(&ktimer);
991 +       pps_unregister_source(source);
992 +
993 +       pr_info("ktimer PPS source unregistered\n");
994 +}
995 +
996 +static int __init pps_ktimer_init(void)
997 +{
998 +       int ret;
999 +
1000 +       ret = pps_register_source(&pps_ktimer_info,
1001 +                               PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
1002 +       if (ret < 0) {
1003 +               printk(KERN_ERR "cannot register ktimer source\n");
1004 +               return ret;
1005 +       }
1006 +       source = ret;
1007 +
1008 +       setup_timer(&ktimer, pps_ktimer_event, 0);
1009 +       mod_timer(&ktimer, jiffies + HZ);
1010 +
1011 +       pr_info("ktimer PPS source registered at %d\n", source);
1012 +
1013 +       return  0;
1014 +}
1015 +
1016 +module_init(pps_ktimer_init);
1017 +module_exit(pps_ktimer_exit);
1018 +
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
1025 --- /dev/null
1026 +++ b/drivers/pps/kapi.c
1027 @@ -0,0 +1,271 @@
1028 +/*
1029 + * kapi.c -- kernel API
1030 + *
1031 + *
1032 + * Copyright (C) 2005-2007   Rodolfo Giometti <giometti@linux.it>
1033 + *
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.
1038 + *
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.
1043 + *
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.
1047 + */
1048 +
1049 +
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>
1059 +
1060 +/*
1061 + * Local variables
1062 + */
1063 +
1064 +static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED;
1065 +static DEFINE_IDR(pps_idr);
1066 +
1067 +/*
1068 + * Local functions
1069 + */
1070 +
1071 +static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
1072 +{
1073 +       ts->nsec += offset->nsec;
1074 +       if (ts->nsec >= NSEC_PER_SEC) {
1075 +               ts->nsec -= NSEC_PER_SEC;
1076 +               ts->sec++;
1077 +       } else if (ts->nsec < 0) {
1078 +               ts->nsec += NSEC_PER_SEC;
1079 +               ts->sec--;
1080 +       }
1081 +       ts->sec += offset->sec;
1082 +}
1083 +
1084 +/*
1085 + * Exported functions
1086 + */
1087 +
1088 +int pps_register_source(struct pps_source_info *info, int default_params)
1089 +{
1090 +       struct pps_device *pps;
1091 +       int id;
1092 +       int err;
1093 +
1094 +       /* Sanity checks */
1095 +       if ((info->mode & default_params) != default_params) {
1096 +               printk(KERN_ERR "pps: %s: unsupported default parameters\n",
1097 +                                       info->name);
1098 +               err = -EINVAL;
1099 +               goto pps_register_source_exit;
1100 +       }
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",
1104 +                                       info->name);
1105 +               err = -EINVAL;
1106 +               goto pps_register_source_exit;
1107 +       }
1108 +       if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
1109 +               printk(KERN_ERR "pps: %s: unspecified time format\n",
1110 +                                       info->name);
1111 +               err = -EINVAL;
1112 +               goto pps_register_source_exit;
1113 +       }
1114 +
1115 +       /* Allocate memory for the new PPS source struct */
1116 +       pps = kzalloc(sizeof(struct pps_device), GFP_KERNEL);
1117 +       if (pps == NULL) {
1118 +               err = -ENOMEM;
1119 +               goto pps_register_source_exit;
1120 +       }
1121 +
1122 +       /* Get new ID for the new PPS source */
1123 +       if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) {
1124 +               err = -ENOMEM;
1125 +               goto kfree_pps;
1126 +       }
1127 +
1128 +       spin_lock_irq(&idr_lock);
1129 +       err = idr_get_new(&pps_idr, pps, &id);
1130 +       spin_unlock_irq(&idr_lock);
1131 +
1132 +       if (err < 0)
1133 +               goto kfree_pps;
1134 +
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",
1138 +                                       info->name);
1139 +               err = -EBUSY;
1140 +               goto free_idr;
1141 +       }
1142 +
1143 +       pps->id = id;
1144 +       pps->params.api_version = PPS_API_VERS;
1145 +       pps->params.mode = default_params;
1146 +       pps->info = *info;
1147 +
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);
1152 +
1153 +       /* Create the char device */
1154 +       err = pps_register_cdev(pps);
1155 +       if (err < 0) {
1156 +               printk(KERN_ERR "pps: %s: unable to create char device\n",
1157 +                                       info->name);
1158 +               goto free_idr;
1159 +       }
1160 +
1161 +       /* Create the sysfs entry */
1162 +       err = pps_sysfs_create_source_entry(pps);
1163 +       if (err < 0) {
1164 +               printk(KERN_ERR "pps: %s: unable to create sysfs entries\n",
1165 +                                       info->name);
1166 +               goto unregister_cdev;
1167 +       }
1168 +
1169 +       pr_info("new PPS source %s at ID %d\n", info->name, id);
1170 +
1171 +       return id;
1172 +
1173 +unregister_cdev:
1174 +       pps_unregister_cdev(pps);
1175 +
1176 +free_idr:
1177 +       spin_lock_irq(&idr_lock);
1178 +       idr_remove(&pps_idr, id);
1179 +       spin_unlock_irq(&idr_lock);
1180 +
1181 +kfree_pps:
1182 +       kfree(pps);
1183 +
1184 +pps_register_source_exit:
1185 +       printk(KERN_ERR "pps: %s: unable to register source\n", info->name);
1186 +
1187 +       return err;
1188 +}
1189 +EXPORT_SYMBOL(pps_register_source);
1190 +
1191 +void pps_unregister_source(int source)
1192 +{
1193 +       struct pps_device *pps;
1194 +
1195 +       spin_lock_irq(&idr_lock);
1196 +       pps = idr_find(&pps_idr, source);
1197 +
1198 +       if (!pps) {
1199 +               spin_unlock_irq(&idr_lock);
1200 +               return;
1201 +       }
1202 +
1203 +       /* This should be done first in order to deny IRQ handlers
1204 +        * to access PPS structs
1205 +        */
1206 +
1207 +       idr_remove(&pps_idr, pps->id);
1208 +       spin_unlock_irq(&idr_lock);
1209 +
1210 +       wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0);
1211 +
1212 +       pps_sysfs_remove_source_entry(pps);
1213 +       pps_unregister_cdev(pps);
1214 +       kfree(pps);
1215 +}
1216 +EXPORT_SYMBOL(pps_unregister_source);
1217 +
1218 +void pps_event(int source, int event, void *data)
1219 +{
1220 +       struct pps_device *pps;
1221 +       struct timespec __ts;
1222 +       struct pps_ktime ts;
1223 +       unsigned long flags;
1224 +
1225 +       /* First of all we get the time stamp... */
1226 +       getnstimeofday(&__ts);
1227 +
1228 +       /* ... and translate it to PPS time data struct */
1229 +       ts.sec = __ts.tv_sec;
1230 +       ts.nsec = __ts.tv_nsec;
1231 +
1232 +       if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0 ) {
1233 +               printk(KERN_ERR "pps: unknown event (%x) for source %d\n",
1234 +                       event, source);
1235 +               return;
1236 +       }
1237 +
1238 +       spin_lock_irqsave(&idr_lock, flags);
1239 +       pps = idr_find(&pps_idr, source);
1240 +
1241 +       /* If we find a valid PPS source we lock it before leaving
1242 +        * the lock!
1243 +        */
1244 +       if (pps)
1245 +               atomic_inc(&pps->usage);
1246 +       spin_unlock_irqrestore(&idr_lock, flags);
1247 +
1248 +       if (!pps)
1249 +               return;
1250 +
1251 +       pr_debug("PPS event on source %d at at %llu.%06u\n",
1252 +                       pps->id, ts.sec, ts.nsec);
1253 +
1254 +       spin_lock_irqsave(&pps->lock, flags);
1255 +
1256 +       /* Must call the echo function? */
1257 +       if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)))
1258 +               pps->info.echo(source, event, data);
1259 +
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);
1266 +
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);
1272 +       }
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);
1277 +
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);
1283 +       }
1284 +
1285 +       pps->go = ~0;
1286 +       wake_up_interruptible(&pps->queue);
1287 +
1288 +       kill_fasync(&pps->async_queue, SIGIO, POLL_IN);
1289 +
1290 +       spin_unlock_irqrestore(&pps->lock, flags);
1291 +
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);
1297 +}
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
1302 --- /dev/null
1303 +++ b/drivers/pps/pps.c
1304 @@ -0,0 +1,332 @@
1305 +/*
1306 + * pps.c -- Main PPS support file
1307 + *
1308 + *
1309 + * Copyright (C) 2005-2007   Rodolfo Giometti <giometti@linux.it>
1310 + *
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.
1315 + *
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.
1320 + *
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.
1324 + */
1325 +
1326 +
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>
1336 +
1337 +/*
1338 + * Local variables
1339 + */
1340 +
1341 +static dev_t pps_devt;
1342 +static struct class *pps_class;
1343 +
1344 +/*
1345 + * Char device methods
1346 + */
1347 +
1348 +static unsigned int pps_cdev_poll(struct file *file, poll_table *wait)
1349 +{
1350 +       struct pps_device *pps = file->private_data;
1351 +
1352 +       poll_wait(file, &pps->queue, wait);
1353 +
1354 +       return POLLIN | POLLRDNORM;
1355 +}
1356 +
1357 +static int pps_cdev_fasync(int fd, struct file *file, int on)
1358 +{
1359 +       struct pps_device *pps = file->private_data;
1360 +       return fasync_helper(fd, file, on, &pps->async_queue);
1361 +}
1362 +
1363 +static int pps_cdev_ioctl(struct inode *inode, struct file *file,
1364 +               unsigned int cmd, unsigned long arg)
1365 +{
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;
1372 +       int err;
1373 +
1374 +       switch (cmd) {
1375 +       case PPS_CHECK:
1376 +
1377 +               /* This does nothing but signal we are a PPS source... */
1378 +
1379 +               return 0;
1380 +
1381 +       case PPS_GETPARAMS:
1382 +               pr_debug("PPS_GETPARAMS: source %d\n", pps->id);
1383 +
1384 +               /* Sanity checks */
1385 +               if (!uarg)
1386 +                       return -EINVAL;
1387 +
1388 +               /* Return current parameters */
1389 +               err = copy_to_user(uarg, &pps->params,
1390 +                                               sizeof(struct pps_kparams));
1391 +               if (err)
1392 +                       return -EFAULT;
1393 +
1394 +               break;
1395 +
1396 +       case PPS_SETPARAMS:
1397 +               pr_debug("PPS_SETPARAMS: source %d\n", pps->id);
1398 +
1399 +               /* Check the capabilities */
1400 +               if (!capable(CAP_SYS_TIME))
1401 +                       return -EPERM;
1402 +
1403 +               /* Sanity checks */
1404 +               if (!uarg)
1405 +                       return -EINVAL;
1406 +               err = copy_from_user(&params, uarg, sizeof(struct pps_kparams));
1407 +               if (err)
1408 +                       return -EFAULT;
1409 +               if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
1410 +                       pr_debug("capture mode unspecified (%x)\n",
1411 +                                                               params.mode);
1412 +                       return -EINVAL;
1413 +               }
1414 +
1415 +               /* Check for supported capabilities */
1416 +               if ((params.mode & ~pps->info.mode) != 0) {
1417 +                       pr_debug("unsupported capabilities (%x)\n",
1418 +                                                               params.mode);
1419 +                       return -EINVAL;
1420 +               }
1421 +
1422 +               spin_lock_irq(&pps->lock);
1423 +
1424 +               /* Save the new parameters */
1425 +               pps->params = params;
1426 +
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",
1431 +                                                               params.mode);
1432 +                       pps->params.mode |= PPS_TSFMT_TSPEC;
1433 +               }
1434 +               if (pps->info.mode & PPS_CANWAIT)
1435 +                       pps->params.mode |= PPS_CANWAIT;
1436 +               pps->params.api_version = PPS_API_VERS;
1437 +
1438 +               spin_unlock_irq(&pps->lock);
1439 +
1440 +               break;
1441 +
1442 +       case PPS_GETCAP:
1443 +               pr_debug("PPS_GETCAP: source %d\n", pps->id);
1444 +
1445 +               /* Sanity checks */
1446 +               if (!uarg)
1447 +                       return -EINVAL;
1448 +
1449 +               err = put_user(pps->info.mode, iuarg);
1450 +               if (err)
1451 +                       return -EFAULT;
1452 +
1453 +               break;
1454 +
1455 +       case PPS_FETCH:
1456 +               pr_debug("PPS_FETCH: source %d\n", pps->id);
1457 +
1458 +               if (!uarg)
1459 +                       return -EINVAL;
1460 +               err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
1461 +               if (err)
1462 +                       return -EFAULT;
1463 +
1464 +               pps->go = 0;
1465 +
1466 +               /* Manage the timeout */
1467 +               if (fdata.timeout.flags & PPS_TIME_INVALID)
1468 +                       err = wait_event_interruptible(pps->queue, pps->go);
1469 +               else {
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);
1474 +
1475 +                       if (ticks != 0) {
1476 +                               err = wait_event_interruptible_timeout(
1477 +                                               pps->queue, pps->go, ticks);
1478 +                               if (err == 0)
1479 +                                       return -ETIMEDOUT;
1480 +                       }
1481 +               }
1482 +
1483 +               /* Check for pending signals */
1484 +               if (err == -ERESTARTSYS) {
1485 +                       pr_debug("pending signal caught\n");
1486 +                       return -EINTR;
1487 +               }
1488 +
1489 +               /* Return the fetched timestamp */
1490 +               spin_lock_irq(&pps->lock);
1491 +
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;
1497 +
1498 +               spin_unlock_irq(&pps->lock);
1499 +
1500 +               err = copy_to_user(uarg, &fdata, sizeof(struct pps_fdata));
1501 +               if (err)
1502 +                       return -EFAULT;
1503 +
1504 +               break;
1505 +
1506 +       default:
1507 +               return -ENOTTY;
1508 +               break;
1509 +       }
1510 +
1511 +       return 0;
1512 +}
1513 +
1514 +static int pps_cdev_open(struct inode *inode, struct file *file)
1515 +{
1516 +       struct pps_device *pps = container_of(inode->i_cdev,
1517 +                                               struct pps_device, cdev);
1518 +
1519 +       /* Lock the PPS source against (possible) deregistration */
1520 +       atomic_inc(&pps->usage);
1521 +
1522 +       file->private_data = pps;
1523 +
1524 +       return 0;
1525 +}
1526 +
1527 +static int pps_cdev_release(struct inode *inode, struct file *file)
1528 +{
1529 +       struct pps_device *pps = file->private_data;
1530 +
1531 +       /* Free the PPS source and wake up (possible) deregistration */
1532 +       atomic_dec(&pps->usage);
1533 +       wake_up_all(&pps->usage_queue);
1534 +
1535 +       return 0;
1536 +}
1537 +
1538 +/*
1539 + * Char device stuff
1540 + */
1541 +
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,
1550 +};
1551 +
1552 +int pps_register_cdev(struct pps_device *pps)
1553 +{
1554 +       int err;
1555 +
1556 +       pps->devno = MKDEV(MAJOR(pps_devt), pps->id);
1557 +       cdev_init(&pps->cdev, &pps_cdev_fops);
1558 +       pps->cdev.owner = pps->info.owner;
1559 +
1560 +       err = cdev_add(&pps->cdev, pps->devno, 1);
1561 +       if (err) {
1562 +               printk(KERN_ERR "pps: %s: failed to add char device %d:%d\n",
1563 +                               pps->info.name, MAJOR(pps_devt), pps->id);
1564 +               return err;
1565 +       }
1566 +       pps->dev = device_create(pps_class, pps->info.dev, pps->devno,
1567 +                                                       "pps%d", pps->id);
1568 +       if (err)
1569 +               goto del_cdev;
1570 +       dev_set_drvdata(pps->dev, pps);
1571 +
1572 +       pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
1573 +                       MAJOR(pps_devt), pps->id);
1574 +
1575 +       return 0;
1576 +
1577 +del_cdev:
1578 +       cdev_del(&pps->cdev);
1579 +
1580 +       return err;
1581 +}
1582 +
1583 +void pps_unregister_cdev(struct pps_device *pps)
1584 +{
1585 +       device_destroy(pps_class, pps->devno);
1586 +       cdev_del(&pps->cdev);
1587 +}
1588 +
1589 +/*
1590 + * Module staff
1591 + */
1592 +
1593 +static void __exit pps_exit(void)
1594 +{
1595 +       class_destroy(pps_class);
1596 +
1597 +       if (pps_devt)
1598 +               unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
1599 +
1600 +       pr_info("LinuxPPS API ver. %d removed\n", PPS_API_VERS);
1601 +}
1602 +
1603 +static int __init pps_init(void)
1604 +{
1605 +       int err;
1606 +
1607 +       pps_class = class_create(THIS_MODULE, "pps");
1608 +       if (!pps_class) {
1609 +               printk(KERN_ERR "pps: ailed to allocate class\n");
1610 +               return -ENOMEM;
1611 +       }
1612 +
1613 +       err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
1614 +       if (err < 0) {
1615 +               printk(KERN_ERR "pps: failed to allocate char device region\n");
1616 +               goto remove_class;
1617 +       }
1618 +
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);
1622 +
1623 +       return 0;
1624 +
1625 +remove_class:
1626 +       class_destroy(pps_class);
1627 +
1628 +       return err;
1629 +}
1630 +
1631 +subsys_initcall(pps_init);
1632 +module_exit(pps_exit);
1633 +
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
1640 --- /dev/null
1641 +++ b/drivers/pps/sysfs.c
1642 @@ -0,0 +1,124 @@
1643 +/*
1644 + * sysfs.c -- sysfs support
1645 + *
1646 + *
1647 + * Copyright (C) 2007   Rodolfo Giometti <giometti@linux.it>
1648 + *
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.
1653 + *
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.
1658 + *
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.
1662 + */
1663 +
1664 +
1665 +#include <linux/device.h>
1666 +#include <linux/module.h>
1667 +#include <linux/string.h>
1668 +#include <linux/pps.h>
1669 +
1670 +/*
1671 + * Attribute functions
1672 + */
1673 +
1674 +static ssize_t pps_show_assert(struct device *dev,
1675 +                               struct device_attribute *attr, char *buf)
1676 +{
1677 +       struct pps_device *pps = dev_get_drvdata(dev);
1678 +
1679 +       return sprintf(buf, "%lld.%09d#%d\n",
1680 +                       pps->assert_tu.sec, pps->assert_tu.nsec,
1681 +                       pps->assert_sequence);
1682 +}
1683 +DEVICE_ATTR(assert, S_IRUGO, pps_show_assert, NULL);
1684 +
1685 +static ssize_t pps_show_clear(struct device *dev,
1686 +                               struct device_attribute *attr, char *buf)
1687 +{
1688 +       struct pps_device *pps = dev_get_drvdata(dev);
1689 +
1690 +       return sprintf(buf, "%lld.%09d#%d\n",
1691 +                       pps->clear_tu.sec, pps->clear_tu.nsec,
1692 +                       pps->clear_sequence);
1693 +}
1694 +DEVICE_ATTR(clear, S_IRUGO, pps_show_clear, NULL);
1695 +
1696 +static ssize_t pps_show_mode(struct device *dev,
1697 +                               struct device_attribute *attr, char *buf)
1698 +{
1699 +       struct pps_device *pps = dev_get_drvdata(dev);
1700 +
1701 +       return sprintf(buf, "%4x\n", pps->info.mode);
1702 +}
1703 +DEVICE_ATTR(mode, S_IRUGO, pps_show_mode, NULL);
1704 +
1705 +static ssize_t pps_show_echo(struct device *dev,
1706 +                               struct device_attribute *attr, char *buf)
1707 +{
1708 +       struct pps_device *pps = dev_get_drvdata(dev);
1709 +
1710 +       return sprintf(buf, "%d\n", !!pps->info.echo);
1711 +}
1712 +DEVICE_ATTR(echo, S_IRUGO, pps_show_echo, NULL);
1713 +
1714 +static ssize_t pps_show_name(struct device *dev,
1715 +                               struct device_attribute *attr, char *buf)
1716 +{
1717 +       struct pps_device *pps = dev_get_drvdata(dev);
1718 +
1719 +       return sprintf(buf, "%s\n", pps->info.name);
1720 +}
1721 +DEVICE_ATTR(name, S_IRUGO, pps_show_name, NULL);
1722 +
1723 +static ssize_t pps_show_path(struct device *dev,
1724 +                               struct device_attribute *attr, char *buf)
1725 +{
1726 +       struct pps_device *pps = dev_get_drvdata(dev);
1727 +
1728 +       return sprintf(buf, "%s\n", pps->info.path);
1729 +}
1730 +DEVICE_ATTR(path, S_IRUGO, pps_show_path, NULL);
1731 +
1732 +/*
1733 + * Public functions
1734 + */
1735 +
1736 +void pps_sysfs_remove_source_entry(struct pps_device *pps)
1737 +{
1738 +       /* Delete info files */
1739 +       if (pps->info.mode & PPS_CAPTUREASSERT)
1740 +               device_remove_file(pps->dev, &dev_attr_assert);
1741 +
1742 +       if (pps->info.mode & PPS_CAPTURECLEAR)
1743 +               device_remove_file(pps->dev, &dev_attr_clear);
1744 +
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);
1749 +}
1750 +
1751 +int pps_sysfs_create_source_entry(struct pps_device *pps)
1752 +{
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);
1756 +
1757 +       if (pps->info.mode & PPS_CAPTURECLEAR)
1758 +               device_create_file(pps->dev, &dev_attr_clear);
1759 +
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);
1764 +
1765 +       return 0;
1766 +}
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 */
1777  
1778         serial_out(up, UART_IER, up->ier);
1779  
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
1784 @@ -33,6 +33,7 @@
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>
1789  
1790  #include <asm/irq.h>
1791  #include <asm/uaccess.h>
1792 @@ -633,6 +634,54 @@ static int uart_get_info(struct uart_state *state,
1793         return 0;
1794  }
1795  
1796 +#ifdef CONFIG_PPS_CLIENT_UART
1797 +
1798 +static int
1799 +uart_register_pps_port(struct uart_state *state, struct uart_port *port)
1800 +{
1801 +       struct tty_driver *drv = port->info->tty->driver;
1802 +       int ret;
1803 +
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);
1810 +
1811 +       state->pps_info.mode = PPS_CAPTUREBOTH | \
1812 +                       PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
1813 +                       PPS_CANWAIT | PPS_TSFMT_TSPEC;
1814 +
1815 +       ret = pps_register_source(&state->pps_info, PPS_CAPTUREBOTH | \
1816 +                               PPS_OFFSETASSERT | PPS_OFFSETCLEAR);
1817 +       if (ret < 0) {
1818 +               dev_err(port->dev, "cannot register PPS source \"%s\"\n",
1819 +                                               state->pps_info.path);
1820 +               return ret;
1821 +       }
1822 +       port->pps_source = ret;
1823 +       dev_dbg(port->dev, "PPS source #%d \"%s\" added\n",
1824 +               port->pps_source, state->pps_info.path);
1825 +
1826 +       return 0;
1827 +}
1828 +
1829 +static void
1830 +uart_unregister_pps_port(struct uart_state *state, struct uart_port *port)
1831 +{
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);
1835 +}
1836 +
1837 +#else
1838 +
1839 +#define uart_register_pps_port(state, port)    do { } while (0)
1840 +#define uart_unregister_pps_port(state, port)  do { } while (0)
1841 +
1842 +#endif /* CONFIG_PPS_CLIENT_UART */
1843 +
1844  static int uart_set_info(struct uart_state *state,
1845                          struct serial_struct __user *newinfo)
1846  {
1847 @@ -807,11 +856,19 @@ static int uart_set_info(struct uart_state *state,
1848                         (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
1849  
1850   check_and_exit:
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);
1855 +               else
1856 +                       uart_unregister_pps_port(state, port);
1857 +       }
1858 +
1859         retval = 0;
1860         if (port->type == PORT_UNKNOWN)
1861                 goto exit;
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) {
1866                         /*
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);
1870         }
1871  
1872 +       /*
1873 +        * Add the PPS support for the current port.
1874 +        */
1875 +       if (port->flags & UPF_HARDPPS_CD)
1876 +               uart_register_pps_port(state, port);
1877 +
1878         if (port->type != PORT_UNKNOWN) {
1879                 unsigned long flags;
1880  
1881 @@ -2359,6 +2422,12 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
1882         mutex_unlock(&state->mutex);
1883  
1884         /*
1885 +        * Remove PPS support from the current port.
1886 +        */
1887 +       if (port->flags & UPF_HARDPPS_CD)
1888 +               uart_unregister_pps_port(state, port);
1889 +
1890 +       /*
1891          * Remove the devices from the tty layer
1892          */
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
1899  unifdef-y += poll.h
1900  unifdef-y += ppp_defs.h
1901  unifdef-y += ppp-comp.h
1902 +unifdef-y += pps.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 {
1919  
1920         struct list_head full_list;
1921         struct parport *slaves[3];
1922 +
1923 +#ifdef CONFIG_PPS_CLIENT_LP
1924 +       struct pps_source_info pps_info;
1925 +       int pps_source;         /* PPS source ID */
1926 +#endif
1927  };
1928  
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)
1933  {
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);
1938 +#endif
1939 +
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
1946 --- /dev/null
1947 +++ b/include/linux/pps.h
1948 @@ -0,0 +1,196 @@
1949 +/*
1950 + * pps.h -- PPS API kernel header.
1951 + *
1952 + *
1953 + * Copyright (C) 2005-2007   Rodolfo Giometti <giometti@linux.it>
1954 + *
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.
1959 + *
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.
1964 + *
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.
1968 + */
1969 +
1970 +
1971 +#ifndef _PPS_H_
1972 +#define _PPS_H_
1973 +
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.  */
1977 +
1978 +/*
1979 + * 3.2 New data structures
1980 + */
1981 +
1982 +#ifndef __KERNEL__
1983 +#include <linux/types.h>
1984 +#include <sys/time.h>
1985 +#include <sys/ioctl.h>
1986 +#else
1987 +#include <linux/time.h>
1988 +#endif
1989 +
1990 +#define PPS_API_VERS           1
1991 +#define PPS_MAX_NAME_LEN       32
1992 +
1993 +/* 32-bit vs. 64-bit compatibility.
1994 + *
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
1999 + * alignment.
2000 + *
2001 + * The simple fix is probably to add an explicit padding.
2002 + *                                                     [David Woodhouse]
2003 + */
2004 +struct pps_ktime {
2005 +       __u64 sec;
2006 +       __u32 nsec;
2007 +       __u32 flags;
2008 +};
2009 +#define PPS_TIME_INVALID       (1<<0)  /* used to specify timeout==NULL */
2010 +
2011 +struct pps_kinfo {
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 */
2017 +};
2018 +
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 */
2024 +};
2025 +
2026 +/*
2027 + * 3.3 Mode bit definitions
2028 + */
2029 +
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 */
2034 +
2035 +#define PPS_OFFSETASSERT       0x10    /* apply compensation for assert ev. */
2036 +#define PPS_OFFSETCLEAR                0x20    /* apply compensation for clear ev. */
2037 +
2038 +#define PPS_CANWAIT            0x100   /* can we wait for an event? */
2039 +#define PPS_CANPOLL            0x200   /* bit reserved for future use */
2040 +
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 */
2044 +
2045 +/* Timestamp formats */
2046 +#define PPS_TSFMT_TSPEC                0x1000  /* select timespec format */
2047 +#define PPS_TSFMT_NTPFP                0x2000  /* select NTP format */
2048 +
2049 +/*
2050 + * 3.4.4 New functions: disciplining the kernel timebase
2051 + */
2052 +
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 */
2059 +/*
2060 + * Here begins the implementation-specific part!
2061 + */
2062 +
2063 +struct pps_fdata {
2064 +       struct pps_kinfo info;
2065 +       struct pps_ktime timeout;
2066 +};
2067 +
2068 +#include <linux/ioctl.h>
2069 +
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 *)
2075 +
2076 +#ifdef __KERNEL__
2077 +
2078 +#include <linux/cdev.h>
2079 +#include <linux/device.h>
2080 +
2081 +#define PPS_VERSION            "5.0.0-rc2"
2082 +#define PPS_MAX_SOURCES                16              /* should be enought... */
2083 +
2084 +/*
2085 + * Global defines
2086 + */
2087 +
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 */
2093 +
2094 +       void (*echo)(int source, int event, void *data); /* PPS echo function */
2095 +
2096 +       struct module *owner;
2097 +       struct device *dev;
2098 +};
2099 +
2100 +/* The main struct */
2101 +struct pps_device {
2102 +       struct pps_source_info info;            /* PSS source info */
2103 +
2104 +       struct pps_kparams params;              /* PPS's current params */
2105 +
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 */
2111 +
2112 +       int go;                                 /* PPS event is arrived? */
2113 +       wait_queue_head_t queue;                /* PPS event queue */
2114 +
2115 +       unsigned int id;                        /* PPS source unique ID */
2116 +       struct cdev cdev;
2117 +       struct device *dev;
2118 +       int devno;
2119 +       struct fasync_struct *async_queue;      /* fasync method */
2120 +       spinlock_t lock;
2121 +
2122 +       atomic_t usage;                         /* usage count */
2123 +       wait_queue_head_t usage_queue;
2124 +
2125 +       struct class_device class_dev;
2126 +};
2127 +
2128 +/*
2129 + * Exported functions
2130 + */
2131 +
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);
2138 +
2139 +extern int pps_sysfs_create_source_entry(struct pps_device *pps);
2140 +extern void pps_sysfs_remove_source_entry(struct pps_device *pps);
2141 +
2142 +#endif /* __KERNEL__ */
2143 +
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
2149 @@ -157,6 +157,7 @@
2150  #include <linux/tty.h>
2151  #include <linux/mutex.h>
2152  #include <linux/sysrq.h>
2153 +#include <linux/pps.h>
2154  
2155  struct uart_port;
2156  struct uart_info;
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 */
2163 +#endif
2164  
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))
2169  
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\
2173 +                                                       |UPF_HARDPPS_CD))
2174  
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;
2180  
2181 +#ifdef CONFIG_PPS_CLIENT_UART
2182 +       struct pps_source_info  pps_info;
2183 +#endif
2184 +
2185         struct mutex            mutex;
2186  };
2187  
2188 @@ -476,13 +485,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status)
2189  {
2190         struct uart_info *info = port->info;
2191  
2192 -       port->icount.dcd++;
2193 -
2194 -#ifdef CONFIG_HARD_PPS
2195 -       if ((port->flags & UPF_HARDPPS_CD) && status)
2196 -               hardpps();
2197 +#ifdef CONFIG_PPS_CLIENT_UART
2198 +       if (port->flags & UPF_HARDPPS_CD) {
2199 +               if (status) {
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);
2203 +               } else {
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);
2207 +               }
2208 +       }
2209  #endif
2210  
2211 +       port->icount.dcd++;
2212 +
2213         if (info->flags & UIF_CHECK_CD) {
2214                 if (status)
2215                         wake_up_interruptible(&info->open_wait);