All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
@ 2014-03-08 19:42 Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins Richard Cochran
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch series introduces a way of changing the auxiliary PTP
Hardware Clock functions (periodic output signals and time stamping
external signals) at run time. In the past on the netdev list, we have
discussed other ways to handle this, such as module parameters and
ethtool. This series implements a new PHC ioctl because that is the
most natural way. Users already activate the auxiliary functions via
the ioctls. The sysfs interface has also been expanded so that the pin
configuration can be programmed using shell scripts.

The first patch adds the new ioctls. The PHC subsystem does most of
the work of maintaining the function-to-pin mapping. Drivers will only
need to allocate and initialize a pin configuration table and also
provide a new method that validates a particular assignment.

Patches 5 and 6 just clean up a couple of issues in the phyter driver,
and the remaining patches actually hook the phyter's pins into the new
system.

Comments and questions are most welcome.

Thanks,
Richard


Richard Cochran (9):
  ptp: introduce programmable pins.
  ptp: add the pin GET/SETFUNC ioctls to the testptp program.
  ptp: expose the programmable pins via sysfs
  ptp: drivers: set the number of programmable pins.
  dp83640: trivial fixes
  dp83640: correct the periodic output frequency
  dp83640: implement programmable pin functions.
  dp83640: let external input pins from the module parameters be
    defaults.
  dp83640: let the periodic pin from the module parameter be a default.

 Documentation/ABI/testing/sysfs-ptp              |   20 ++++
 Documentation/ptp/testptp.c                      |   58 +++++++++-
 drivers/net/ethernet/adi/bfin_mac.c              |    1 +
 drivers/net/ethernet/broadcom/tg3.c              |    1 +
 drivers/net/ethernet/freescale/fec_ptp.c         |    1 +
 drivers/net/ethernet/freescale/gianfar_ptp.c     |    1 +
 drivers/net/ethernet/intel/e1000e/ptp.c          |    1 +
 drivers/net/ethernet/mellanox/mlx4/en_clock.c    |    1 +
 drivers/net/ethernet/sfc/ptp.c                   |    1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c |    1 +
 drivers/net/ethernet/ti/cpts.c                   |    1 +
 drivers/net/ethernet/tile/tilegx.c               |    1 +
 drivers/net/phy/dp83640.c                        |   93 ++++++++++++---
 drivers/ptp/ptp_chardev.c                        |  133 +++++++++++++++++++++-
 drivers/ptp/ptp_clock.c                          |   23 ++++
 drivers/ptp/ptp_ixp46x.c                         |    1 +
 drivers/ptp/ptp_pch.c                            |    1 +
 drivers/ptp/ptp_private.h                        |    7 ++
 drivers/ptp/ptp_sysfs.c                          |  109 ++++++++++++++++++
 include/linux/ptp_clock_kernel.h                 |   33 ++++++
 include/uapi/linux/ptp_clock.h                   |   39 ++++++-
 21 files changed, 507 insertions(+), 20 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins.
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-10 12:53     ` Sørensen, Stefan
  2014-03-11  7:58   ` Christian Riesch
  2014-03-08 19:42 ` [PATCH RFC net-next v1 2/9] ptp: add the pin GET/SETFUNC ioctls to the testptp program Richard Cochran
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch adds a pair of new ioctls to the PTP Hardware Clock device
interface. Using the ioctls, user space programs can query each pin to
find out its current function and also reprogram a different function
if desired.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/ptp/ptp_chardev.c        |  133 +++++++++++++++++++++++++++++++++++++-
 drivers/ptp/ptp_clock.c          |   23 +++++++
 drivers/ptp/ptp_private.h        |    4 ++
 include/linux/ptp_clock_kernel.h |   33 ++++++++++
 include/uapi/linux/ptp_clock.h   |   39 ++++++++++-
 5 files changed, 230 insertions(+), 2 deletions(-)

diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 34a0c60..dc13d1e 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -25,6 +25,104 @@
 
 #include "ptp_private.h"
 
+static int ptp_disable_pinfunc(struct ptp_clock_info *ops,
+			       enum ptp_pin_function func, unsigned int chan)
+{
+	struct ptp_clock_request rq;
+	int err = 0;
+
+	memset(&rq, 0, sizeof(rq));
+
+	switch (func) {
+	case PTP_PF_NONE:
+		break;
+	case PTP_PF_EXTTS:
+		rq.type = PTP_CLK_REQ_EXTTS;
+		rq.extts.index = chan;
+		err = ops->enable(ops, &rq, 0);
+		break;
+	case PTP_PF_PEROUT:
+		rq.type = PTP_CLK_REQ_PEROUT;
+		rq.perout.index = chan;
+		err = ops->enable(ops, &rq, 0);
+		break;
+	case PTP_PF_PHYSYNC:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+int ptp_setpin(struct ptp_clock *ptp, unsigned int pin,
+	       enum ptp_pin_function func, unsigned int chan)
+{
+	struct ptp_clock_info *info = ptp->info;
+	struct ptp_pin_desc *pin1 = NULL, *pin2 = &info->pin_config[pin];
+	unsigned int i;
+
+	/* Check to see if any other pin previously had this function. */
+	if (mutex_lock_interruptible(&ptp->pincfg_mux))
+		return -ERESTARTSYS;
+	for (i = 0; i < info->n_pins; i++) {
+		if (info->pin_config[i].func == func &&
+		    info->pin_config[i].chan == chan) {
+			pin1 = &info->pin_config[i];
+			break;
+		}
+	}
+	mutex_unlock(&ptp->pincfg_mux);
+	if (pin1 && i == pin)
+		return 0;
+
+	/* Check the desired function and channel. */
+	switch (func) {
+	case PTP_PF_NONE:
+		break;
+	case PTP_PF_EXTTS:
+		if (chan >= info->n_ext_ts)
+			return -EINVAL;
+		break;
+	case PTP_PF_PEROUT:
+		if (chan >= info->n_per_out)
+			return -EINVAL;
+		break;
+	case PTP_PF_PHYSYNC:
+		pr_err("sorry, cannot reassign the calibration pin\n");
+		return -EINVAL;
+	default:
+		return -EINVAL;
+	}
+
+	if (pin1 && pin1->func == PTP_PF_PHYSYNC) {
+		pr_err("sorry, cannot reprogram the calibration pin\n");
+		return -EINVAL;
+	}
+
+	if (info->setpin(info, pin, func, chan)) {
+		pr_err("driver cannot use function %u on pin %u\n", func, chan);
+		return -EOPNOTSUPP;
+	}
+
+	/* Disable whatever function was previously assigned. */
+	ptp_disable_pinfunc(info, pin2->func, pin2->chan);
+	if (pin1)
+		ptp_disable_pinfunc(info, func, chan);
+
+	if (mutex_lock_interruptible(&ptp->pincfg_mux))
+		return -ERESTARTSYS;
+	pin2->func = func;
+	pin2->chan = chan;
+	if (pin1) {
+		pin1->func = PTP_PF_NONE;
+		pin1->chan = 0;
+	}
+	mutex_unlock(&ptp->pincfg_mux);
+
+	return 0;
+}
+
 int ptp_open(struct posix_clock *pc, fmode_t fmode)
 {
 	return 0;
@@ -35,12 +133,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 	struct ptp_clock_caps caps;
 	struct ptp_clock_request req;
 	struct ptp_sys_offset *sysoff = NULL;
+	struct ptp_pin_desc pd;
 	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
 	struct ptp_clock_info *ops = ptp->info;
 	struct ptp_clock_time *pct;
 	struct timespec ts;
 	int enable, err = 0;
-	unsigned int i;
+	unsigned int i, pin_index;
 
 	switch (cmd) {
 
@@ -51,6 +150,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 		caps.n_ext_ts = ptp->info->n_ext_ts;
 		caps.n_per_out = ptp->info->n_per_out;
 		caps.pps = ptp->info->pps;
+		caps.n_pins = ptp->info->n_pins;
 		if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
 			err = -EFAULT;
 		break;
@@ -126,6 +226,37 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 			err = -EFAULT;
 		break;
 
+	case PTP_PIN_GETFUNC:
+		if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
+			err = -EFAULT;
+			break;
+		}
+		pin_index = pd.index;
+		if (pin_index >= ops->n_pins) {
+			err = -EINVAL;
+			break;
+		}
+		if (mutex_lock_interruptible(&ptp->pincfg_mux))
+			return -ERESTARTSYS;
+		pd = ops->pin_config[pin_index];
+		mutex_unlock(&ptp->pincfg_mux);
+		if (!err && copy_to_user((void __user *)arg, &pd, sizeof(pd)))
+			err = -EFAULT;
+		break;
+
+	case PTP_PIN_SETFUNC:
+		if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
+			err = -EFAULT;
+			break;
+		}
+		pin_index = pd.index;
+		if (pin_index >= ops->n_pins) {
+			err = -EINVAL;
+			break;
+		}
+		err = ptp_setpin(ptp, pin_index, pd.func, pd.chan);
+		break;
+
 	default:
 		err = -ENOTTY;
 		break;
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index a8319b2..3105d1d 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -169,6 +169,7 @@ static void delete_ptp_clock(struct posix_clock *pc)
 	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
 
 	mutex_destroy(&ptp->tsevq_mux);
+	mutex_destroy(&ptp->pincfg_mux);
 	ida_simple_remove(&ptp_clocks_map, ptp->index);
 	kfree(ptp);
 }
@@ -203,6 +204,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 	ptp->index = index;
 	spin_lock_init(&ptp->tsevq.lock);
 	mutex_init(&ptp->tsevq_mux);
+	mutex_init(&ptp->pincfg_mux);
 	init_waitqueue_head(&ptp->tsev_wq);
 
 	/* Create a new device in our class. */
@@ -249,6 +251,7 @@ no_sysfs:
 	device_destroy(ptp_class, ptp->devid);
 no_device:
 	mutex_destroy(&ptp->tsevq_mux);
+	mutex_destroy(&ptp->pincfg_mux);
 no_slot:
 	kfree(ptp);
 no_memory:
@@ -305,6 +308,26 @@ int ptp_clock_index(struct ptp_clock *ptp)
 }
 EXPORT_SYMBOL(ptp_clock_index);
 
+int ptp_find_pin(struct ptp_clock *ptp,
+		 enum ptp_pin_function func, unsigned int chan)
+{
+	struct ptp_pin_desc *pin = NULL;
+	int i;
+
+	mutex_lock(&ptp->pincfg_mux);
+	for (i = 0; i < ptp->info->n_pins; i++) {
+		if (ptp->info->pin_config[i].func == func &&
+		    ptp->info->pin_config[i].chan == chan) {
+			pin = &ptp->info->pin_config[i];
+			break;
+		}
+	}
+	mutex_unlock(&ptp->pincfg_mux);
+
+	return pin ? pin - ptp->info->pin_config : -1;
+}
+EXPORT_SYMBOL(ptp_find_pin);
+
 /* module operations */
 
 static void __exit ptp_exit(void)
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index df03f2e..253e942 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -48,6 +48,7 @@ struct ptp_clock {
 	long dialed_frequency; /* remembers the frequency adjustment */
 	struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
 	struct mutex tsevq_mux; /* one process at a time reading the fifo */
+	struct mutex pincfg_mux; /* protect concurrent info->pin_config access */
 	wait_queue_head_t tsev_wq;
 	int defunct; /* tells readers to go away when clock is being removed */
 };
@@ -69,6 +70,9 @@ static inline int queue_cnt(struct timestamp_event_queue *q)
  * see ptp_chardev.c
  */
 
+int ptp_setpin(struct ptp_clock *ptp, unsigned int pin,
+	       enum ptp_pin_function func, unsigned int chan);
+
 long ptp_ioctl(struct posix_clock *pc,
 	       unsigned int cmd, unsigned long arg);
 
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 38a9935..04b0d42 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -49,7 +49,11 @@ struct ptp_clock_request {
  * @n_alarm:   The number of programmable alarms.
  * @n_ext_ts:  The number of external time stamp channels.
  * @n_per_out: The number of programmable periodic signals.
+ * @n_pins:    The number of programmable pins.
  * @pps:       Indicates whether the clock supports a PPS callback.
+ * @pin_config: Array of length 'n_pins'. If the number of
+ *              programmable pins is nonzero, then drivers must
+ *              allocate and initialize this array.
  *
  * clock operations
  *
@@ -70,6 +74,18 @@ struct ptp_clock_request {
  *            parameter request: Desired resource to enable or disable.
  *            parameter on: Caller passes one to enable or zero to disable.
  *
+ * @setpin:   Confirm that a pin can perform a given function. The PTP
+ *            Hardware Clock subsystem maintains the 'pin_config'
+ *            array on behalf of the drivers, but the PHC subsystem
+ *            assumes that every pin can perform every function. This
+ *            hook gives drivers a way of telling the core about
+ *            limitations on specific pins. This function must return
+ *            zero if the function can be assigned to this pin, and
+ *            nonzero otherwise.
+ *            parameter pin: index of the pin in question.
+ *            parameter func: the desired function to use.
+ *            parameter chan: the function channel index to use.
+ *
  * Drivers should embed their ptp_clock_info within a private
  * structure, obtaining a reference to it using container_of().
  *
@@ -83,13 +99,17 @@ struct ptp_clock_info {
 	int n_alarm;
 	int n_ext_ts;
 	int n_per_out;
+	int n_pins;
 	int pps;
+	struct ptp_pin_desc *pin_config;
 	int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
 	int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
 	int (*gettime)(struct ptp_clock_info *ptp, struct timespec *ts);
 	int (*settime)(struct ptp_clock_info *ptp, const struct timespec *ts);
 	int (*enable)(struct ptp_clock_info *ptp,
 		      struct ptp_clock_request *request, int on);
+	int (*setpin)(struct ptp_clock_info *ptp, unsigned int pin,
+		      enum ptp_pin_function func, unsigned int chan);
 };
 
 struct ptp_clock;
@@ -156,4 +176,17 @@ extern void ptp_clock_event(struct ptp_clock *ptp,
 
 extern int ptp_clock_index(struct ptp_clock *ptp);
 
+/**
+ * ptp_find_pin() - obtain the pin index of a given auxiliary function
+ *
+ * @ptp:    The clock obtained from ptp_clock_register().
+ * @func:   One of the ptp_pin_function enumerated values.
+ * @chan:   The particular functional channel to find.
+ * Return:  Pin index in the range of zero to ptp_clock_caps.n_pins - 1,
+ *          or -1 if the auxiliary function cannot be found.
+ */
+
+int ptp_find_pin(struct ptp_clock *ptp,
+		 enum ptp_pin_function func, unsigned int chan);
+
 #endif
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index b65c834..f0b7bfe 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -50,7 +50,8 @@ struct ptp_clock_caps {
 	int n_ext_ts;  /* Number of external time stamp channels. */
 	int n_per_out; /* Number of programmable periodic signals. */
 	int pps;       /* Whether the clock supports a PPS callback. */
-	int rsv[15];   /* Reserved for future use. */
+	int n_pins;    /* Number of input/output pins. */
+	int rsv[14];   /* Reserved for future use. */
 };
 
 struct ptp_extts_request {
@@ -80,6 +81,40 @@ struct ptp_sys_offset {
 	struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
 };
 
+enum ptp_pin_function {
+	PTP_PF_NONE,
+	PTP_PF_EXTTS,
+	PTP_PF_PEROUT,
+	PTP_PF_PHYSYNC,
+};
+
+struct ptp_pin_desc {
+	/*
+	 * Hardware specific human readable pin name. This field is
+	 * set by the kernel during the PTP_PIN_GETFUNC ioctl and is
+	 * ignored for the PTP_PIN_SETFUNC ioctl.
+	 */
+	char name[64];
+	/*
+	 * Pin index in the range of zero to ptp_clock_caps.n_pins - 1.
+	 */
+	unsigned int index;
+	/*
+	 * Which of the PTP_PF_xxx functions to use on this pin.
+	 */
+	unsigned int func;
+	/*
+	 * The specific channel to use for this function.
+	 * This corresponds to the 'index' field of the
+	 * PTP_EXTTS_REQUEST and PTP_PEROUT_REQUEST ioctls.
+	 */
+	unsigned int chan;
+	/*
+	 * Reserved for future use.
+	 */
+	unsigned int rsv[5];
+};
+
 #define PTP_CLK_MAGIC '='
 
 #define PTP_CLOCK_GETCAPS  _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps)
@@ -87,6 +122,8 @@ struct ptp_sys_offset {
 #define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request)
 #define PTP_ENABLE_PPS     _IOW(PTP_CLK_MAGIC, 4, int)
 #define PTP_SYS_OFFSET     _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
+#define PTP_PIN_GETFUNC    _IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
+#define PTP_PIN_SETFUNC    _IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
 
 struct ptp_extts_event {
 	struct ptp_clock_time t; /* Time event occured. */
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 2/9] ptp: add the pin GET/SETFUNC ioctls to the testptp program.
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 3/9] ptp: expose the programmable pins via sysfs Richard Cochran
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch adds a option to the test program that lists the
programmable pins on a PTP Hardware Clock device, assuming there
are any such pins. A second option lets the user reprogram the
auxiliary function of a single pin.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 Documentation/ptp/testptp.c |   58 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 55 insertions(+), 3 deletions(-)

diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c
index 4aba043..e9eaee6 100644
--- a/Documentation/ptp/testptp.c
+++ b/Documentation/ptp/testptp.c
@@ -120,6 +120,13 @@ static void usage(char *progname)
 		" -i val     index for event/trigger\n"
 		" -k val     measure the time offset between system and phc clock\n"
 		"            for 'val' times (Maximum 25)\n"
+		" -l         list the current pin configuration\n"
+		" -L pin,val configure pin index 'pin' with function 'val'\n"
+		"            the channel index is taken from the '-i' option\n"
+		"            'val' specifies the auxiliary function:\n"
+		"            0 - none\n"
+		"            1 - external time stamp\n"
+		"            2 - periodic output\n"
 		" -p val     enable output with a period of 'val' nanoseconds\n"
 		" -P val     enable or disable (val=1|0) the system clock PPS\n"
 		" -s         set the ptp clock time from the system time\n"
@@ -134,6 +141,7 @@ int main(int argc, char *argv[])
 	struct ptp_extts_event event;
 	struct ptp_extts_request extts_request;
 	struct ptp_perout_request perout_request;
+	struct ptp_pin_desc desc;
 	struct timespec ts;
 	struct timex tx;
 
@@ -156,11 +164,13 @@ int main(int argc, char *argv[])
 	int extts = 0;
 	int gettime = 0;
 	int index = 0;
+	int list_pins = 0;
 	int oneshot = 0;
 	int pct_offset = 0;
 	int n_samples = 0;
 	int periodic = 0;
 	int perout = -1;
+	int pin_index = -1, pin_func;
 	int pps = -1;
 	int settime = 0;
 
@@ -169,7 +179,7 @@ int main(int argc, char *argv[])
 
 	progname = strrchr(argv[0], '/');
 	progname = progname ? 1+progname : argv[0];
-	while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:p:P:sSt:v"))) {
+	while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:v"))) {
 		switch (c) {
 		case 'a':
 			oneshot = atoi(optarg);
@@ -199,6 +209,16 @@ int main(int argc, char *argv[])
 			pct_offset = 1;
 			n_samples = atoi(optarg);
 			break;
+		case 'l':
+			list_pins = 1;
+			break;
+		case 'L':
+			cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func);
+			if (cnt != 2) {
+				usage(progname);
+				return -1;
+			}
+			break;
 		case 'p':
 			perout = atoi(optarg);
 			break;
@@ -245,12 +265,14 @@ int main(int argc, char *argv[])
 			       "  %d programmable alarms\n"
 			       "  %d external time stamp channels\n"
 			       "  %d programmable periodic signals\n"
-			       "  %d pulse per second\n",
+			       "  %d pulse per second\n"
+			       "  %d programmable pins\n",
 			       caps.max_adj,
 			       caps.n_alarm,
 			       caps.n_ext_ts,
 			       caps.n_per_out,
-			       caps.pps);
+			       caps.pps,
+			       caps.n_pins);
 		}
 	}
 
@@ -331,6 +353,24 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	if (list_pins) {
+		int n_pins = 0;
+		if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
+			perror("PTP_CLOCK_GETCAPS");
+		} else {
+			n_pins = caps.n_pins;
+		}
+		for (i = 0; i < n_pins; i++) {
+			desc.index = i;
+			if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) {
+				perror("PTP_PIN_GETFUNC");
+				break;
+			}
+			printf("name %s index %u func %u chan %u\n",
+			       desc.name, desc.index, desc.func, desc.chan);
+		}
+	}
+
 	if (oneshot) {
 		install_handler(SIGALRM, handle_alarm);
 		/* Create a timer. */
@@ -392,6 +432,18 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	if (pin_index >= 0) {
+		memset(&desc, 0, sizeof(desc));
+		desc.index = pin_index;
+		desc.func = pin_func;
+		desc.chan = index;
+		if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) {
+			perror("PTP_PIN_SETFUNC");
+		} else {
+			puts("set pin function okay");
+		}
+	}
+
 	if (pps != -1) {
 		int enable = pps ? 1 : 0;
 		if (ioctl(fd, PTP_ENABLE_PPS, enable)) {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 3/9] ptp: expose the programmable pins via sysfs
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 2/9] ptp: add the pin GET/SETFUNC ioctls to the testptp program Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 4/9] ptp: drivers: set the number of programmable pins Richard Cochran
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch adds the sysfs hooks needed in order to get and set the
programmable pin settings.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 Documentation/ABI/testing/sysfs-ptp |   20 +++++++
 drivers/ptp/ptp_private.h           |    3 +
 drivers/ptp/ptp_sysfs.c             |  109 +++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp
index 05aeedf..44806a6 100644
--- a/Documentation/ABI/testing/sysfs-ptp
+++ b/Documentation/ABI/testing/sysfs-ptp
@@ -54,6 +54,26 @@ Description:
 		This file contains the number of programmable periodic
 		output channels offered by the PTP hardware clock.
 
+What:		/sys/class/ptp/ptpN/n_pins
+Date:		March 2014
+Contact:	Richard Cochran <richardcochran@gmail.com>
+Description:
+		This file contains the number of programmable pins
+		offered by the PTP hardware clock.
+
+What:		/sys/class/ptp/ptpN/pins
+Date:		March 2014
+Contact:	Richard Cochran <richardcochran@gmail.com>
+Description:
+		This directory contains one file for each programmable
+		pin offered by the PTP hardware clock. The file name
+		is the hardware dependent pin name. Reading from this
+		file produces two numbers, the assigned function (see
+		the PTP_PF_ enumeration values in linux/ptp_clock.h)
+		and the channel number. The function and channel
+		assignment may be changed by two writing numbers into
+		the file.
+
 What:		/sys/class/ptp/ptpN/pps_avaiable
 Date:		September 2010
 Contact:	Richard Cochran <richardcochran@gmail.com>
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 253e942..fb7c6b1 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -51,6 +51,9 @@ struct ptp_clock {
 	struct mutex pincfg_mux; /* protect concurrent info->pin_config access */
 	wait_queue_head_t tsev_wq;
 	int defunct; /* tells readers to go away when clock is being removed */
+	struct device_attribute *pin_dev_attr;
+	struct attribute **pin_attr;
+	struct attribute_group pin_attr_group;
 };
 
 /*
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index 13ec531..4495c4d 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #include <linux/capability.h>
+#include <linux/slab.h>
 
 #include "ptp_private.h"
 
@@ -42,6 +43,7 @@ PTP_SHOW_INT(max_adjustment, max_adj);
 PTP_SHOW_INT(n_alarms, n_alarm);
 PTP_SHOW_INT(n_external_timestamps, n_ext_ts);
 PTP_SHOW_INT(n_periodic_outputs, n_per_out);
+PTP_SHOW_INT(n_programmable_pins, n_pins);
 PTP_SHOW_INT(pps_available, pps);
 
 static struct attribute *ptp_attrs[] = {
@@ -50,6 +52,7 @@ static struct attribute *ptp_attrs[] = {
 	&dev_attr_n_alarms.attr,
 	&dev_attr_n_external_timestamps.attr,
 	&dev_attr_n_periodic_outputs.attr,
+	&dev_attr_n_programmable_pins.attr,
 	&dev_attr_pps_available.attr,
 	NULL,
 };
@@ -175,6 +178,60 @@ out:
 	return err;
 }
 
+static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name)
+{
+	int i;
+	for (i = 0; i < ptp->info->n_pins; i++) {
+		if (!strcmp(ptp->info->pin_config[i].name, name))
+			return i;
+	}
+	return -1;
+}
+
+static ssize_t ptp_pin_show(struct device *dev, struct device_attribute *attr,
+			    char *page)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	unsigned int func, chan;
+	int index;
+
+	index = ptp_pin_name2index(ptp, attr->attr.name);
+	if (index < 0)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&ptp->pincfg_mux))
+		return -ERESTARTSYS;
+
+	func = ptp->info->pin_config[index].func;
+	chan = ptp->info->pin_config[index].chan;
+
+	mutex_unlock(&ptp->pincfg_mux);
+
+	return snprintf(page, PAGE_SIZE, "%u %u\n", func, chan);
+}
+
+static ssize_t ptp_pin_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	unsigned int func, chan;
+	int cnt, err, index;
+
+	cnt = sscanf(buf, "%u %u", &func, &chan);
+	if (cnt != 2)
+		return -EINVAL;
+
+	index = ptp_pin_name2index(ptp, attr->attr.name);
+	if (index < 0)
+		return -EINVAL;
+
+	err = ptp_setpin(ptp, index, func, chan);
+	if (err)
+		return err;
+
+	return count;
+}
+
 static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
 static DEVICE_ATTR(fifo,         0444, extts_fifo_show, NULL);
 static DEVICE_ATTR(period,       0220, NULL, period_store);
@@ -195,7 +252,54 @@ int ptp_cleanup_sysfs(struct ptp_clock *ptp)
 	if (info->pps)
 		device_remove_file(dev, &dev_attr_pps_enable);
 
+	if (info->n_pins) {
+		sysfs_remove_group(&dev->kobj, &ptp->pin_attr_group);
+		kfree(ptp->pin_attr);
+		kfree(ptp->pin_dev_attr);
+	}
+	return 0;
+}
+
+static int ptp_populate_pins(struct ptp_clock *ptp)
+{
+	struct device *dev = ptp->dev;
+	struct ptp_clock_info *info = ptp->info;
+	int err = -ENOMEM, i, n_pins = info->n_pins;
+
+	ptp->pin_dev_attr = kzalloc(n_pins * sizeof(*ptp->pin_dev_attr),
+				    GFP_KERNEL);
+	if (!ptp->pin_dev_attr)
+		goto no_dev_attr;
+
+	ptp->pin_attr = kzalloc((1 + n_pins) * sizeof(struct attribute *),
+				GFP_KERNEL);
+	if (!ptp->pin_attr)
+		goto no_pin_attr;
+
+	for (i = 0; i < n_pins; i++) {
+		struct device_attribute *da = &ptp->pin_dev_attr[i];
+		sysfs_attr_init(&da->attr);
+		da->attr.name = info->pin_config[i].name;
+		da->attr.mode = 0644;
+		da->show = ptp_pin_show;
+		da->store = ptp_pin_store;
+		ptp->pin_attr[i] = &da->attr;
+	}
+
+	ptp->pin_attr_group.name = "pins";
+	ptp->pin_attr_group.attrs = ptp->pin_attr;
+
+	err = sysfs_create_group(&dev->kobj, &ptp->pin_attr_group);
+	if (err)
+		goto no_group;
 	return 0;
+
+no_group:
+	kfree(ptp->pin_attr);
+no_pin_attr:
+	kfree(ptp->pin_dev_attr);
+no_dev_attr:
+	return err;
 }
 
 int ptp_populate_sysfs(struct ptp_clock *ptp)
@@ -222,6 +326,11 @@ int ptp_populate_sysfs(struct ptp_clock *ptp)
 		if (err)
 			goto out4;
 	}
+	if (info->n_pins) {
+		err = ptp_populate_pins(ptp);
+		if (err)
+			goto out4;
+	}
 	return 0;
 out4:
 	if (info->n_per_out)
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 4/9] ptp: drivers: set the number of programmable pins.
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (2 preceding siblings ...)
  2014-03-08 19:42 ` [PATCH RFC net-next v1 3/9] ptp: expose the programmable pins via sysfs Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 5/9] dp83640: trivial fixes Richard Cochran
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch updates the many PTP Hardware Clock drivers with the
newly introduced field that advertises the number of programmable
pins. Some of these devices do have programmable pins, but the
implementation will have to wait for follow on patches.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/net/ethernet/adi/bfin_mac.c              |    1 +
 drivers/net/ethernet/broadcom/tg3.c              |    1 +
 drivers/net/ethernet/freescale/fec_ptp.c         |    1 +
 drivers/net/ethernet/freescale/gianfar_ptp.c     |    1 +
 drivers/net/ethernet/intel/e1000e/ptp.c          |    1 +
 drivers/net/ethernet/mellanox/mlx4/en_clock.c    |    1 +
 drivers/net/ethernet/sfc/ptp.c                   |    1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c |    1 +
 drivers/net/ethernet/ti/cpts.c                   |    1 +
 drivers/net/ethernet/tile/tilegx.c               |    1 +
 drivers/ptp/ptp_ixp46x.c                         |    1 +
 drivers/ptp/ptp_pch.c                            |    1 +
 12 files changed, 12 insertions(+)

diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index c0f68dc..83a8cdb 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -1040,6 +1040,7 @@ static struct ptp_clock_info bfin_ptp_caps = {
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
 	.n_per_out	= 0,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= bfin_ptp_adjfreq,
 	.adjtime	= bfin_ptp_adjtime,
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index e12735f..5130c58 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6322,6 +6322,7 @@ static const struct ptp_clock_info tg3_ptp_caps = {
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
 	.n_per_out	= 1,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= tg3_ptp_adjfreq,
 	.adjtime	= tg3_ptp_adjtime,
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 89ccb5b..82386b2 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -372,6 +372,7 @@ void fec_ptp_init(struct platform_device *pdev)
 	fep->ptp_caps.n_alarm = 0;
 	fep->ptp_caps.n_ext_ts = 0;
 	fep->ptp_caps.n_per_out = 0;
+	fep->ptp_caps.n_pins = 0;
 	fep->ptp_caps.pps = 0;
 	fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
 	fep->ptp_caps.adjtime = fec_ptp_adjtime;
diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index abc28da..bb56800 100644
--- a/drivers/net/ethernet/freescale/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
@@ -414,6 +414,7 @@ static struct ptp_clock_info ptp_gianfar_caps = {
 	.n_alarm	= 0,
 	.n_ext_ts	= N_EXT_TS,
 	.n_per_out	= 0,
+	.n_pins		= 0,
 	.pps		= 1,
 	.adjfreq	= ptp_gianfar_adjfreq,
 	.adjtime	= ptp_gianfar_adjtime,
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index 065f8c8..299ab50 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -191,6 +191,7 @@ static const struct ptp_clock_info e1000e_ptp_clock_info = {
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
 	.n_per_out	= 0,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= e1000e_phc_adjfreq,
 	.adjtime	= e1000e_phc_adjtime,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
index abaf6bb..57dda95 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
@@ -276,6 +276,7 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = {
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
 	.n_per_out	= 0,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= mlx4_en_phc_adjfreq,
 	.adjtime	= mlx4_en_phc_adjtime,
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 722344f..6b861e3 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -1194,6 +1194,7 @@ static const struct ptp_clock_info efx_phc_clock_info = {
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
 	.n_per_out	= 0,
+	.n_pins		= 0,
 	.pps		= 1,
 	.adjfreq	= efx_phc_adjfreq,
 	.adjtime	= efx_phc_adjtime,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index 7680581..b7ad356 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -164,6 +164,7 @@ static struct ptp_clock_info stmmac_ptp_clock_ops = {
 	.n_alarm = 0,
 	.n_ext_ts = 0,
 	.n_per_out = 0,
+	.n_pins = 0,
 	.pps = 0,
 	.adjfreq = stmmac_adjust_freq,
 	.adjtime = stmmac_adjust_time,
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index 8c351f1..372cb19 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -217,6 +217,7 @@ static struct ptp_clock_info cpts_info = {
 	.name		= "CTPS timer",
 	.max_adj	= 1000000,
 	.n_ext_ts	= 0,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= cpts_ptp_adjfreq,
 	.adjtime	= cpts_ptp_adjtime,
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 17503da..298d1c3 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -870,6 +870,7 @@ static struct ptp_clock_info ptp_mpipe_caps = {
 	.name		= "mPIPE clock",
 	.max_adj	= 999999999,
 	.n_ext_ts	= 0,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= ptp_mpipe_adjfreq,
 	.adjtime	= ptp_mpipe_adjtime,
diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c
index 4a08727..604d340 100644
--- a/drivers/ptp/ptp_ixp46x.c
+++ b/drivers/ptp/ptp_ixp46x.c
@@ -244,6 +244,7 @@ static struct ptp_clock_info ptp_ixp_caps = {
 	.name		= "IXP46X timer",
 	.max_adj	= 66666655,
 	.n_ext_ts	= N_EXT_TS,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= ptp_ixp_adjfreq,
 	.adjtime	= ptp_ixp_adjtime,
diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index 71a2559..90a1063 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -514,6 +514,7 @@ static struct ptp_clock_info ptp_pch_caps = {
 	.name		= "PCH timer",
 	.max_adj	= 50000000,
 	.n_ext_ts	= N_EXT_TS,
+	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= ptp_pch_adjfreq,
 	.adjtime	= ptp_pch_adjtime,
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 5/9] dp83640: trivial fixes
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (3 preceding siblings ...)
  2014-03-08 19:42 ` [PATCH RFC net-next v1 4/9] ptp: drivers: set the number of programmable pins Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 6/9] dp83640: correct the periodic output frequency Richard Cochran
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch cleans up the input checking code on the external time stamp
function by using an unsigned rather than a signed channel index.

Also, this patch corrects the author's email address. When this macro
was last changed, the top level domain part of the email address was
left behind.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/net/phy/dp83640.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 98e7cbf..d6c1061 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -424,13 +424,13 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
 	struct dp83640_clock *clock =
 		container_of(ptp, struct dp83640_clock, caps);
 	struct phy_device *phydev = clock->chosen->phydev;
-	int index;
+	unsigned int index;
 	u16 evnt, event_num, gpio_num;
 
 	switch (rq->type) {
 	case PTP_CLK_REQ_EXTTS:
 		index = rq->extts.index;
-		if (index < 0 || index >= N_EXT_TS)
+		if (index >= N_EXT_TS)
 			return -EINVAL;
 		event_num = EXT_EVENT + index;
 		evnt = EVNT_WR | (event_num & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
@@ -1363,7 +1363,7 @@ static void __exit dp83640_exit(void)
 }
 
 MODULE_DESCRIPTION("National Semiconductor DP83640 PHY driver");
-MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.at>");
+MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
 MODULE_LICENSE("GPL");
 
 module_init(dp83640_init);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 6/9] dp83640: correct the periodic output frequency
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (4 preceding siblings ...)
  2014-03-08 19:42 ` [PATCH RFC net-next v1 5/9] dp83640: trivial fixes Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 7/9] dp83640: implement programmable pin functions Richard Cochran
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

The phyter driver incorrectly feeds the value of the period into what
is in fact a pulse width register, resulting in the actual period
being twice the dialed value. This patch fixes the issue and renames a
variable to make the code at bit more clear.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/net/phy/dp83640.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index d6c1061..9e26555 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -271,7 +271,7 @@ static void periodic_output(struct dp83640_clock *clock,
 {
 	struct dp83640_private *dp83640 = clock->chosen;
 	struct phy_device *phydev = dp83640->phydev;
-	u32 sec, nsec, period;
+	u32 sec, nsec, pwidth;
 	u16 gpio, ptp_trig, trigger, val;
 
 	gpio = on ? gpio_tab[PEROUT_GPIO] : 0;
@@ -296,8 +296,9 @@ static void periodic_output(struct dp83640_clock *clock,
 
 	sec = clkreq->perout.start.sec;
 	nsec = clkreq->perout.start.nsec;
-	period = clkreq->perout.period.sec * 1000000000UL;
-	period += clkreq->perout.period.nsec;
+	pwidth = clkreq->perout.period.sec * 1000000000UL;
+	pwidth += clkreq->perout.period.nsec;
+	pwidth /= 2;
 
 	mutex_lock(&clock->extreg_lock);
 
@@ -310,8 +311,8 @@ static void periodic_output(struct dp83640_clock *clock,
 	ext_write(0, phydev, PAGE4, PTP_TDR, nsec >> 16);      /* ns[31:16] */
 	ext_write(0, phydev, PAGE4, PTP_TDR, sec & 0xffff);    /* sec[15:0] */
 	ext_write(0, phydev, PAGE4, PTP_TDR, sec >> 16);       /* sec[31:16] */
-	ext_write(0, phydev, PAGE4, PTP_TDR, period & 0xffff); /* ns[15:0] */
-	ext_write(0, phydev, PAGE4, PTP_TDR, period >> 16);    /* ns[31:16] */
+	ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff); /* ns[15:0] */
+	ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16);    /* ns[31:16] */
 
 	/*enable trigger*/
 	val &= ~TRIG_LOAD;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 7/9] dp83640: implement programmable pin functions.
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (5 preceding siblings ...)
  2014-03-08 19:42 ` [PATCH RFC net-next v1 6/9] dp83640: correct the periodic output frequency Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 8/9] dp83640: let external input pins from the module parameters be defaults Richard Cochran
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch adapts the dp83640 driver to allow reconfiguration of which
auxiliary function goes on which pin. The functions may be reassigned
freely with the one exception of the calibration function.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/net/phy/dp83640.c |   52 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 9e26555..f98998f 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -47,6 +47,7 @@
 #define CAL_EVENT	7
 #define CAL_TRIGGER	7
 #define PER_TRIGGER	6
+#define DP83640_N_PINS	12
 
 #define MII_DP83640_MICR 0x11
 #define MII_DP83640_MISR 0x12
@@ -173,6 +174,37 @@ MODULE_PARM_DESC(chosen_phy, \
 MODULE_PARM_DESC(gpio_tab, \
 	"Which GPIO line to use for which purpose: cal,perout,extts1,...,extts6");
 
+static void dp83640_gpio_defaults(struct ptp_pin_desc *pd)
+{
+	int i, index;
+
+	for (i = 0; i < DP83640_N_PINS; i++) {
+		snprintf(pd[i].name, sizeof(pd[i].name), "GPIO%d", 1 + i);
+		pd[i].index = i;
+	}
+
+	for (i = 0; i < GPIO_TABLE_SIZE; i++) {
+		if (gpio_tab[i] < 1 || gpio_tab[i] > DP83640_N_PINS) {
+			pr_err("gpio_tab[%d]=%hu out of range", i, gpio_tab[i]);
+			return;
+		}
+	}
+
+	index = gpio_tab[CALIBRATE_GPIO] - 1;
+	pd[index].func = PTP_PF_PHYSYNC;
+	pd[index].chan = 0;
+
+	index = gpio_tab[PEROUT_GPIO] - 1;
+	pd[index].func = PTP_PF_PEROUT;
+	pd[index].chan = 0;
+
+	for (i = EXTTS0_GPIO; i < GPIO_TABLE_SIZE; i++) {
+		index = gpio_tab[i] - 1;
+		pd[index].func = PTP_PF_EXTTS;
+		pd[index].chan = i - EXTTS0_GPIO;
+	}
+}
+
 /* a list of clocks and a mutex to protect it */
 static LIST_HEAD(phyter_clocks);
 static DEFINE_MUTEX(phyter_clocks_lock);
@@ -459,6 +491,12 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
 	return -EOPNOTSUPP;
 }
 
+static int ptp_dp83640_setpin(struct ptp_clock_info *ptp, unsigned int pin,
+			      enum ptp_pin_function func, unsigned int chan)
+{
+	return 0;
+}
+
 static u8 status_frame_dst[6] = { 0x01, 0x1B, 0x19, 0x00, 0x00, 0x00 };
 static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F };
 
@@ -876,6 +914,7 @@ static void dp83640_free_clocks(void)
 		mutex_destroy(&clock->extreg_lock);
 		mutex_destroy(&clock->clock_lock);
 		put_device(&clock->bus->dev);
+		kfree(clock->caps.pin_config);
 		kfree(clock);
 	}
 
@@ -895,12 +934,18 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
 	clock->caps.n_alarm	= 0;
 	clock->caps.n_ext_ts	= N_EXT_TS;
 	clock->caps.n_per_out	= 1;
+	clock->caps.n_pins	= DP83640_N_PINS;
 	clock->caps.pps		= 0;
 	clock->caps.adjfreq	= ptp_dp83640_adjfreq;
 	clock->caps.adjtime	= ptp_dp83640_adjtime;
 	clock->caps.gettime	= ptp_dp83640_gettime;
 	clock->caps.settime	= ptp_dp83640_settime;
 	clock->caps.enable	= ptp_dp83640_enable;
+	clock->caps.setpin	= ptp_dp83640_setpin;
+	/*
+	 * Convert the module param defaults into a dynamic pin configuration.
+	 */
+	dp83640_gpio_defaults(clock->caps.pin_config);
 	/*
 	 * Get a reference to this bus instance.
 	 */
@@ -951,6 +996,13 @@ static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus)
 	if (!clock)
 		goto out;
 
+	clock->caps.pin_config = kzalloc(sizeof(struct ptp_pin_desc) *
+					 DP83640_N_PINS, GFP_KERNEL);
+	if (!clock->caps.pin_config) {
+		kfree(clock);
+		clock = NULL;
+		goto out;
+	}
 	dp83640_clock_init(clock, bus);
 	list_add_tail(&phyter_clocks, &clock->list);
 out:
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 8/9] dp83640: let external input pins from the module parameters be defaults.
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (6 preceding siblings ...)
  2014-03-08 19:42 ` [PATCH RFC net-next v1 7/9] dp83640: implement programmable pin functions Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-08 19:42 ` [PATCH RFC net-next v1 9/9] dp83640: let the periodic pin from the module parameter be a default Richard Cochran
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch changes the driver to use the new pin configuration method when
programming the external time stamp input signals.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/net/phy/dp83640.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index f98998f..d60b90c 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -468,7 +468,10 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
 		event_num = EXT_EVENT + index;
 		evnt = EVNT_WR | (event_num & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
 		if (on) {
-			gpio_num = gpio_tab[EXTTS0_GPIO + index];
+			gpio_num = 1 + ptp_find_pin(clock->ptp_clock,
+						    PTP_PF_EXTTS, index);
+			if (gpio_num < 1)
+				return -EINVAL;
 			evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
 			if (rq->extts.flags & PTP_FALLING_EDGE)
 				evnt |= EVNT_FALL;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next v1 9/9] dp83640: let the periodic pin from the module parameter be a default.
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (7 preceding siblings ...)
  2014-03-08 19:42 ` [PATCH RFC net-next v1 8/9] dp83640: let external input pins from the module parameters be defaults Richard Cochran
@ 2014-03-08 19:42 ` Richard Cochran
  2014-03-10 12:52   ` Sørensen, Stefan
  2014-03-12  8:21 ` Christian Riesch
  10 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-08 19:42 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, Ben Hutchings, Christian Riesch, David Miller,
	Stefan Sørensen

This patch changes the driver use the new pin configuration method when
programming the periodic output signal.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
 drivers/net/phy/dp83640.c |   19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index d60b90c..a829fd5 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -298,15 +298,22 @@ static u64 phy2txts(struct phy_txts *p)
 	return ns;
 }
 
-static void periodic_output(struct dp83640_clock *clock,
-			    struct ptp_clock_request *clkreq, bool on)
+static int periodic_output(struct dp83640_clock *clock,
+			   struct ptp_clock_request *clkreq, bool on)
 {
 	struct dp83640_private *dp83640 = clock->chosen;
 	struct phy_device *phydev = dp83640->phydev;
 	u32 sec, nsec, pwidth;
 	u16 gpio, ptp_trig, trigger, val;
 
-	gpio = on ? gpio_tab[PEROUT_GPIO] : 0;
+	if (on) {
+		gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT, 0);
+		if (gpio < 1)
+			return -EINVAL;
+	} else {
+		gpio = 0;
+	}
+
 	trigger = PER_TRIGGER;
 
 	ptp_trig = TRIG_WR |
@@ -323,7 +330,7 @@ static void periodic_output(struct dp83640_clock *clock,
 		ext_write(0, phydev, PAGE5, PTP_TRIG, ptp_trig);
 		ext_write(0, phydev, PAGE4, PTP_CTL, val);
 		mutex_unlock(&clock->extreg_lock);
-		return;
+		return 0;
 	}
 
 	sec = clkreq->perout.start.sec;
@@ -352,6 +359,7 @@ static void periodic_output(struct dp83640_clock *clock,
 	ext_write(0, phydev, PAGE4, PTP_CTL, val);
 
 	mutex_unlock(&clock->extreg_lock);
+	return 0;
 }
 
 /* ptp clock methods */
@@ -484,8 +492,7 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
 	case PTP_CLK_REQ_PEROUT:
 		if (rq->perout.index != 0)
 			return -EINVAL;
-		periodic_output(clock, rq, on);
-		return 0;
+		return periodic_output(clock, rq, on);
 
 	default:
 		break;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
@ 2014-03-10 12:52   ` Sørensen, Stefan
  2014-03-08 19:42 ` [PATCH RFC net-next v1 2/9] ptp: add the pin GET/SETFUNC ioctls to the testptp program Richard Cochran
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Sørensen, Stefan @ 2014-03-10 12:52 UTC (permalink / raw)
  To: richardcochran; +Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1270 bytes --]

On Sat, 2014-03-08 at 20:42 +0100, Richard Cochran wrote:
> This patch series introduces a way of changing the auxiliary PTP
> Hardware Clock functions (periodic output signals and time stamping
> external signals) at run time. In the past on the netdev list, we have
> discussed other ways to handle this, such as module parameters and
> ethtool. This series implements a new PHC ioctl because that is the
> most natural way. Users already activate the auxiliary functions via
> the ioctls. The sysfs interface has also been expanded so that the pin
> configuration can be programmed using shell scripts.

A few general questions / thoughts:

What are the n_ext_ts and n_per_out supposed to be set to now? The
number of pins configured for the relevant function or the number of
channels that are available for the function?

The implementation is limited to a single function for each pin - the
dp83640 supports an ext_ts and several periodic outputs on the same pin,
but I do not see that many real-world uses. 

I have done a few short run-time tests, and so far everything is working
as expected.

Stefan
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
@ 2014-03-10 12:52   ` Sørensen, Stefan
  0 siblings, 0 replies; 23+ messages in thread
From: Sørensen, Stefan @ 2014-03-10 12:52 UTC (permalink / raw)
  To: richardcochran; +Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

On Sat, 2014-03-08 at 20:42 +0100, Richard Cochran wrote:
> This patch series introduces a way of changing the auxiliary PTP
> Hardware Clock functions (periodic output signals and time stamping
> external signals) at run time. In the past on the netdev list, we have
> discussed other ways to handle this, such as module parameters and
> ethtool. This series implements a new PHC ioctl because that is the
> most natural way. Users already activate the auxiliary functions via
> the ioctls. The sysfs interface has also been expanded so that the pin
> configuration can be programmed using shell scripts.

A few general questions / thoughts:

What are the n_ext_ts and n_per_out supposed to be set to now? The
number of pins configured for the relevant function or the number of
channels that are available for the function?

The implementation is limited to a single function for each pin - the
dp83640 supports an ext_ts and several periodic outputs on the same pin,
but I do not see that many real-world uses. 

I have done a few short run-time tests, and so far everything is working
as expected.

Stefan

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins.
  2014-03-08 19:42 ` [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins Richard Cochran
@ 2014-03-10 12:53     ` Sørensen, Stefan
  2014-03-11  7:58   ` Christian Riesch
  1 sibling, 0 replies; 23+ messages in thread
From: Sørensen, Stefan @ 2014-03-10 12:53 UTC (permalink / raw)
  To: richardcochran; +Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1994 bytes --]

On Sat, 2014-03-08 at 20:42 +0100, Richard Cochran wrote:

>+int ptp_setpin(struct ptp_clock *ptp, unsigned int pin,
>+               enum ptp_pin_function func, unsigned int chan)

>From the name I would think that this would set the state of the pin.
Rename to ptp_set_pinfunc?

> +int ptp_find_pin(struct ptp_clock *ptp,
> +		 enum ptp_pin_function func, unsigned int chan)
> +{
> +	struct ptp_pin_desc *pin = NULL;
> +	int i;
> +
> +	mutex_lock(&ptp->pincfg_mux);
> +	for (i = 0; i < ptp->info->n_pins; i++) {
> +		if (ptp->info->pin_config[i].func == func &&
> +		    ptp->info->pin_config[i].chan == chan) {
> +			pin = &ptp->info->pin_config[i];
> +			break;
> +		}
> +	}
> +	mutex_unlock(&ptp->pincfg_mux);
> +
> +	return pin ? pin - ptp->info->pin_config : -1;
> +}

Maybe replace 'pin - ptp->info->pin_config' with 'i'?

> +++ b/drivers/ptp/ptp_private.h
> @@ -48,6 +48,7 @@ struct ptp_clock {
>  	long dialed_frequency; /* remembers the frequency adjustment */
>  	struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
>  	struct mutex tsevq_mux; /* one process at a time reading the fifo */
> +	struct mutex pincfg_mux; /* protect concurrent info->pin_config access */

Line over 80 chars. 

> + * @setpin:   Confirm that a pin can perform a given function. The PTP
> + *            Hardware Clock subsystem maintains the 'pin_config'
> + *            array on behalf of the drivers, but the PHC subsystem
> + *            assumes that every pin can perform every function. This
> + *            hook gives drivers a way of telling the core about
> + *            limitations on specific pins. This function must return
> + *            zero if the function can be assigned to this pin, and
> + *            nonzero otherwise.

The function does not actually set the pin. Rename to verify_pinfunc?

Stefan
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins.
@ 2014-03-10 12:53     ` Sørensen, Stefan
  0 siblings, 0 replies; 23+ messages in thread
From: Sørensen, Stefan @ 2014-03-10 12:53 UTC (permalink / raw)
  To: richardcochran; +Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

On Sat, 2014-03-08 at 20:42 +0100, Richard Cochran wrote:

>+int ptp_setpin(struct ptp_clock *ptp, unsigned int pin,
>+               enum ptp_pin_function func, unsigned int chan)

From the name I would think that this would set the state of the pin.
Rename to ptp_set_pinfunc?

> +int ptp_find_pin(struct ptp_clock *ptp,
> +		 enum ptp_pin_function func, unsigned int chan)
> +{
> +	struct ptp_pin_desc *pin = NULL;
> +	int i;
> +
> +	mutex_lock(&ptp->pincfg_mux);
> +	for (i = 0; i < ptp->info->n_pins; i++) {
> +		if (ptp->info->pin_config[i].func == func &&
> +		    ptp->info->pin_config[i].chan == chan) {
> +			pin = &ptp->info->pin_config[i];
> +			break;
> +		}
> +	}
> +	mutex_unlock(&ptp->pincfg_mux);
> +
> +	return pin ? pin - ptp->info->pin_config : -1;
> +}

Maybe replace 'pin - ptp->info->pin_config' with 'i'?

> +++ b/drivers/ptp/ptp_private.h
> @@ -48,6 +48,7 @@ struct ptp_clock {
>  	long dialed_frequency; /* remembers the frequency adjustment */
>  	struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
>  	struct mutex tsevq_mux; /* one process at a time reading the fifo */
> +	struct mutex pincfg_mux; /* protect concurrent info->pin_config access */

Line over 80 chars. 

> + * @setpin:   Confirm that a pin can perform a given function. The PTP
> + *            Hardware Clock subsystem maintains the 'pin_config'
> + *            array on behalf of the drivers, but the PHC subsystem
> + *            assumes that every pin can perform every function. This
> + *            hook gives drivers a way of telling the core about
> + *            limitations on specific pins. This function must return
> + *            zero if the function can be assigned to this pin, and
> + *            nonzero otherwise.

The function does not actually set the pin. Rename to verify_pinfunc?

Stefan

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins.
  2014-03-10 12:53     ` Sørensen, Stefan
  (?)
@ 2014-03-10 13:32     ` Richard Cochran
  -1 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-10 13:32 UTC (permalink / raw)
  To: Sørensen, Stefan
  Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

On Mon, Mar 10, 2014 at 12:53:09PM +0000, Sørensen, Stefan wrote:
> On Sat, 2014-03-08 at 20:42 +0100, Richard Cochran wrote:

> > +int ptp_find_pin(struct ptp_clock *ptp,
> > +		 enum ptp_pin_function func, unsigned int chan)
> > +{
> > +	struct ptp_pin_desc *pin = NULL;
> > +	int i;
> > +
> > +	mutex_lock(&ptp->pincfg_mux);
> > +	for (i = 0; i < ptp->info->n_pins; i++) {
> > +		if (ptp->info->pin_config[i].func == func &&
> > +		    ptp->info->pin_config[i].chan == chan) {
> > +			pin = &ptp->info->pin_config[i];
> > +			break;
> > +		}
> > +	}
> > +	mutex_unlock(&ptp->pincfg_mux);
> > +
> > +	return pin ? pin - ptp->info->pin_config : -1;
> > +}
> 
> Maybe replace 'pin - ptp->info->pin_config' with 'i'?

Yes, of course.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-10 12:52   ` Sørensen, Stefan
  (?)
@ 2014-03-10 13:42   ` Richard Cochran
  2014-03-12  6:58     ` Christian Riesch
  -1 siblings, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2014-03-10 13:42 UTC (permalink / raw)
  To: Sørensen, Stefan
  Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

On Mon, Mar 10, 2014 at 12:52:57PM +0000, Sørensen, Stefan wrote:
> 
> What are the n_ext_ts and n_per_out supposed to be set to now? The
> number of pins configured for the relevant function or the number of
> channels that are available for the function?

They are the number of available functions. This is not necessarily the
same as the number of pins. Many chips have more functions than pins.

> The implementation is limited to a single function for each pin - the
> dp83640 supports an ext_ts and several periodic outputs on the same pin,
> but I do not see that many real-world uses. 

Yes, it does support different functions on a single pin, but not at
the same time.  You have to choose what function you want on each pin,
and that is what the new ioctl lets you do.

I did not change the n_per_out in this series, but once this basic
support gets merged, then you will be able to increase n_per_out for
the dp83640 with little extra effort.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-10 12:52   ` Sørensen, Stefan
  (?)
  (?)
@ 2014-03-10 14:05   ` Richard Cochran
  -1 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-10 14:05 UTC (permalink / raw)
  To: Sørensen, Stefan
  Cc: netdev, linux-kernel, bhutchings, christian.riesch, davem

On Mon, Mar 10, 2014 at 12:52:57PM +0000, Sørensen, Stefan wrote:
> The implementation is limited to a single function for each pin - the
> dp83640 supports an ext_ts and several periodic outputs on the same pin,
> but I do not see that many real-world uses. 

So the main use case is to allow users to configure the auxiliary
functions according to their needs. This series provides this without
relying on DT, ACPI, etc. The sysfs control lets you put this into a
boot script, for example.

In addition, there are also less common use cases for re-configuring
pins at run time. One use would be to switch from a PPS output to a
time stamping input during automated PTP testing.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins.
  2014-03-08 19:42 ` [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins Richard Cochran
  2014-03-10 12:53     ` Sørensen, Stefan
@ 2014-03-11  7:58   ` Christian Riesch
  2014-03-11 10:08     ` Richard Cochran
  1 sibling, 1 reply; 23+ messages in thread
From: Christian Riesch @ 2014-03-11  7:58 UTC (permalink / raw)
  To: Richard Cochran, netdev
  Cc: linux-kernel, Ben Hutchings, David Miller, Stefan Sørensen

Hi Richard,

--On March 08, 2014 20:42 +0100 Richard Cochran <richardcochran@gmail.com> 
wrote:

> This patch adds a pair of new ioctls to the PTP Hardware Clock device
> interface. Using the ioctls, user space programs can query each pin to
> find out its current function and also reprogram a different function
> if desired.
>
> Signed-off-by: Richard Cochran <richardcochran@gmail.com>
> ---
>  drivers/ptp/ptp_chardev.c        |  133
> +++++++++++++++++++++++++++++++++++++-  drivers/ptp/ptp_clock.c
> |   23 +++++++
>  drivers/ptp/ptp_private.h        |    4 ++
>  include/linux/ptp_clock_kernel.h |   33 ++++++++++
>  include/uapi/linux/ptp_clock.h   |   39 ++++++++++-
>  5 files changed, 230 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
> index 34a0c60..dc13d1e 100644
> --- a/drivers/ptp/ptp_chardev.c
> +++ b/drivers/ptp/ptp_chardev.c
[...]
> +int ptp_setpin(struct ptp_clock *ptp, unsigned int pin,
> +	       enum ptp_pin_function func, unsigned int chan)
> +{
> +	struct ptp_clock_info *info = ptp->info;
> +	struct ptp_pin_desc *pin1 = NULL, *pin2 = &info->pin_config[pin];
> +	unsigned int i;
> +
> +	/* Check to see if any other pin previously had this function. */
> +	if (mutex_lock_interruptible(&ptp->pincfg_mux))
> +		return -ERESTARTSYS;
> +	for (i = 0; i < info->n_pins; i++) {
> +		if (info->pin_config[i].func == func &&
> +		    info->pin_config[i].chan == chan) {
> +			pin1 = &info->pin_config[i];
> +			break;
> +		}
> +	}
> +	mutex_unlock(&ptp->pincfg_mux);
> +	if (pin1 && i == pin)
> +		return 0;
> +
> +	/* Check the desired function and channel. */
> +	switch (func) {
> +	case PTP_PF_NONE:
> +		break;
> +	case PTP_PF_EXTTS:
> +		if (chan >= info->n_ext_ts)
> +			return -EINVAL;
> +		break;
> +	case PTP_PF_PEROUT:
> +		if (chan >= info->n_per_out)
> +			return -EINVAL;
> +		break;
> +	case PTP_PF_PHYSYNC:
> +		pr_err("sorry, cannot reassign the calibration pin\n");
> +		return -EINVAL;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (pin1 && pin1->func == PTP_PF_PHYSYNC) {
> +		pr_err("sorry, cannot reprogram the calibration pin\n");
> +		return -EINVAL;

            ^^^^
Will this ever happen? pin1 && pin1->func == PTP_PF_PHYSYNC means that func 
== PTP_PF_PHYSYNC, but in this case you already return -EINVAL a few lines 
above.

Christian


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins.
  2014-03-11  7:58   ` Christian Riesch
@ 2014-03-11 10:08     ` Richard Cochran
  0 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-11 10:08 UTC (permalink / raw)
  To: Christian Riesch
  Cc: netdev, linux-kernel, Ben Hutchings, David Miller, Stefan Sørensen

On Tue, Mar 11, 2014 at 08:58:45AM +0100, Christian Riesch wrote:
> >+	if (pin1 && pin1->func == PTP_PF_PHYSYNC) {
> >+		pr_err("sorry, cannot reprogram the calibration pin\n");
> >+		return -EINVAL;
> 
>            ^^^^
> Will this ever happen? pin1 && pin1->func == PTP_PF_PHYSYNC means
> that func == PTP_PF_PHYSYNC, but in this case you already return
> -EINVAL a few lines above.

This a bug. I really meant to test (pin2->func == PTP_PF_PHYSYNC) to
prevent clobbering the calibration function with some other function.
I'll fix it for v2.

Thanks,
Richard


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-10 13:42   ` Richard Cochran
@ 2014-03-12  6:58     ` Christian Riesch
  2014-03-12 14:22       ` Richard Cochran
  0 siblings, 1 reply; 23+ messages in thread
From: Christian Riesch @ 2014-03-12  6:58 UTC (permalink / raw)
  To: Richard Cochran, Sørensen,; +Cc: netdev, linux-kernel, bhutchings, davem

Hi Richard,

--On March 10, 2014 14:42 +0100 Richard Cochran <richardcochran@gmail.com> 
wrote:

> On Mon, Mar 10, 2014 at 12:52:57PM +0000, Sørensen, Stefan wrote:
>>
>> What are the n_ext_ts and n_per_out supposed to be set to now? The
>> number of pins configured for the relevant function or the number of
>> channels that are available for the function?
>
> They are the number of available functions. This is not necessarily the
> same as the number of pins. Many chips have more functions than pins.
>
>> The implementation is limited to a single function for each pin - the
>> dp83640 supports an ext_ts and several periodic outputs on the same pin,
>> but I do not see that many real-world uses.
>
> Yes, it does support different functions on a single pin, but not at
> the same time.  You have to choose what function you want on each pin,
> and that is what the new ioctl lets you do.
>
> I did not change the n_per_out in this series,

Why not? I think it would be a good idea to set both n_ext_ts and n_per_out 
to the correct value right from the start (8, right?).
Christian

> but once this basic
> support gets merged, then you will be able to increase n_per_out for
> the dp83640 with little extra effort.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
                   ` (9 preceding siblings ...)
  2014-03-10 12:52   ` Sørensen, Stefan
@ 2014-03-12  8:21 ` Christian Riesch
  2014-03-12 14:46   ` Richard Cochran
  10 siblings, 1 reply; 23+ messages in thread
From: Christian Riesch @ 2014-03-12  8:21 UTC (permalink / raw)
  To: Richard Cochran, netdev
  Cc: linux-kernel, Ben Hutchings, David Miller, Stefan Sørensen

Hi Richard,

--On March 08, 2014 20:42 +0100 Richard Cochran <richardcochran@gmail.com> 
wrote:

> This patch series introduces a way of changing the auxiliary PTP
> Hardware Clock functions (periodic output signals and time stamping
> external signals) at run time. In the past on the netdev list, we have
> discussed other ways to handle this, such as module parameters and
> ethtool. This series implements a new PHC ioctl because that is the
> most natural way. Users already activate the auxiliary functions via
> the ioctls. The sysfs interface has also been expanded so that the pin
> configuration can be programmed using shell scripts.

I did a few tests on one of my boards, everything works so far! Thanks for 
the patchset, I like it!

> The first patch adds the new ioctls. The PHC subsystem does most of
> the work of maintaining the function-to-pin mapping. Drivers will only
> need to allocate and initialize a pin configuration table and also
> provide a new method that validates a particular assignment.
>
> Patches 5 and 6 just clean up a couple of issues in the phyter driver,
> and the remaining patches actually hook the phyter's pins into the new
> system.
>
> Comments and questions are most welcome.

Do you think it is possible to extend this in the future, e.g. for 
selecting the polarity of periodic output signals or for time stamping of 
external signals (rising edge/falling edge), or duty cycles of the periodic 
signal other than 50%? How could this be done? Using the reserved fields in 
struct ptp_pin_desc?

Do you think the concept allows an extension for single pulse output, e.g. 
programming a pin to output a single pulse at a given time, as supported by 
the DP83640?

If several DP83640 are connected together with the calibration function, 
only the GPIOs of the master device can be used, right? I guess this could 
also be extended in the future to use the GPIOs of all DP83640, right? Or 
do you see a problem with your concept here?

Best regards,
Christian


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-12  6:58     ` Christian Riesch
@ 2014-03-12 14:22       ` Richard Cochran
  0 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-12 14:22 UTC (permalink / raw)
  To: Christian Riesch; +Cc: Sørensen,, netdev, linux-kernel, bhutchings, davem

On Wed, Mar 12, 2014 at 07:58:37AM +0100, Christian Riesch wrote:
> >I did not change the n_per_out in this series,
> 
> Why not? I think it would be a good idea to set both n_ext_ts and
> n_per_out to the correct value right from the start (8, right?).
> Christian

Yes, it is a good idea, but it is a little extra work, especially
testing it. Channels 0 and 1 must be programmed differently, IIRC.

Right now, I am focusing on:

1. getting the new ioctl interface right
2. making it work for the phyter while keeping the module params.

After that, as I said before:
 
> >but once this basic
> >support gets merged, then you will be able to increase n_per_out for
> >the dp83640 with little extra effort.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next v1 0/9] ptp: dynamic pin control
  2014-03-12  8:21 ` Christian Riesch
@ 2014-03-12 14:46   ` Richard Cochran
  0 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2014-03-12 14:46 UTC (permalink / raw)
  To: Christian Riesch
  Cc: netdev, linux-kernel, Ben Hutchings, David Miller, Stefan Sørensen

On Wed, Mar 12, 2014 at 09:21:00AM +0100, Christian Riesch wrote:
> 
> Do you think it is possible to extend this in the future, e.g. for
> selecting the polarity of periodic output signals  or for time
> stamping of external signals (rising edge/falling edge), or duty
> cycles of the periodic signal other than 50%? How could this be
> done? Using the reserved fields in struct ptp_pin_desc?

Yes, this can be done, but this relates to the ptp_xyz_request ioctls
and not to the ptp_pin_desc. You asked for three things. Here is how
one might implement them.

1. selecting the polarity of periodic output signals

   ptp_perout_request.flags (new flag)

2. time stamping of external signals (rising edge/falling edge)

   This is already supported in the ptp_extts_request.flags field.
   The drivers just need to implement it.

3. duty cycles of the periodic signal other than 50%?

   Maybe using one of the ptp_perout_request.rsv fields.
 
> Do you think the concept allows an extension for single pulse
> output, e.g. programming a pin to output a single pulse at a given
> time, as supported by the DP83640?

Yes, either a new ioctl or maybe ptp_perout_request.flags with a
ONE-SHOT flag.

> If several DP83640 are connected together with the calibration
> function, only the GPIOs of the master device can be used, right? I
> guess this could also be extended in the future to use the GPIOs of
> all DP83640, right? Or do you see a problem with your concept here?

If the driver would combine all of the pins and functions over all the
devices, that would be best. I think it would be tricky to implement,
since the driver probe() function doesn't know how many more phyters
to expect.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2014-03-12 14:46 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-08 19:42 [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 1/9] ptp: introduce programmable pins Richard Cochran
2014-03-10 12:53   ` Sørensen, Stefan
2014-03-10 12:53     ` Sørensen, Stefan
2014-03-10 13:32     ` Richard Cochran
2014-03-11  7:58   ` Christian Riesch
2014-03-11 10:08     ` Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 2/9] ptp: add the pin GET/SETFUNC ioctls to the testptp program Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 3/9] ptp: expose the programmable pins via sysfs Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 4/9] ptp: drivers: set the number of programmable pins Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 5/9] dp83640: trivial fixes Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 6/9] dp83640: correct the periodic output frequency Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 7/9] dp83640: implement programmable pin functions Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 8/9] dp83640: let external input pins from the module parameters be defaults Richard Cochran
2014-03-08 19:42 ` [PATCH RFC net-next v1 9/9] dp83640: let the periodic pin from the module parameter be a default Richard Cochran
2014-03-10 12:52 ` [PATCH RFC net-next v1 0/9] ptp: dynamic pin control Sørensen, Stefan
2014-03-10 12:52   ` Sørensen, Stefan
2014-03-10 13:42   ` Richard Cochran
2014-03-12  6:58     ` Christian Riesch
2014-03-12 14:22       ` Richard Cochran
2014-03-10 14:05   ` Richard Cochran
2014-03-12  8:21 ` Christian Riesch
2014-03-12 14:46   ` Richard Cochran

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.