From d94ba80ebbea17f036cecb104398fbcd788aa742 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 22 Apr 2011 12:03:08 +0200 Subject: ptp: Added a brand new class driver for ptp clocks. This patch adds an infrastructure for hardware clocks that implement IEEE 1588, the Precision Time Protocol (PTP). A class driver offers a registration method to particular hardware clock drivers. Each clock is presented as a standard POSIX clock. The ancillary clock features are exposed in two different ways, via the sysfs and by a character device. Signed-off-by: Richard Cochran Acked-by: Arnd Bergmann Acked-by: David S. Miller Signed-off-by: John Stultz --- include/linux/Kbuild | 1 + include/linux/ptp_classify.h | 7 ++ include/linux/ptp_clock.h | 84 +++++++++++++++++++++++ include/linux/ptp_clock_kernel.h | 139 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 include/linux/ptp_clock.h create mode 100644 include/linux/ptp_clock_kernel.h (limited to 'include') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 75cf611641e6..4585836ba664 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -302,6 +302,7 @@ header-y += ppp-comp.h header-y += ppp_defs.h header-y += pps.h header-y += prctl.h +header-y += ptp_clock.h header-y += ptrace.h header-y += qnx4_fs.h header-y += qnxtypes.h diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h index 943a85ab0020..e07e2742a865 100644 --- a/include/linux/ptp_classify.h +++ b/include/linux/ptp_classify.h @@ -25,6 +25,7 @@ #include #include +#include #include #ifdef __KERNEL__ #include @@ -58,6 +59,12 @@ #define OFF_NEXT 6 #define OFF_UDP_DST 2 +#define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */ +#define OFF_PTP_SEQUENCE_ID 30 +#define OFF_PTP_CONTROL 32 /* PTPv1 only */ + +#define IPV4_HLEN(data) (((struct iphdr *)(data + OFF_IHL))->ihl << 2) + #define IP6_HLEN 40 #define UDP_HLEN 8 diff --git a/include/linux/ptp_clock.h b/include/linux/ptp_clock.h new file mode 100644 index 000000000000..94e981f810a2 --- /dev/null +++ b/include/linux/ptp_clock.h @@ -0,0 +1,84 @@ +/* + * PTP 1588 clock support - user space interface + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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 _PTP_CLOCK_H_ +#define _PTP_CLOCK_H_ + +#include +#include + +/* PTP_xxx bits, for the flags field within the request structures. */ +#define PTP_ENABLE_FEATURE (1<<0) +#define PTP_RISING_EDGE (1<<1) +#define PTP_FALLING_EDGE (1<<2) + +/* + * struct ptp_clock_time - represents a time value + * + * The sign of the seconds field applies to the whole value. The + * nanoseconds field is always unsigned. The reserved field is + * included for sub-nanosecond resolution, should the demand for + * this ever appear. + * + */ +struct ptp_clock_time { + __s64 sec; /* seconds */ + __u32 nsec; /* nanoseconds */ + __u32 reserved; +}; + +struct ptp_clock_caps { + int max_adj; /* Maximum frequency adjustment in parts per billon. */ + int n_alarm; /* Number of programmable alarms. */ + 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. */ +}; + +struct ptp_extts_request { + unsigned int index; /* Which channel to configure. */ + unsigned int flags; /* Bit field for PTP_xxx flags. */ + unsigned int rsv[2]; /* Reserved for future use. */ +}; + +struct ptp_perout_request { + struct ptp_clock_time start; /* Absolute start time. */ + struct ptp_clock_time period; /* Desired period, zero means disable. */ + unsigned int index; /* Which channel to configure. */ + unsigned int flags; /* Reserved for future use. */ + unsigned int rsv[4]; /* Reserved for future use. */ +}; + +#define PTP_CLK_MAGIC '=' + +#define PTP_CLOCK_GETCAPS _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps) +#define PTP_EXTTS_REQUEST _IOW(PTP_CLK_MAGIC, 2, struct ptp_extts_request) +#define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request) +#define PTP_ENABLE_PPS _IOW(PTP_CLK_MAGIC, 4, int) + +struct ptp_extts_event { + struct ptp_clock_time t; /* Time event occured. */ + unsigned int index; /* Which channel produced the event. */ + unsigned int flags; /* Reserved for future use. */ + unsigned int rsv[2]; /* Reserved for future use. */ +}; + +#endif diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h new file mode 100644 index 000000000000..dd2e44fba63e --- /dev/null +++ b/include/linux/ptp_clock_kernel.h @@ -0,0 +1,139 @@ +/* + * PTP 1588 clock support + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * 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 _PTP_CLOCK_KERNEL_H_ +#define _PTP_CLOCK_KERNEL_H_ + +#include + + +struct ptp_clock_request { + enum { + PTP_CLK_REQ_EXTTS, + PTP_CLK_REQ_PEROUT, + PTP_CLK_REQ_PPS, + } type; + union { + struct ptp_extts_request extts; + struct ptp_perout_request perout; + }; +}; + +/** + * struct ptp_clock_info - decribes a PTP hardware clock + * + * @owner: The clock driver should set to THIS_MODULE. + * @name: A short name to identify the clock. + * @max_adj: The maximum possible frequency adjustment, in parts per billon. + * @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. + * @pps: Indicates whether the clock supports a PPS callback. + * + * clock operations + * + * @adjfreq: Adjusts the frequency of the hardware clock. + * parameter delta: Desired period change in parts per billion. + * + * @adjtime: Shifts the time of the hardware clock. + * parameter delta: Desired change in nanoseconds. + * + * @gettime: Reads the current time from the hardware clock. + * parameter ts: Holds the result. + * + * @settime: Set the current time on the hardware clock. + * parameter ts: Time value to set. + * + * @enable: Request driver to enable or disable an ancillary feature. + * parameter request: Desired resource to enable or disable. + * parameter on: Caller passes one to enable or zero to disable. + * + * Drivers should embed their ptp_clock_info within a private + * structure, obtaining a reference to it using container_of(). + * + * The callbacks must all return zero on success, non-zero otherwise. + */ + +struct ptp_clock_info { + struct module *owner; + char name[16]; + s32 max_adj; + int n_alarm; + int n_ext_ts; + int n_per_out; + int pps; + 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); +}; + +struct ptp_clock; + +/** + * ptp_clock_register() - register a PTP hardware clock driver + * + * @info: Structure describing the new clock. + */ + +extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info); + +/** + * ptp_clock_unregister() - unregister a PTP hardware clock driver + * + * @ptp: The clock to remove from service. + */ + +extern int ptp_clock_unregister(struct ptp_clock *ptp); + + +enum ptp_clock_events { + PTP_CLOCK_ALARM, + PTP_CLOCK_EXTTS, + PTP_CLOCK_PPS, +}; + +/** + * struct ptp_clock_event - decribes a PTP hardware clock event + * + * @type: One of the ptp_clock_events enumeration values. + * @index: Identifies the source of the event. + * @timestamp: When the event occured. + */ + +struct ptp_clock_event { + int type; + int index; + u64 timestamp; +}; + +/** + * ptp_clock_event() - notify the PTP layer about an event + * + * @ptp: The clock obtained from ptp_clock_register(). + * @event: Message structure describing the event. + */ + +extern void ptp_clock_event(struct ptp_clock *ptp, + struct ptp_clock_event *event); + +#endif -- cgit v1.2.3-59-g8ed1b