Skip to contentSkip to conversation

PPS: serial clients support.

PATCH In review Rodolfo Giometti 6 participants 26 messages Apr 10, 2008 – May 2, 2008

Subsystems (5)
lore
Share & tools
lore

Rodolfo Giometti

author maintainer
#0 lore raw

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
index 60b83be..517c338 100644
@@ -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
index 77f7a7f..880cbeb 100644
@@ -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
index 289942f..0f8fbd4 100644
@@ -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
author maintainer
#1 lore raw
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?

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
#2 lore raw
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

#3 lore raw

LinuxPPS (RESUBMIT 4): the PPS Linux implementation.

In reply to Rodolfo Giometti

This 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(-)
#4 lore raw

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
new file mode 100644
index 0000000..8cba1d9
@@ -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
index c18363b..b4c7d26 100644
@@ -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
index 90dcbbc..a67d624 100644
@@ -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
index 3a0e354..0c11e5c 100644
@@ -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
index e5e394a..adc0924 100644
@@ -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
new file mode 100644
index 0000000..cc2eb8e
@@ -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
new file mode 100644
index 0000000..19ea582
@@ -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
index 9cdd12a..0dd702c 100644
@@ -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
#5 lore raw

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
new file mode 100644
index 0000000..2372949
@@ -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 __inline int 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 __inline int time_pps_destroy(pps_handle_t handle)
+{
+	return close(handle);
+}
+
+static __inline int 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 __inline int 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 __inline int time_pps_getcap(pps_handle_t handle, int *mode)
+{
+	return ioctl(handle, PPS_GETCAP, mode);
+}
+
+static __inline int 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 __inline int 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
#6 lore raw

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
new file mode 100644
index 0000000..af4f9b4
@@ -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
new file mode 100644
index 0000000..93c0e17
@@ -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
#7 lore raw

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
index cc2eb8e..1afe4e0 100644
@@ -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
index 19ea582..98960dd 100644
@@ -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
new file mode 100644
index 0000000..60b83be
@@ -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
new file mode 100644
index 0000000..f3c1e39
@@ -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
#8 lore raw

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
index 60b83be..517c338 100644
@@ -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
index 77f7a7f..880cbeb 100644
@@ -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
index 289942f..0f8fbd4 100644
@@ -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
#9 lore raw

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
index af4f9b4..8ef4f47 100644
@@ -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
#10 lore raw

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
index 60ac642..b201fed 100644
@@ -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
index 517c338..09ba5c3 100644
@@ -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
index d1ad546..501a9dc 100644
@@ -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
#11 lore raw
In reply to Rodolfo Giometti
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.

author maintainer
#12 lore raw
Quoted 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
#13 lore raw
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

author maintainer
#14 lore raw
Quoted 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->ops patch 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
#15 lore raw
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?

author maintainer
#16 lore raw
Quoted 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
Quoted 2 lines
   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?

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
#17 lore raw
In reply to Alan Cox
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->ops patch 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
#18 lore raw
Quoted 3 lines

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.

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

author maintainer
#19 lore raw
Quoted 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
#20 lore raw
Quoted 3 lines

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?

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 the pps_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

author maintainer
#21 lore raw
Quoted 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_event management into uart_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

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 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 ?

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 the pps_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.

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
#22 lore raw
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

author maintainer
#23 lore raw
Quoted 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 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++;
#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
#24 lore raw
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

author maintainer
#25 lore raw
Quoted 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_change callback ..

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