PPS: serial clients support.
Subsystems (5)
Rodolfo Giometti
maintainerPATCH 5/7 PPS: serial clients support.
Adds support for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
--- drivers/pps/clients/Kconfig | 10 +++++ drivers/serial/8250.c | 2 + drivers/serial/serial_core.c | 81 +++++++++++++++++++++++++++++++++++++++++- include/linux/serial_core.h | 30 ++++++++++++--- 4 files changed, 116 insertions(+), 7 deletions(-)
drivers/pps/clients/Kconfig +10 -0
@@ -15,4 +15,14 @@ config PPS_CLIENT_KTIMER This driver can also be built as a module. If so, the module will be called ktimer.ko. +comment "UART serial support (forced off)" + depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)) + +config PPS_CLIENT_UART + bool "UART serial support" + depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y) + help + If you say yes here you get support for a PPS source connected + with the CD (Carrier Detect) pin of your serial port. + endif
drivers/serial/8250.c +2 -0
@@ -2119,6 +2119,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, up->ier |=UART_IER_MSI ;if (up->capabilities &UART_CAP_UUE ) up->ier |=UART_IER_UUE |UART_IER_RTOIE ; +if (up->port.flags &UPF_HARDPPS_CD ) + up->ier |=UART_IER_MSI ;/* enable interrupts */ serial_out (up,UART_IER , up->ier);
drivers/serial/serial_core.c +80 -1
115 lines not on this page · raw message
include/linux/serial_core.h +24 -6
@@ -166,6 +166,7 @@#include <linux/tty.h> #include <linux/mutex.h> #include <linux/sysrq.h> +#include <linux/pps.h> struct uart_port ;struct uart_info ;
@@ -245,6 +246,9 @@ struct uart_port {unsigned char regshift;/* reg offset shift */ unsigned char iotype;/* io access style */ unsigned char unused1; +#ifdef CONFIG_PPS_CLIENT_UART +int pps_source;/* PPS source ID */ +#endif #define UPIO_PORT (0)#define UPIO_HUB6 (1)
@@ -289,7 +293,8 @@ struct uart_port {#define UPF_IOREMAP ((__force upf_t) (1 << 31))#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff)) -#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY)) +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY\ + |UPF_HARDPPS_CD))unsigned int mctrl;/* current modem ctrl settings */ unsigned int timeout;/* character-based timeout */
@@ -322,6 +327,10 @@ struct uart_state {struct uart_info *info;struct uart_port *port; +#ifdef CONFIG_PPS_CLIENT_UART +struct pps_source_info pps_info; +#endif +struct mutex mutex; };
@@ -486,13 +495,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) {struct uart_info *info = port->info; - port->icount.dcd++; - -#ifdef CONFIG_HARD_PPS -if ((port->flags &UPF_HARDPPS_CD ) && status) -hardpps (); +#ifdef CONFIG_PPS_CLIENT_UART +if (port->flags &UPF_HARDPPS_CD ) { +if (status) { +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); + }else { +pps_event (port->pps_source,PPS_CAPTURECLEAR , port); +dev_dbg (port->dev,"PPS clear at %lu on source #%d\n" , + jiffies, port->pps_source); + } + }#endif + port->icount.dcd++; +if (info->flags &UIF_CHECK_CD ) {if (status)wake_up_interruptible (&info->open_wait);
Signature · 9 lines
1.5.4.3 -- GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Rodolfo Giometti
maintainerQuoted 2 lines · Rodolfo Giometti
Adds support for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
Should I resubmit the whole patch set?
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 5 lines · Rodolfo Giometti
Quoted 2 lines · Rodolfo Giometti
Adds support for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
Should I resubmit the whole patch set?
Please do.
thanks,
greg k-h
LinuxPPS (RESUBMIT 4): the PPS Linux implementation.
In reply to Rodolfo GiomettiThis patch set adds the PPS support into Linux.
PPS means "pulse per second" and its API is specified by RFC 2783 (Pulse-Per-Second API for UNIX-like Operating Systems, Version 1.0).
The code has been tested with the NTPD program
(http://www.eecis.udel.edu/~mills/ntp/html/index.html) and several GPS antennae.
Rodolfo
--
Documentation/pps/Makefile | 2 b/Documentation/ABI/testing/sysfs-pps | 73 +++++++ b/Documentation/ioctl-number.txt | 2 b/Documentation/pps/Makefile | 27 ++ b/Documentation/pps/pps.txt | 170 +++++++++++++++++ b/Documentation/pps/ppsctl.c | 63 ++++++ b/Documentation/pps/ppsfind | 17 + b/Documentation/pps/ppstest.c | 152 +++++++++++++++ b/Documentation/pps/timepps.h | 196 +++++++++++++++++++ b/MAINTAINERS | 7 b/drivers/Kconfig | 2 b/drivers/Makefile | 1 b/drivers/char/lp.c | 61 ++++++ b/drivers/pps/Kconfig | 33 +++ b/drivers/pps/Makefile | 8 b/drivers/pps/clients/Kconfig | 18 + b/drivers/pps/clients/Makefile | 9 b/drivers/pps/clients/ktimer.c | 115 +++++++++++ b/drivers/pps/kapi.c | 330 +++++++++++++++++++++++++++++++++ b/drivers/pps/pps.c | 335 ++++++++++++++++++++++++++++++++++ b/drivers/pps/sysfs.c | 103 ++++++++++ b/drivers/serial/8250.c | 2 b/drivers/serial/serial_core.c | 81 ++++++++ b/include/linux/Kbuild | 1 b/include/linux/parport.h | 13 + b/include/linux/pps.h | 203 ++++++++++++++++++++ b/include/linux/serial_core.h | 31 ++- drivers/pps/Kconfig | 2 drivers/pps/Makefile | 1 drivers/pps/clients/Kconfig | 20 ++ 30 files changed, 2063 insertions(+), 15 deletions(-)
PATCH 1/7 LinuxPPS core support.
This patch adds the kernel side of the PPS support currently named "LinuxPPS".
PPS means "pulse per second" and a PPS source is just a device which provides a high precision signal each second so that an application can use it to adjust system clock time.
Common use is the combination of the NTPD as userland program with a GPS receiver as PPS source to obtain a wallclock-time with sub-millisecond synchronisation to UTC.
To obtain this goal the userland programs shoud use the PPS API specification (RFC 2783 - Pulse-Per-Second API for UNIX-like Operating Systems, Version 1.0) which in part is implemented by this patch. It provides a set of chars devices, one per PPS source, which can be used to get the time signal. The RFC's functions can be implemented by accessing to these char devices.
--- Documentation/ABI/testing/sysfs-pps | 73 ++++++++ Documentation/ioctl-number.txt | 2 + Documentation/pps/pps.txt | 170 ++++++++++++++++++ MAINTAINERS | 7 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/pps/Kconfig | 33 ++++ drivers/pps/Makefile | 8 + drivers/pps/kapi.c | 330 ++++++++++++++++++++++++++++++++++ drivers/pps/pps.c | 335 +++++++++++++++++++++++++++++++++++ drivers/pps/sysfs.c | 103 +++++++++++ include/linux/Kbuild | 1 + include/linux/pps.h | 202 +++++++++++++++++++++ 13 files changed, 1267 insertions(+), 0 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-pps create mode 100644 Documentation/pps/pps.txt create mode 100644 drivers/pps/Kconfig create mode 100644 drivers/pps/Makefile create mode 100644 drivers/pps/kapi.c create mode 100644 drivers/pps/pps.c create mode 100644 drivers/pps/sysfs.c create mode 100644 include/linux/pps.h
Documentation/ABI/testing/sysfs-pps new file +73 -0
@@ -0,0 +1,73 @@ +What: /sys/class/pps/ +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ directory will contain files and + directories that will provide a unified interface to + the PPS sources. + +What: /sys/class/pps/ppsX/ +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/ directory is related to X-th + PPS source into the system. Each directory will + contain files to manage and control its PPS source. + +What: /sys/class/pps/ppsX/assert +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/assert file reports the assert events + and the assert sequence number of the X-th source in the form: + + <secs>.<nsec>#<sequence> + + If the source has no assert events the content of this file + is void. + +What: /sys/class/pps/ppsX/clear +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/clear file reports the clear events + and the clear sequence number of the X-th source in the form: + + <secs>.<nsec>#<sequence> + + If the source has no clear events the content of this file + is void. + +What: /sys/class/pps/ppsX/mode +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/mode file reports the functioning + mode of the X-th source in hexadecimal encoding. + + Please, refer to linux/include/linux/pps.h for further + info. + +What: /sys/class/pps/ppsX/echo +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/echo file reports if the X-th source + supports or not an "echo" function. + +What: /sys/class/pps/ppsX/name +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/name file reports the name of the + X-th source. + +What: /sys/class/pps/ppsX/path +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/path file reports the path name of + the device connected with the X-th source. + + If the source is not connected with any device the content + of this file is void.
Documentation/ioctl-number.txt +2 -0
@@ -97,6 +97,8 @@ Code Seq# Include File Comments 'M' all linux/soundcard.h 'N' 00-1F drivers/usb/scanner.h 'P' all linux/soundcard.h +'P' 00-04 linux/pps.h LinuxPPS + <mailto:[email protected]> 'Q' all linux/soundcard.h 'R' 00-1F linux/random.h 'S' all linux/cdrom.h conflict!
Documentation/pps/pps.txt new file +170 -0
170 lines not on this page · raw message
MAINTAINERS +7 -0
@@ -3171,6 +3171,13 @@ P: James Chapman M: [email protected] S: Maintained +PPS SUPPORT +P: Rodolfo Giometti +M: [email protected] +W: http://wiki.enneenne.com/index.php/LinuxPPS_support +L: [email protected] +S: Maintained + PREEMPTIBLE KERNEL P: Robert Love M: [email protected]
drivers/Kconfig +2 -0
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig" source "drivers/spi/Kconfig" +source "drivers/pps/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/w1/Kconfig"
drivers/Makefile +1 -0
@@ -62,6 +62,7 @@ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_RTC_LIB) += rtc/ obj-y += i2c/ +obj-$(CONFIG_PPS) += pps/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_POWER_SUPPLY) += power/ obj-$(CONFIG_HWMON) += hwmon/
drivers/pps/Kconfig new file +33 -0
@@ -0,0 +1,33 @@ +# +# PPS support configuration +# + +menu "PPS support" + +config PPS + tristate "PPS support" + depends on EXPERIMENTAL + ---help--- + PPS (Pulse Per Second) is a special pulse provided by some GPS + antennae. Userland can use it to get a high-precision time + reference. + + Some antennae's PPS signals are connected with the CD (Carrier + Detect) pin of the serial line they use to communicate with the + host. In this case use the SERIAL_LINE client support. + + Some antennae's PPS signals are connected with some special host + inputs so you have to enable the corresponding client support. + + To compile this driver as a module, choose M here: the module + will be called pps_core.ko. + +config PPS_DEBUG + bool "PPS debugging messages" + depends on PPS + help + Say Y here if you want the PPS support to produce a bunch of debug + messages to the system log. Select this if you are having a + problem with PPS support and want to see more of what is going on. + +endmenu
drivers/pps/Makefile new file +8 -0
@@ -0,0 +1,8 @@ +# +# Makefile for the PPS core. +# + +pps_core-y := pps.o kapi.o sysfs.o +obj-$(CONFIG_PPS) := pps_core.o + +ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
drivers/pps/kapi.c new file +330 -0
330 lines not on this page · raw message
drivers/pps/pps.c new file +335 -0
335 lines not on this page · raw message
drivers/pps/sysfs.c new file +103 -0
103 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -294,6 +294,7 @@ unifdef-y += pmu.h unifdef-y += poll.h unifdef-y += ppp_defs.h unifdef-y += ppp-comp.h +unifdef-y += pps.h unifdef-y += ptrace.h unifdef-y += qnx4_fs.h unifdef-y += quota.h
include/linux/pps.h new file +202 -0
202 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 2/7 PPS: userland header file for PPS API.
This patch adds into the PPS's documentation directory a possible implementation of the PPS API (RFC 2783) by using the LinuxPPS's char devices.
This file is not just an example but it can be used into real systems. :)
--- Documentation/pps/timepps.h | 195 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 Documentation/pps/timepps.h
Documentation/pps/timepps.h new file +195 -0
@@ -0,0 +1,195 @@ +/* +* timepps.h -- PPS API main header +* +* Copyright (C) 2005-2007 Rodolfo Giometti <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SYS_TIMEPPS_H_ +#define _SYS_TIMEPPS_H_ + +#include <sys/syscall.h> +#include <unistd.h> +#include <errno.h> +#include <linux/pps.h> + +#define LINUXPPS 1/* signal we are using LinuxPPS */ + +/* +* New data structures +*/ + +struct ntp_fp { +unsigned int integral; +unsigned int fractional; +}; + +union pps_timeu { +struct timespec tspec; +struct ntp_fp ntpfp; +unsigned long longpad[3 ]; +}; + +struct pps_info { +unsigned long assert_sequence;/* seq. num. of assert event */ +unsigned long clear_sequence;/* seq. num. of clear event */ +union pps_timeu assert_tu;/* time of assert event */ +union pps_timeu clear_tu;/* time of clear event */ +int current_mode;/* current mode bits */ +}; + +struct pps_params { +int api_version;/* API version # */ +int mode;/* mode bits */ +union pps_timeu assert_off_tu;/* offset compensation for assert */ +union pps_timeu clear_off_tu;/* offset compensation for clear */ +}; + +typedef int pps_handle_t ;/* represents a PPS source */ +typedef unsigned long pps_seq_t ;/* sequence number */ +typedef struct ntp_fp ntp_fp_t ;/* NTP-compatible time stamp */ +typedef union pps_timeu pps_timeu_t ;/* generic data type for time stamps */ +typedef struct pps_info pps_info_t ; +typedef struct pps_params pps_params_t ; + +#define assert_timestamp assert_tu.tspec +#define clear_timestamp clear_tu.tspec + +#define assert_timestamp_ntpfp assert_tu.ntpfp +#define clear_timestamp_ntpfp clear_tu.ntpfp + +#define assert_offset assert_off_tu.tspec +#define clear_offset clear_off_tu.tspec + +#define assert_offset_ntpfp assert_off_tu.ntpfp +#define clear_offset_ntpfp clear_off_tu.ntpfp + +/* +* The PPS API +*/ + +static __inlineint time_pps_create (int source,pps_handle_t *handle) +{ +int ret; + +if (!handle) { + errno =EINVAL ; +return -1 ; + } + +/* First we check if current device is a PPS valid PPS one... +*/ + ret =ioctl (source,PPS_CHECK ); +if (ret) { + errno =EOPNOTSUPP ; +return -1 ; + } + +/* ... then since in LinuxPPS there are no differences between a +* "PPS source" and a "PPS handle", we simply return the same value. +*/ + *handle = source; + +return 0 ; +} + +static __inlineint time_pps_destroy (pps_handle_t handle) +{ +return close (handle); +} + +static __inlineint time_pps_getparams (pps_handle_t handle, +pps_params_t *ppsparams) +{ +int ret; +struct pps_kparams __ppsparams; + + ret =ioctl (handle,PPS_GETPARAMS , &__ppsparams); + + ppsparams->api_version = __ppsparams.api_version; + ppsparams->mode = __ppsparams.mode; + ppsparams->assert_off_tu.tspec.tv_sec = __ppsparams.assert_off_tu.sec; + ppsparams->assert_off_tu.tspec.tv_nsec = __ppsparams.assert_off_tu.nsec; + ppsparams->clear_off_tu.tspec.tv_sec = __ppsparams.clear_off_tu.sec; + ppsparams->clear_off_tu.tspec.tv_nsec = __ppsparams.clear_off_tu.nsec; + +return ret; +} + +static __inlineint time_pps_setparams (pps_handle_t handle, +const pps_params_t *ppsparams) +{ +struct pps_kparams __ppsparams; + + __ppsparams.api_version = ppsparams->api_version; + __ppsparams.mode = ppsparams->mode; + __ppsparams.assert_off_tu.sec = ppsparams->assert_off_tu.tspec.tv_sec; + __ppsparams.assert_off_tu.nsec = ppsparams->assert_off_tu.tspec.tv_nsec; + __ppsparams.clear_off_tu.sec = ppsparams->clear_off_tu.tspec.tv_sec; + __ppsparams.clear_off_tu.nsec = ppsparams->clear_off_tu.tspec.tv_nsec; + +return ioctl (handle,PPS_SETPARAMS , &__ppsparams); +} + +/* Get capabilities for handle */ +static __inlineint time_pps_getcap (pps_handle_t handle,int *mode) +{ +return ioctl (handle,PPS_GETCAP , mode); +} + +static __inlineint time_pps_fetch (pps_handle_t handle,const int tsformat, +pps_info_t *ppsinfobuf, +const struct timespec *timeout) +{ +struct pps_fdata __fdata; +int ret; + +/* Sanity checks */ +if (tsformat !=PPS_TSFMT_TSPEC ) { + errno =EINVAL ; +return -1 ; + } + +if (timeout) { + __fdata.timeout.sec = timeout->tv_sec; + __fdata.timeout.nsec = timeout->tv_nsec; + __fdata.timeout.flags = ~PPS_TIME_INVALID ; + }else + __fdata.timeout.flags =PPS_TIME_INVALID ; + + ret =ioctl (handle,PPS_FETCH , &__fdata); + + ppsinfobuf->assert_sequence = __fdata.info.assert_sequence; + ppsinfobuf->clear_sequence = __fdata.info.clear_sequence; + ppsinfobuf->assert_tu.tspec.tv_sec = __fdata.info.assert_tu.sec; + ppsinfobuf->assert_tu.tspec.tv_nsec = __fdata.info.assert_tu.nsec; + ppsinfobuf->clear_tu.tspec.tv_sec = __fdata.info.clear_tu.sec; + ppsinfobuf->clear_tu.tspec.tv_nsec = __fdata.info.clear_tu.nsec; + ppsinfobuf->current_mode = __fdata.info.current_mode; + +return ret; +} + +static __inlineint time_pps_kcbind (pps_handle_t handle, +const int kernel_consumer, +const int edge,const int tsformat) +{ +/* LinuxPPS doesn't implement kernel consumer feature */ + errno =EOPNOTSUPP ; +return -1 ; +} + +#endif /* _SYS_TIMEPPS_H_ */
Signature · 1 line
1.5.4.3
PATCH 3/7 PPS: documentation programs and examples.
Here some utilities and examples about the PPS API and the LinuxPPS support.
* ppstest.c implements an useful testing program, while
* ppsfind tries to help the user into finding a specific PPS source by using its name or path.
--- Documentation/pps/Makefile | 27 ++++++++ Documentation/pps/ppsfind | 17 +++++ Documentation/pps/ppstest.c | 151 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 Documentation/pps/Makefile create mode 100644 Documentation/pps/ppsfind create mode 100644 Documentation/pps/ppstest.c
Documentation/pps/Makefile new file +27 -0
@@ -0,0 +1,27 @@ +TARGETS = ppstest + +CFLAGS += -Wall -O2 -D_GNU_SOURCE +CFLAGS += -I . +CFLAGS += -ggdb + +# -- Actions section -- + +.PHONY : all depend dep + +all : .depend $(TARGETS) + +.depend depend dep : + $(CC) $(CFLAGS) -M $(TARGETS:=.c) > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + + +# -- Clean section -- + +.PHONY : clean + +clean : + rm -f *.o *~ core .depend + rm -f ${TARGETS}
Documentation/pps/ppsfind new file +17 -0
@@ -0,0 +1,17 @@ +#!/bin/sh + +SYS="/sys/class/pps/" + +if [ $# -lt 1 ] ; then + echo "usage: ppsfind <name>" >&2 + exit 1 +fi + +for d in $(ls $SYS) ; do + if grep $1 $SYS/$d/name >& /dev/null || \ + grep $1 $SYS/$d/path >& /dev/null ; then + echo "$d: name=$(cat $SYS/$d/name) path=$(cat $SYS/$d/path)" + fi +done + +exit 0
Documentation/pps/ppstest.c new file +151 -0
151 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 4/7 PPS: LinuxPPS clients support.
Each PPS source can be registered/deregistered into the system by using special modules called "clients". They simply define the PPS sources' attributes and implement the time signal registartion mechanism.
This patch adds a special directory for such clients and adds a dummy client that can be useful to test system integrity on real systems.
--- drivers/pps/Kconfig | 2 + drivers/pps/Makefile | 1 + drivers/pps/clients/Kconfig | 18 +++++++ drivers/pps/clients/Makefile | 9 +++ drivers/pps/clients/ktimer.c | 114 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 144 insertions(+), 0 deletions(-) create mode 100644 drivers/pps/clients/Kconfig create mode 100644 drivers/pps/clients/Makefile create mode 100644 drivers/pps/clients/ktimer.c
drivers/pps/Kconfig +2 -0
@@ -30,4 +30,6 @@ config PPS_DEBUG messages to the system log. Select this if you are having a problem with PPS support and want to see more of what is going on. +source drivers/pps/clients/Kconfig + endmenu
drivers/pps/Makefile +1 -0
@@ -4,5 +4,6 @@ pps_core-y := pps.o kapi.o sysfs.o obj-$(CONFIG_PPS) := pps_core.o +obj-y += clients/ ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
drivers/pps/clients/Kconfig new file +18 -0
@@ -0,0 +1,18 @@ +# +# PPS clients configuration +# + +if PPS + +comment "PPS clients support" + +config PPS_CLIENT_KTIMER + tristate "Kernel timer client (Testing client, use for debug)" + help + If you say yes here you get support for a PPS debugging client + which uses a kernel timer to generate the PPS signal. + + This driver can also be built as a module. If so, the module + will be called ktimer.ko. + +endif
drivers/pps/clients/Makefile new file +9 -0
@@ -0,0 +1,9 @@ +# +# Makefile for PPS clients. +# + +obj-$(CONFIG_PPS_CLIENT_KTIMER) += ktimer.o + +ifeq ($(CONFIG_PPS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif
drivers/pps/clients/ktimer.c new file +114 -0
114 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 5/7 PPS: serial clients support.
Adds support for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
--- drivers/pps/clients/Kconfig | 10 +++++ drivers/serial/8250.c | 2 + drivers/serial/serial_core.c | 81 +++++++++++++++++++++++++++++++++++++++++- include/linux/serial_core.h | 30 ++++++++++++--- 4 files changed, 116 insertions(+), 7 deletions(-)
drivers/pps/clients/Kconfig +10 -0
@@ -15,4 +15,14 @@ config PPS_CLIENT_KTIMER This driver can also be built as a module. If so, the module will be called ktimer.ko. +comment "UART serial support (forced off)" + depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)) + +config PPS_CLIENT_UART + bool "UART serial support" + depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y) + help + If you say yes here you get support for a PPS source connected + with the CD (Carrier Detect) pin of your serial port. + endif
drivers/serial/8250.c +2 -0
@@ -2119,6 +2119,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, up->ier |=UART_IER_MSI ;if (up->capabilities &UART_CAP_UUE ) up->ier |=UART_IER_UUE |UART_IER_RTOIE ; +if (up->port.flags &UPF_HARDPPS_CD ) + up->ier |=UART_IER_MSI ;/* enable interrupts */ serial_out (up,UART_IER , up->ier);
drivers/serial/serial_core.c +80 -1
115 lines not on this page · raw message
include/linux/serial_core.h +24 -6
@@ -166,6 +166,7 @@#include <linux/tty.h> #include <linux/mutex.h> #include <linux/sysrq.h> +#include <linux/pps.h> struct uart_port ;struct uart_info ;
@@ -245,6 +246,9 @@ struct uart_port {unsigned char regshift;/* reg offset shift */ unsigned char iotype;/* io access style */ unsigned char unused1; +#ifdef CONFIG_PPS_CLIENT_UART +int pps_source;/* PPS source ID */ +#endif #define UPIO_PORT (0)#define UPIO_HUB6 (1)
@@ -289,7 +293,8 @@ struct uart_port {#define UPF_IOREMAP ((__force upf_t) (1 << 31))#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff)) -#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY)) +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY\ + |UPF_HARDPPS_CD))unsigned int mctrl;/* current modem ctrl settings */ unsigned int timeout;/* character-based timeout */
@@ -322,6 +327,10 @@ struct uart_state {struct uart_info *info;struct uart_port *port; +#ifdef CONFIG_PPS_CLIENT_UART +struct pps_source_info pps_info; +#endif +struct mutex mutex; };
@@ -486,13 +495,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) {struct uart_info *info = port->info; - port->icount.dcd++; - -#ifdef CONFIG_HARD_PPS -if ((port->flags &UPF_HARDPPS_CD ) && status) -hardpps (); +#ifdef CONFIG_PPS_CLIENT_UART +if (port->flags &UPF_HARDPPS_CD ) { +if (status) { +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); + }else { +pps_event (port->pps_source,PPS_CAPTURECLEAR , port); +dev_dbg (port->dev,"PPS clear at %lu on source #%d\n" , + jiffies, port->pps_source); + } + }#endif + port->icount.dcd++; +if (info->flags &UIF_CHECK_CD ) {if (status)wake_up_interruptible (&info->open_wait);
Signature · 1 line
1.5.4.3
PATCH 6/7 PPS: example program to enable PPS support on serial ports.
--- Documentation/pps/Makefile | 2 +- Documentation/pps/ppsctl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletions(-) create mode 100644 Documentation/pps/ppsctl.c
Documentation/pps/Makefile +1 -1
@@ -1,4 +1,4 @@ -TARGETS = ppstest +TARGETS = ppstest ppsctl CFLAGS += -Wall -O2 -D_GNU_SOURCE CFLAGS += -I .
Documentation/pps/ppsctl.c new file +62 -0
62 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 7/7 PPS: parallel port clients support.
Adds support for the PPS sources connected with the interrupt pin of a parallel port.
--- drivers/char/lp.c | 61 +++++++++++++++++++++++++++++++++++++++++++ drivers/pps/clients/Kconfig | 10 +++++++ include/linux/parport.h | 12 ++++++++ 3 files changed, 83 insertions(+), 0 deletions(-)
drivers/char/lp.c +61 -0
@@ -746,6 +746,27 @@ static struct console lpcons = {#endif /* console on line printer */ +/* Support for PPS signal on the line printer */ + +#ifdef CONFIG_PPS_CLIENT_LP + +static void lp_pps_echo (int source,int event,void *data) +{ +struct parport *port = data; +unsigned char status =parport_read_status (port); + +/* echo event via SEL bit */ +parport_write_control (port, +parport_read_control (port) |PARPORT_CONTROL_SELECT ); + +/* signal no event */ +if ((status &PARPORT_STATUS_ACK ) !=0 ) +parport_write_control (port, +parport_read_control (port) & ~PARPORT_CONTROL_SELECT ); +} + +#endif +/* --- initialisation code ------------------------------------- */ static int parport_nr[LP_NO ] = { [0 ...LP_NO -1 ] =LP_PARPORT_UNSPEC };
@@ -816,6 +837,38 @@ static int lp_register(int nr, struct parport *port) }#endif +#ifdef CONFIG_PPS_CLIENT_LP + port->pps_info.owner =THIS_MODULE ; + port->pps_info.dev = port->dev; +snprintf (port->pps_info.path,PPS_MAX_NAME_LEN ,"/dev/lp%d" , nr); + +/* No PPS support if lp port has no IRQ line */ +if (port->irq !=PARPORT_IRQ_NONE ) { +strncpy (port->pps_info.name, port->name,PPS_MAX_NAME_LEN ); + + port->pps_info.mode =PPS_CAPTUREASSERT |PPS_OFFSETASSERT | \ +PPS_ECHOASSERT | \ +PPS_CANWAIT |PPS_TSFMT_TSPEC ; + + port->pps_info.echo = lp_pps_echo; + + port->pps_source =pps_register_source (&(port->pps_info), +PPS_CAPTUREASSERT |PPS_OFFSETASSERT ); +if (port->pps_source <0 ) +dev_err (port->dev, +"cannot register PPS source \"%s\"\n" , + port->pps_info.path); +else +dev_info (port->dev,"PPS source #%d \"%s\" added\n" , + port->pps_source, port->pps_info.path); + }else { + port->pps_source =-1 ; +dev_err (port->dev,"PPS support disabled because port \"%s\" " +"is in polling mode\n" , + port->pps_info.path); + } +#endif +return 0 ; }
@@ -858,6 +911,14 @@ static void lp_detach (struct parport *port) console_registered =NULL ; }#endif /* CONFIG_LP_CONSOLE */ + +#ifdef CONFIG_PPS_CLIENT_LP +if (port->pps_source >=0 ) { +pps_unregister_source (port->pps_source); +dev_dbg (port->dev,"PPS source #%d \"%s\" removed\n" , + port->pps_source, port->pps_info.path); + } +#endif } static struct parport_driver lp_driver = {
drivers/pps/clients/Kconfig +10 -0
@@ -25,4 +25,14 @@ config PPS_CLIENT_UART If you say yes here you get support for a PPS source connected with the CD (Carrier Detect) pin of your serial port. +comment "Parallel printer support (forced off)" + depends on !( PRINTER != n && !(PPS = m && PRINTER = y)) + +config PPS_CLIENT_LP + bool "Parallel printer support" + depends on PRINTER != n && !(PPS = m && PRINTER = y) + help + If you say yes here you get support for a PPS source connected + with the interrupt pin of your parallel port. + endif
include/linux/parport.h +12 -0
@@ -100,6 +100,7 @@ typedef enum {#include <linux/proc_fs.h> #include <linux/spinlock.h> #include <linux/wait.h> +#include <linux/pps.h> #include <linux/irqreturn.h> #include <asm/system.h> #include <asm/ptrace.h>
@@ -328,6 +329,11 @@ struct parport {struct list_head full_list;struct parport *slaves[3 ]; + +#ifdef CONFIG_PPS_CLIENT_LP +struct pps_source_info pps_info; +int pps_source;/* PPS source ID */ +#endif };#define DEFAULT_SPIN_TIME 500/* us */
@@ -516,6 +522,12 @@ extern int parport_daisy_select (struct parport *port, int daisy, int mode);/* Lowlevel drivers _can_ call this support function to handle irqs. */ static inline void parport_generic_irq (struct parport *port) { +#ifdef CONFIG_PPS_CLIENT_LP +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); +#endif +parport_ieee1284_interrupt (port);read_lock (&port->cad_lock);if (port->cad && port->cad->irq_func)
Signature · 1 line
1.5.4.3
Quoted 2 lines · On Thu, 10 Apr 2008 20:22:29 +0200 Rodolfo Giometti <[email protected]> wrote:
Adds support for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
Better and now readable but this is definitely in the wrong place and should be pushed up the stack so it can be generalised for all serial devices as an ldisc or similar.
This bit is definitely not ready to go upstream but the general PPS stuff looks fairly sane.
Rodolfo Giometti
maintainerQuoted 9 lines · Alan Cox
Quoted 2 lines · On Thu, 10 Apr 2008 20:22:29 +0200 Rodolfo Giometti <[email protected]> wrote:
Adds support for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
Better and now readable but this is definitely in the wrong place and should be pushed up the stack so it can be generalised for all serial devices as an ldisc or similar.
How can I do that? From a serial device I just need the IRQ time arrival, no other data at all. How a ldisc can help me in this task?
This patch adds PPS support just for UARTs, other devices should provide their own support by using the new provided API. :)
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 2 lines
How can I do that? From a serial device I just need the IRQ time arrival, no other data at all. How a ldisc can help me in this task?
At the moment you can't. That needs fixing. Most of the infrastructure is there but not all of it.
Quoted 2 lines
This patch adds PPS support just for UARTs, other devices should provide their own support by using the new provided API. :)
I do not want PPS code adding to every single serial driver. That way lies madness. We do it once, and in the right layer. I'll take a further look at it after the tty->ops patch is merged. At that point we'll be in a good position to add the needed ops/callbacks.
Alan
Rodolfo Giometti
maintainerQuoted 11 lines · Alan Cox
Quoted 2 lines
How can I do that? From a serial device I just need the IRQ time arrival, no other data at all. How a ldisc can help me in this task?
At the moment you can't. That needs fixing. Most of the infrastructure is there but not all of it.
Quoted 2 lines
This patch adds PPS support just for UARTs, other devices should provide their own support by using the new provided API. :)
I do not want PPS code adding to every single serial driver. That way lies madness. We do it once, and in the right layer. I'll take a further
The problem is that deferencing the pps_event() call will cause severe problems to PPS accuracy... here you can find some considerations on this topic:
http://ml.enneenne.com/pipermail/linuxpps/2008-April/001738.html
Quoted 2 lines
look at it after the
tty->opspatch is merged. At that point we'll be in a good position to add the needed ops/callbacks.
Can you please give me an URL where I can see that patch?
Thanks a lot for your help,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 6 lines · Rodolfo Giometti
The problem is that deferencing the
pps_event()call will cause severe problems to PPS accuracy... here you can find some considerations on this topic:http://ml.enneenne.com/pipermail/linuxpps/2008-April/001738.html
What about adding precise timestamping to the lowest possible irq handling level ( arch/*/entry*.S ) and then export that information in a general way so it is useful for other applications?
Rodolfo Giometti
maintainerQuoted 6 lines · Serge Belyshev
Quoted 4 lines · Rodolfo Giometti
The problem is that deferencing the
pps_event()call will cause severe problems to PPS accuracy... here you can find some considerations on this topic:
Quoted 6 lines
What about adding precise timestamping to the lowest possible irq handling level (
arch/*/entry*.S) and then export that information in a general way so it is useful for other applications?
The problem is that at such level you cannot easily retrieve info about where your serial port is connected to and which PPS source you should manage...
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 4 lines · Alan Cox
I do not want PPS code adding to every single serial driver. That way lies madness. We do it once, and in the right layer. I'll take a further look at it after the
tty->opspatch is merged. At that point we'll be in a good position to add the needed ops/callbacks.
I thought it just required that the uart driver call uart_handle_dcd_change when the state of the CD changes, and all the PPS stuff happened in that function.
That seems pretty low intrusion, since the serial driver wouldn't need to be touched with the PPS code at all as long as it already calls the uart_handle functions.
Now if the driver doesn't generate an IRQ whenever a status line changes, then the driver does need to be updated to do that. Some (like jsm) already do, and have no need for the HARDPPS setting at all. It seems reasonable though that the serial drivers should already have had support for generating interrupts when a status line changes.
Signature · 1 line
Len Sorensen
Quoted 3 lines
I thought it just required that the uart driver call
uart_handle_dcd_changewhen the state of the CD changes, and all the PPS stuff happened in that function.
uart_ is only used by some drivers. We have a whole army of drivers using the tty layer directly and another army of drivers using the USB layer.
You also need a sensible way to talk to the devices, identify support and avoid clashing uses of carrier pins.
Alan
Rodolfo Giometti
maintainerQuoted 6 lines · Alan Cox
uart_is only used by some drivers. We have a whole army of drivers using the tty layer directly and another army of drivers using the USB layer.You also need a sensible way to talk to the devices, identify support and avoid clashing uses of carrier pins.
Hello Alan,
if I add a dedicated line discipline to register/unregister the PPS source and I leave the pps_event management into uart_handle_dcd_change() function, it can be acceptable?
The uart_handle_dcd_change() is generic and I need the DCD status to correctly manage the pps_event. The USB layer is not useful for PPS stuff.
Thanks for your suggestions,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 3 lines
if I add a dedicated line discipline to register/unregister the PPS source and I leave the
pps_eventmanagement intouart_handle_dcd_change()function, it can be acceptable?
Keep the two things apart.
uart_handle_dcd_change looks a good basis for the UART layer support for drivers serial
an LDISC looks right for the top layer
We just need the bits in the middle right. I've added the serial layer pass through for the set_ldisc() interface so that bit is done. Probably the main thing we need is to add tty->ldisc.dcd_change() for reporting DCD change back to the line discipline. We could queue it as a TTY_ event but I assume you need it immediately not queued ?
Quoted 3 lines
The
uart_handle_dcd_change()is generic and I need the DCD status to correctly manage thepps_event. The USB layer is not useful for PPS stuff
Not every character driver uses drivers/serial or USB. That is fine. What I care about is that you *could* add PPS support to another serial driver cleanly, not that it is done immediately. What matters is the interface, the rest will follow.
Alan
Rodolfo Giometti
maintainerQuoted 10 lines · Alan Cox
Quoted 3 lines
if I add a dedicated line discipline to register/unregister the PPS source and I leave the
pps_eventmanagement intouart_handle_dcd_change()function, it can be acceptable?Keep the two things apart.
uart_handle_dcd_changelooks a good basis for the UART layer support for drivers serial
an LDISC looks right for the top layer
Quoted 5 lines
We just need the bits in the middle right. I've added the serial layer pass through for the
set_ldisc()interface so that bit is done. Probably the main thing we need is to addtty->ldisc.dcd_change()for reporting DCD change back to the line discipline. We could queue it as aTTY_event but I assume you need it immediately not queued ?
Yes, you are right. PPS events should be registered as soon as they arrive, that's why I'd like to put events registration (or at least IRQ timestamps) into do_IRQ() as follow:
fastcall unsigned int do_IRQ(struct pt_regs *regs)
{
struct pt_regs *old_regs;
/* high bit used in ret_from_ code */
int irq = ~regs->orig_eax;
struct irq_desc *desc = irq_desc + irq;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
u32 *isp;
#endif if (unlikely((unsigned)irq >= NR_IRQS)) {
printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
__FUNCTION__, irq);
BUG();
}
pps_irq_event_register(irq);
old_regs = set_irq_regs(regs);
irq_enter();but this solution arises two drawbacks:
1) the PPS echo functions should be executed by pps_irq_event_register() into do_IRQ(). Brrrr... :)
2) the shared IRQ line may cause "false" PPS events.
The latter drawback can be solved simply not using the shared IRQs for PPS sources but the former is not an easy task... so I suppose we should delay the echo function call at "safer" time, maybe using the function tty->ldisc.dcd_change().
Quoted 8 lines
Quoted 3 lines
The
uart_handle_dcd_change()is generic and I need the DCD status to correctly manage thepps_event. The USB layer is not useful for PPS stuffNot every character driver uses
drivers/serialor USB. That is fine. What I care about is that you *could* add PPS support to another serial driver cleanly, not that it is done immediately. What matters is the interface, the rest will follow.
I see. So what do you suggest to do? Should I add an ldisc to register/unregister serial PPS sources and adding function tty->ldisc.dcd_change() to manage the events?
Thanks for your suggestions,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 3 lines
I see. So what do you suggest to do? Should I add an ldisc to register/unregister serial PPS sources and adding function
tty->ldisc.dcd_change()to manage the events?
I think so. To me that sounds the ideal solution.
Alan
Rodolfo Giometti
maintainerQuoted 5 lines · Alan Cox
Quoted 3 lines
I see. So what do you suggest to do? Should I add an ldisc to register/unregister serial PPS sources and adding function
tty->ldisc.dcd_change()to manage the events?I think so. To me that sounds the ideal solution.
So I should rewrite the uart_handle_dcd_change() as follow?
static inline voiduart_handle_dcd_change(struct uart_port *port, unsigned int status)
{
struct uart_info *info = port->info;
struct tty_struct *tty = info->tty;
struct tty_ldisc *ld;
ld = tty_ldisc_ref(tty);
if (ld != NULL) {
if (ld->dcd_change)
(ld->dcd_change)(tty, port, status);
tty_ldisc_deref(ld);
}
port->icount.dcd++;#ifdef CONFIG_HARD_PPS
if ((port->flags & UPF_HARDPPS_CD) && status)
hardpps();#endif
if (info->flags & UIF_CHECK_CD) {
if (status)
wake_up_interruptible(&info->open_wait);
else if (tty)
tty_hangup(tty);
}
}Is that right?
Thanks a lot,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
Quoted 18 lines
So I should rewrite the
uart_handle_dcd_change()as follow?static inline void
uart_handle_dcd_change(struct uart_port *port, unsigned int status){ struct uart_info *info = port->info; struct tty_struct *tty = info->tty; struct tty_ldisc *ld; ld = tty_ldisc_ref(tty); if (ld != NULL) { if (ld->dcd_change) (ld->dcd_change)(tty, port, status); tty_ldisc_deref(ld); } port->icount.dcd++;
Quoted 4 lines
#ifdef CONFIG_HARD_PPS if ((port->flags & UPF_HARDPPS_CD) && status) hardpps();#endif
The ifdef bit can go - it will be in your dcd_change callback ..
Alan
Rodolfo Giometti
maintainerQuoted 16 lines · Alan Cox
Quoted 16 lines
So I should rewrite the
uart_handle_dcd_change()as follow?static inline void
uart_handle_dcd_change(struct uart_port *port, unsigned int status){ struct uart_info *info = port->info; struct tty_struct *tty = info->tty; struct tty_ldisc *ld; ld = tty_ldisc_ref(tty); if (ld != NULL) { if (ld->dcd_change) (ld->dcd_change)(tty, port, status); tty_ldisc_deref(ld); }
Quoted 8 lines
Quoted 6 lines
port->icount.dcd++;#ifdef CONFIG_HARD_PPS if ((port->flags & UPF_HARDPPS_CD) && status) hardpps();#endif
The ifdef bit can go - it will be in your
dcd_changecallback ..
The "#ifdef CONFIG_HARD_PPS" is currently into kernel code, is *not* my modification at all. In fact you can find the flag UPF_HARDPPS_CD defined into include/linux/serial_core.h. It's a part of a very old PPS implemention (never merged into mainline) and it was used to enable the PPS layer for serial ports. That's why I didn't define an ldisc but implemented my PPS version using it. :)
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti