Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Aug 2015 17:07:24 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r287037 - in stable/10: . share/man/man4 sys/dev/uart
Message-ID:  <201508231707.t7NH7O5W013396@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Aug 23 17:07:23 2015
New Revision: 287037
URL: https://svnweb.freebsd.org/changeset/base/287037

Log:
  MFC r286469, r286591, r286595, r286596, r286613:
  
    Provide the tty-layer mutex when initializing the pps api.  This allows
    time_pps_fetch() to be used in blocking mode.
  
    Allow the choice of PPS signal captured by uart(4) to be runtime-configured,
    eliminating the need to build a custom kernel to use the CTS signal.
  
    Correct the polarity of the PPS assert and clear events with respect to the
    electrical signals on the serial port.
  
    Document the change in polarity of the uart(4) PPS capture.
  
    Style fix -- do the braces for switches correctly.
  
  Relnotes:	yes

Modified:
  stable/10/UPDATING
  stable/10/share/man/man4/uart.4
  stable/10/sys/dev/uart/uart_bus.h
  stable/10/sys/dev/uart/uart_core.c
  stable/10/sys/dev/uart/uart_tty.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/UPDATING
==============================================================================
--- stable/10/UPDATING	Sun Aug 23 16:22:21 2015	(r287036)
+++ stable/10/UPDATING	Sun Aug 23 17:07:23 2015	(r287037)
@@ -16,6 +16,20 @@ from older versions of FreeBSD, try WITH
 stable/10, and then rebuild without this option. The bootstrap process from
 older version of current is a bit fragile.
 
+20150823:
+	The polarity of Pulse Per Second (PPS) capture events with the
+	uart(4) driver has been corrected.  Prior to this change the PPS
+	"assert" event corresponded to the trailing edge of a positive PPS
+	pulse and the "clear" event was the leading edge of the next pulse.
+	
+	As the width of a PPS pulse in a typical GPS receiver is on the
+	order of 1 millisecond, most users will not notice any significant
+	difference with this change.
+	
+	Anyone who has compensated for the historical polarity reversal by
+	configuring a negative offset equal to the pulse width will need to
+	remove that workaround.
+
 20150822:
 	From legacy ata(4) driver was removed support for SATA controllers
 	supported by more functional drivers ahci(4), siis(4) and mvs(4).

Modified: stable/10/share/man/man4/uart.4
==============================================================================
--- stable/10/share/man/man4/uart.4	Sun Aug 23 16:22:21 2015	(r287036)
+++ stable/10/share/man/man4/uart.4	Sun Aug 23 17:07:23 2015	(r287037)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 12, 2008
+.Dd August 10, 2015
 .Dt UART 4
 .Os
 .Sh NAME
@@ -151,6 +151,39 @@ SCC: serial communications controllers s
 device driver.
 .El
 .\"
+.Sh Pulse Per Second (PPS) Timing Interface
+The
+.Nm
+driver can capture PPS timing information as defined in RFC 2783.
+The API, accessed via
+.Xr ioctl 8 ,
+is available on the tty device.
+To use the PPS capture feature with
+.Xr ntpd 8 ,
+symlink the tty device to
+.Va /dev/pps0.
+.Pp
+The
+.Va hw.uart.pps_mode
+tunable configures the PPS capture mode for all uart devices;
+it can be set in
+.Xr loader.conf 5 .
+The
+.Va dev.uart.0.pps_mode
+sysctl configures the PPS capture mode for a specific uart device;
+it can be set in
+.Xr loader.conf 5
+or
+.Xr sysctl.conf 5 .
+The following capture modes are available:
+.Bl -tag -compact -offset "mmmm" -width "mmmm"
+.It 0
+Capture disabled.
+.It 1
+Capture pulses on the CTS line.
+.It 2
+Capture pulses on the DCD line (default).
+.El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/ttyu?.init" -compact
 .It Pa /dev/ttyu?

Modified: stable/10/sys/dev/uart/uart_bus.h
==============================================================================
--- stable/10/sys/dev/uart/uart_bus.h	Sun Aug 23 16:22:21 2015	(r287036)
+++ stable/10/sys/dev/uart/uart_bus.h	Sun Aug 23 17:07:23 2015	(r287037)
@@ -48,14 +48,6 @@
 #define	UART_STAT_OVERRUN	0x0400
 #define	UART_STAT_PARERR	0x0800
 
-#ifdef UART_PPS_ON_CTS
-#define	UART_SIG_DPPS		SER_DCTS
-#define	UART_SIG_PPS		SER_CTS
-#else
-#define	UART_SIG_DPPS		SER_DDCD
-#define	UART_SIG_PPS		SER_DCD
-#endif
-
 /* UART_IOCTL() requests */
 #define	UART_IOCTL_BREAK	1
 #define	UART_IOCTL_IFLOW	2
@@ -119,6 +111,7 @@ struct uart_softc {
 
 	/* Pulse capturing support (PPS). */
 	struct pps_state sc_pps;
+	int		 sc_pps_mode;
 
 	/* Upper layer data. */
 	void		*sc_softih;
@@ -149,6 +142,7 @@ void uart_sched_softih(struct uart_softc
 
 int uart_tty_attach(struct uart_softc *);
 int uart_tty_detach(struct uart_softc *);
+struct mtx *uart_tty_getlock(struct uart_softc *);
 void uart_tty_intr(void *arg);
 
 /*

Modified: stable/10/sys/dev/uart/uart_core.c
==============================================================================
--- stable/10/sys/dev/uart/uart_core.c	Sun Aug 23 16:22:21 2015	(r287036)
+++ stable/10/sys/dev/uart/uart_core.c	Sun Aug 23 17:07:23 2015	(r287037)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/queue.h>
 #include <sys/reboot.h>
+#include <sys/sysctl.h>
 #include <machine/bus.h>
 #include <sys/rman.h>
 #include <machine/resource.h>
@@ -64,6 +65,108 @@ static MALLOC_DEFINE(M_UART, "UART", "UA
 static int uart_poll_freq = UART_POLL_FREQ;
 TUNABLE_INT("debug.uart_poll_freq", &uart_poll_freq);
 
+#define	PPS_MODE_DISABLED	0
+#define	PPS_MODE_CTS		1
+#define	PPS_MODE_DCD		2
+
+static inline int
+uart_pps_signal(int pps_mode)
+{
+
+	switch(pps_mode) {
+	case PPS_MODE_CTS:
+		return (SER_CTS);
+	case PPS_MODE_DCD:
+		return (SER_DCD);
+	}
+	return (0);
+}
+static inline int
+uart_pps_mode_valid(int pps_mode)
+{
+
+	switch(pps_mode) {
+	case PPS_MODE_DISABLED:
+	case PPS_MODE_CTS:
+	case PPS_MODE_DCD:
+		return (true);
+	}
+	return (false);
+}
+
+static const char *
+uart_pps_mode_name(int pps_mode)
+{
+	switch(pps_mode) {
+	case PPS_MODE_DISABLED:
+		return ("disabled");
+	case PPS_MODE_CTS:
+		return ("CTS");
+	case PPS_MODE_DCD:
+		return ("DCD");
+	}
+	return ("invalid");
+}
+
+static int
+uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct uart_softc *sc;
+	int err, tmp;
+
+	sc = arg1;
+	tmp = sc->sc_pps_mode;
+	err = sysctl_handle_int(oidp, &tmp, 0, req);
+	if (err != 0 || req->newptr == NULL)
+		return (err);
+	if (!uart_pps_mode_valid(tmp))
+		return (EINVAL);
+	sc->sc_pps_mode = tmp;
+	return(0);
+}
+
+static void
+uart_pps_init(struct uart_softc *sc)
+{
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *tree;
+
+	ctx = device_get_sysctl_ctx(sc->sc_dev);
+	tree = device_get_sysctl_tree(sc->sc_dev);
+
+	/*
+	 * The historical default for pps capture mode is either DCD or CTS,
+	 * depending on the UART_PPS_ON_CTS kernel option.  Start with that,
+	 * then try to fetch the tunable that overrides the mode for all uart
+	 * devices, then try to fetch the sysctl-tunable that overrides the mode
+	 * for one specific device.
+	 */
+#ifdef UART_PPS_ON_CTS
+	sc->sc_pps_mode = PPS_MODE_CTS;
+#else
+	sc->sc_pps_mode = PPS_MODE_DCD;
+#endif
+	TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode);
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode",
+	    CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uart_pps_mode_sysctl, "I",
+	    "pulse capturing mode - 0/1/2 - disabled/CTS/DCD");
+
+	if (!uart_pps_mode_valid(sc->sc_pps_mode)) {
+		device_printf(sc->sc_dev, 
+		    "Invalid pps_mode %d configured; disabling PPS capture\n",
+		    sc->sc_pps_mode);
+		sc->sc_pps_mode = PPS_MODE_DISABLED;
+	} else if (bootverbose) {
+		device_printf(sc->sc_dev, "PPS capture mode %d (%s)\n",
+		    sc->sc_pps_mode, uart_pps_mode_name(sc->sc_pps_mode));
+	}
+
+	sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
+	sc->sc_pps.driver_mtx = uart_tty_getlock(sc);
+	sc->sc_pps.driver_abi = PPS_ABI_VERSION;
+	pps_init_abi(&sc->sc_pps);
+}
+
 void
 uart_add_sysdev(struct uart_devinfo *di)
 {
@@ -199,15 +302,22 @@ static __inline int
 uart_intr_sigchg(void *arg)
 {
 	struct uart_softc *sc = arg;
-	int new, old, sig;
+	int new, old, pps_sig, sig;
 
 	sig = UART_GETSIG(sc);
 
+	/*
+	 * Time pulse counting support. Note that both CTS and DCD are
+	 * active-low signals. The status bit is high to indicate that
+	 * the signal on the line is low, which corresponds to a PPS
+	 * clear event.
+	 */
 	if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) {
-		if (sig & UART_SIG_DPPS) {
+		pps_sig = uart_pps_signal(sc->sc_pps_mode);
+		if (sig & SER_DELTA(pps_sig)) {
 			pps_capture(&sc->sc_pps);
-			pps_event(&sc->sc_pps, (sig & UART_SIG_PPS) ?
-			    PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
+			pps_event(&sc->sc_pps, (sig & pps_sig) ?
+			    PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
 		}
 	}
 
@@ -499,9 +609,6 @@ uart_bus_attach(device_t dev)
 		    sc->sc_sysdev->stopbits);
 	}
 
-	sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
-	pps_init(&sc->sc_pps);
-
 	sc->sc_leaving = 0;
 	sc->sc_testintr = 1;
 	filt = uart_intr(sc);
@@ -554,10 +661,14 @@ uart_bus_attach(device_t dev)
 		printf("\n");
 	}
 
-	error = (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL)
-	    ? (*sc->sc_sysdev->attach)(sc) : uart_tty_attach(sc);
-	if (error)
-		goto fail;
+	if (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) {
+		if ((error = sc->sc_sysdev->attach(sc)) != 0)
+			goto fail;
+	} else {
+		if ((error = uart_tty_attach(sc)) != 0)
+			goto fail;
+		uart_pps_init(sc);
+	}
 
 	if (sc->sc_sysdev != NULL)
 		sc->sc_sysdev->hwmtx = sc->sc_hwmtx;

Modified: stable/10/sys/dev/uart/uart_tty.c
==============================================================================
--- stable/10/sys/dev/uart/uart_tty.c	Sun Aug 23 16:22:21 2015	(r287036)
+++ stable/10/sys/dev/uart/uart_tty.c	Sun Aug 23 17:07:23 2015	(r287037)
@@ -410,3 +410,13 @@ uart_tty_detach(struct uart_softc *sc)
 
 	return (0);
 }
+
+struct mtx *
+uart_tty_getlock(struct uart_softc *sc)
+{
+
+	if (sc->sc_u.u_tty.tp != NULL)
+		return (tty_getlock(sc->sc_u.u_tty.tp));
+	else
+		return (NULL);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508231707.t7NH7O5W013396>